This commit is contained in:
Lukas Hejtmanek
2010-02-05 16:17:33 +01:00
parent 00597883d5
commit f0893e122e
60 changed files with 14677 additions and 14185 deletions

View File

@@ -62,9 +62,7 @@
#undef DEBUG
#undef DEBUG_MEM
@BOTTOM@
@ BOTTOM @
#ifndef WORDS_BIGENDIAN
#define WORDS_SMALLENDIAN
#endif

View File

@@ -54,419 +54,415 @@
#include "audio/audio.h"
#include "portaudio.h"
const int interleaved = 1; // whether we use interleaved or non-interleaved input. ideally should get rid of this and use always non-interleaved mode...but there are some troubles with nonInterlevad support in MaxOSX(probably portaudio bug)
const int interleaved = 1; // whether we use interleaved or non-interleaved input. ideally should get rid of this and use always non-interleaved mode...but there are some troubles with nonInterlevad support in MaxOSX(probably portaudio bug)
PaStream *stream; // portaudio stream defined globally
PaStream *stream; // portaudio stream defined globally
void audio_wait_for_reading(void)
{
unsigned int x;
// printf("%d..\n", Pa_GetStreamWriteAvailable(stream));
while((x = Pa_GetStreamReadAvailable(stream)) < audio_samples_per_frame*2)
printf("%d..",x);
unsigned int x;
// printf("%d..\n", Pa_GetStreamWriteAvailable(stream));
while ((x =
Pa_GetStreamReadAvailable(stream)) <
audio_samples_per_frame * 2)
printf("%d..", x);
printf("ok, now:%d\n", x);
printf("ok, now:%d\n", x);
}
int audio_init(int output_device, int input_device)
{
/*
* so far we only work with portaudio
* might get more complicated later..(jack?)
*/
/*
* so far we only work with portaudio
* might get more complicated later..(jack?)
*/
printf("Initializing portaudio..\n");
printf("Initializing portaudio..\n");
PaError error;
error = Pa_Initialize();
if(error != paNoError)
{
printf("error initializing portaudio\n");
printf("\tPortAudio error: %s\n", Pa_GetErrorText( error ) );
return -1;
}
PaError error;
printf("Using PortAudio version: %s\n", Pa_GetVersionText());
error = Pa_Initialize();
if (error != paNoError) {
printf("error initializing portaudio\n");
printf("\tPortAudio error: %s\n", Pa_GetErrorText(error));
return -1;
}
PaStreamParameters inputParameters, outputParameters;
printf("Using PortAudio version: %s\n", Pa_GetVersionText());
// default device
if(output_device == -1)
{
printf("\nUsing default output audio device:");
fflush(stdout);
print_device_info(Pa_GetDefaultOutputDevice());
printf("\n");
outputParameters.device = Pa_GetDefaultOutputDevice();
}
else
if(output_device >= 0)
{
printf("\nUsing output audio device:");
print_device_info(output_device);
printf("\n");
outputParameters.device = output_device;
}
// default device
if(input_device == -1)
{
printf("Using default input audio device");
print_device_info(Pa_GetDefaultInputDevice());
printf("\n");
inputParameters.device = Pa_GetDefaultInputDevice();
}
else
if(input_device >= 0)
{
printf("Using input audio device:");
print_device_info(input_device);
printf("\n");
inputParameters.device = input_device;
}
PaStreamParameters inputParameters, outputParameters;
if(input_device != -2)
{
inputParameters.channelCount = 1;
inputParameters.sampleFormat = paInt24;
if(!interleaved)
inputParameters.sampleFormat |= paNonInterleaved;
// default device
if (output_device == -1) {
printf("\nUsing default output audio device:");
fflush(stdout);
print_device_info(Pa_GetDefaultOutputDevice());
printf("\n");
outputParameters.device = Pa_GetDefaultOutputDevice();
} else if (output_device >= 0) {
printf("\nUsing output audio device:");
print_device_info(output_device);
printf("\n");
outputParameters.device = output_device;
}
// default device
if (input_device == -1) {
printf("Using default input audio device");
print_device_info(Pa_GetDefaultInputDevice());
printf("\n");
inputParameters.device = Pa_GetDefaultInputDevice();
} else if (input_device >= 0) {
printf("Using input audio device:");
print_device_info(input_device);
printf("\n");
inputParameters.device = input_device;
}
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultHighInputLatency ;
if (input_device != -2) {
inputParameters.channelCount = 1;
inputParameters.sampleFormat = paInt24;
if (!interleaved)
inputParameters.sampleFormat |= paNonInterleaved;
inputParameters.hostApiSpecificStreamInfo = NULL;
}
inputParameters.suggestedLatency =
Pa_GetDeviceInfo(inputParameters.device)->
defaultHighInputLatency;
if(output_device != -2)
{
outputParameters.channelCount = 1; // output channels
outputParameters.sampleFormat = paInt24;
if(!interleaved)
outputParameters.sampleFormat |= paNonInterleaved;
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
}
inputParameters.hostApiSpecificStreamInfo = NULL;
}
if (output_device != -2) {
outputParameters.channelCount = 1; // output channels
outputParameters.sampleFormat = paInt24;
if (!interleaved)
outputParameters.sampleFormat |= paNonInterleaved;
outputParameters.suggestedLatency =
Pa_GetDeviceInfo(outputParameters.device)->
defaultHighOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
}
error = Pa_OpenStream( &stream,
(input_device == -2)?NULL:&inputParameters,
(output_device == -2)?NULL:&outputParameters,
48000,
audio_samples_per_frame, // frames per buffer // TODO decide on the amount
paNoFlag,
NULL, // callback function; NULL, because we use blocking functions
NULL // user data - none, because we use blocking functions
);
if(error != paNoError)
{
printf("Error opening audio stream\n");
printf("\tPortAudio error: %s\n", Pa_GetErrorText( error ) );
return -1;
}
error = Pa_OpenStream(&stream, (input_device == -2) ? NULL : &inputParameters, (output_device == -2) ? NULL : &outputParameters, 48000, audio_samples_per_frame, // frames per buffer // TODO decide on the amount
paNoFlag, NULL, // callback function; NULL, because we use blocking functions
NULL // user data - none, because we use blocking functions
);
if (error != paNoError) {
printf("Error opening audio stream\n");
printf("\tPortAudio error: %s\n", Pa_GetErrorText(error));
return -1;
}
return 0;
return 0;
}
int audio_close() // closes and frees all audio resources
int audio_close() // closes and frees all audio resources
{
Pa_StopStream(stream); // may not be necessary
Pa_Terminate();
Pa_StopStream(stream); // may not be necessary
Pa_Terminate();
}
int audio_buffer_full(const audio_frame_buffer *buffer)
int audio_buffer_full(const audio_frame_buffer * buffer)
{
return (buffer->occupation == buffer->total_number_of_frames);
return (buffer->occupation == buffer->total_number_of_frames);
}
int audio_buffer_empty(audio_frame_buffer *buffer)
int audio_buffer_empty(audio_frame_buffer * buffer)
{
return (buffer->occupation == 0);
return (buffer->occupation == 0);
}
int init_audio_frame_buffer(audio_frame_buffer *buffer, int frames_per_buffer)
int init_audio_frame_buffer(audio_frame_buffer * buffer, int frames_per_buffer)
{
assert(frames_per_buffer > 0);
assert(frames_per_buffer > 0);
int i;
if((buffer->audio_frames = (audio_frame**) malloc(frames_per_buffer * sizeof(audio_frame*))) == NULL)
{
printf("Error allocating memory for audio buffer!\n");
return 1;
}
int i;
if ((buffer->audio_frames =
(audio_frame **) malloc(frames_per_buffer *
sizeof(audio_frame *))) == NULL) {
printf("Error allocating memory for audio buffer!\n");
return 1;
}
for(i = 0; i < frames_per_buffer; i++)
{
buffer->audio_frames[i] = (audio_frame*)malloc(sizeof(audio_frame)); // FIXME: all audio frames should be allocated with one malloc call...
init_audio_frame(buffer->audio_frames[i], audio_samples_per_frame);
}
for (i = 0; i < frames_per_buffer; i++) {
buffer->audio_frames[i] = (audio_frame *) malloc(sizeof(audio_frame)); // FIXME: all audio frames should be allocated with one malloc call...
init_audio_frame(buffer->audio_frames[i],
audio_samples_per_frame);
}
buffer->total_number_of_frames = frames_per_buffer;
buffer->start = 0;
buffer->end = 0;
buffer->occupation = 0;
return 0;
buffer->total_number_of_frames = frames_per_buffer;
buffer->start = 0;
buffer->end = 0;
buffer->occupation = 0;
return 0;
}
// write buffer to output device
int audio_write(const audio_frame *buffer)
int audio_write(const audio_frame * buffer)
{
PaError error;
if(interleaved)
{
audio_frame_to_interleaved_buffer(buffer->tmp_buffer, buffer, 1);
error = Pa_WriteStream(stream, buffer->tmp_buffer, buffer->samples_per_channel);
}
else
error = Pa_WriteStream(stream, buffer->channels, buffer->samples_per_channel);
PaError error;
if (interleaved) {
audio_frame_to_interleaved_buffer(buffer->tmp_buffer, buffer,
1);
error =
Pa_WriteStream(stream, buffer->tmp_buffer,
buffer->samples_per_channel);
} else
error =
Pa_WriteStream(stream, buffer->channels,
buffer->samples_per_channel);
if(error != paNoError)
{
printf("Pa write stream error:%s\n", Pa_GetErrorText(error));
return 1;
}
if (error != paNoError) {
printf("Pa write stream error:%s\n", Pa_GetErrorText(error));
return 1;
}
return 0;
return 0;
}
// get first empty frame, bud don't consider it as being used
audio_frame* audio_buffer_get_empty_frame(audio_frame_buffer *buffer)
audio_frame *audio_buffer_get_empty_frame(audio_frame_buffer * buffer)
{
// if we are full, we return NULL
if(audio_buffer_full(buffer))
return NULL;
// if we are full, we return NULL
if (audio_buffer_full(buffer))
return NULL;
audio_frame *frame = buffer->audio_frames[buffer->end];
return frame;
audio_frame *frame = buffer->audio_frames[buffer->end];
return frame;
}
void print_available_devices(void)
{
int numDevices;
int numDevices;
PaError error;
error = Pa_Initialize();
if(error != paNoError)
{
printf("error initializing portaudio\n");
printf("\tPortAudio error: %s\n", Pa_GetErrorText( error ) );
return;
}
PaError error;
numDevices = Pa_GetDeviceCount();
if( numDevices < 0)
{
printf("Error getting portaudio devices number\n");
return;
}
if( numDevices == 0)
{
printf("There are NO available audio devices!\n");
return;
}
error = Pa_Initialize();
if (error != paNoError) {
printf("error initializing portaudio\n");
printf("\tPortAudio error: %s\n", Pa_GetErrorText(error));
return;
}
int i;
printf("Available devices(%d)\n", numDevices);
for(i = 0; i < numDevices; i++)
{
if(i == Pa_GetDefaultInputDevice())
printf("(*i) ");
if(i == Pa_GetDefaultOutputDevice())
printf("(*o)");
printf("Device %d :", i);
print_device_info(i);
printf("\n");
}
numDevices = Pa_GetDeviceCount();
if (numDevices < 0) {
printf("Error getting portaudio devices number\n");
return;
}
if (numDevices == 0) {
printf("There are NO available audio devices!\n");
return;
}
return;
int i;
printf("Available devices(%d)\n", numDevices);
for (i = 0; i < numDevices; i++) {
if (i == Pa_GetDefaultInputDevice())
printf("(*i) ");
if (i == Pa_GetDefaultOutputDevice())
printf("(*o)");
printf("Device %d :", i);
print_device_info(i);
printf("\n");
}
return;
}
void print_device_info(PaDeviceIndex device)
{
if( (device < 0) || (device >= Pa_GetDeviceCount()) )
{
printf("Requested info on non-existing device");
return;
}
const PaDeviceInfo *device_info = Pa_GetDeviceInfo(device);
printf(" %s (output channels: %d; input channels: %d)", device_info->name, device_info->maxOutputChannels, device_info->maxInputChannels);
if ((device < 0) || (device >= Pa_GetDeviceCount())) {
printf("Requested info on non-existing device");
return;
}
const PaDeviceInfo *device_info = Pa_GetDeviceInfo(device);
printf(" %s (output channels: %d; input channels: %d)",
device_info->name, device_info->maxOutputChannels,
device_info->maxInputChannels);
}
// read from input device
int audio_read(audio_frame *buffer)
int audio_read(audio_frame * buffer)
{
// here we distinguish between interleaved and noninterleved, but non interleaved version hasn't been tested yet
PaError error;
if(interleaved)
{
error = Pa_ReadStream( stream, buffer->tmp_buffer, buffer->samples_per_channel);
interleaved_buffer_to_audio_frame(buffer, buffer->tmp_buffer, 1);
}
else
{
error = Pa_ReadStream( stream, buffer->channels, buffer->samples_per_channel);
}
// here we distinguish between interleaved and noninterleved, but non interleaved version hasn't been tested yet
PaError error;
if (interleaved) {
error =
Pa_ReadStream(stream, buffer->tmp_buffer,
buffer->samples_per_channel);
interleaved_buffer_to_audio_frame(buffer, buffer->tmp_buffer,
1);
} else {
error =
Pa_ReadStream(stream, buffer->channels,
buffer->samples_per_channel);
}
if((error != paNoError) && (error != paInputOverflowed))
{
printf("Pa read stream error:%s\n", Pa_GetErrorText(error));
return 1;
}
return 0;
if ((error != paNoError) && (error != paInputOverflowed)) {
printf("Pa read stream error:%s\n", Pa_GetErrorText(error));
return 1;
}
return 0;
}
int init_audio_frame(audio_frame *buffer, unsigned int samples_per_channel)
int init_audio_frame(audio_frame * buffer, unsigned int samples_per_channel)
{
int i;
for(i = 0; i < 8; i++)
{
if((buffer->channels[i] = (char*)malloc(samples_per_channel * 3/* ~24 bit*/ )) == NULL)
{
printf("Error allocating memory for audio buffers\n");
return -1;
}
int i;
for (i = 0; i < 8; i++) {
if ((buffer->channels[i] =
(char *)malloc(samples_per_channel * 3 /* ~24 bit */ )) ==
NULL) {
printf("Error allocating memory for audio buffers\n");
return -1;
}
memset(buffer->channels[i], 0, samples_per_channel * 3);
}
buffer->samples_per_channel = samples_per_channel;
memset(buffer->channels[i], 0, samples_per_channel * 3);
}
buffer->samples_per_channel = samples_per_channel;
// the temporary buffer is large enough to store all channels
if((buffer->tmp_buffer = (char *)malloc(samples_per_channel * 3 * 8)) == NULL)
{
printf("Error allocating temporary buffer");
return -1;
}
// the temporary buffer is large enough to store all channels
if ((buffer->tmp_buffer =
(char *)malloc(samples_per_channel * 3 * 8)) == NULL) {
printf("Error allocating temporary buffer");
return -1;
}
return 0;
return 0;
}
void free_audio_frame_buffer(audio_frame_buffer *buffer)
void free_audio_frame_buffer(audio_frame_buffer * buffer)
{
int i;
for(i = 0; i < buffer->total_number_of_frames; i++)
free(buffer->audio_frames[i]);
int i;
for (i = 0; i < buffer->total_number_of_frames; i++)
free(buffer->audio_frames[i]);
free(buffer->audio_frames);
free(buffer->audio_frames);
buffer->start = buffer->end = buffer->total_number_of_frames = 0;
buffer->start = buffer->end = buffer->total_number_of_frames = 0;
}
void free_audio_frame(audio_frame *buffer)
void free_audio_frame(audio_frame * buffer)
{
int i;
for(i = 0; i < 8; i++)
free(buffer->channels[i]);
free(buffer->tmp_buffer);
int i;
for (i = 0; i < 8; i++)
free(buffer->channels[i]);
free(buffer->tmp_buffer);
}
inline
void interleaved_buffer_to_audio_frame(audio_frame *pa_buffer, const char *in_buffer, int num_channels)
void interleaved_buffer_to_audio_frame(audio_frame * pa_buffer,
const char *in_buffer,
int num_channels)
{
assert(num_channels == 1); // we only handle mono buffer for now...
assert(num_channels == 1); // we only handle mono buffer for now...
// we suppose the number of samples in in_buffer is equal to the number in pa_buffer (this should be set globally)
memcpy(pa_buffer->channels[0], in_buffer, pa_buffer->samples_per_channel * 3);
// we suppose the number of samples in in_buffer is equal to the number in pa_buffer (this should be set globally)
memcpy(pa_buffer->channels[0], in_buffer,
pa_buffer->samples_per_channel * 3);
}
inline
void network_buffer_to_audio_frame(audio_frame *pa_buffer, const char *network_buffer)
void network_buffer_to_audio_frame(audio_frame * pa_buffer,
const char *network_buffer)
{
unsigned int i;
const char *tmp_buffer = network_buffer;
for(i = 0; i < pa_buffer->samples_per_channel*8; i++)
{
int actual_channel = i % 8;
int actual_sample = i / 8;
pa_buffer->channels[actual_channel][actual_sample*3+0] = tmp_buffer[2];
pa_buffer->channels[actual_channel][actual_sample*3+1] = tmp_buffer[1];
pa_buffer->channels[actual_channel][actual_sample*3+2] = tmp_buffer[0];
unsigned int i;
const char *tmp_buffer = network_buffer;
for (i = 0; i < pa_buffer->samples_per_channel * 8; i++) {
int actual_channel = i % 8;
int actual_sample = i / 8;
tmp_buffer += 3; // we iterate over 3 byte samples..
}
pa_buffer->channels[actual_channel][actual_sample * 3 + 0] =
tmp_buffer[2];
pa_buffer->channels[actual_channel][actual_sample * 3 + 1] =
tmp_buffer[1];
pa_buffer->channels[actual_channel][actual_sample * 3 + 2] =
tmp_buffer[0];
tmp_buffer += 3; // we iterate over 3 byte samples..
}
}
int audio_ready_to_write(void)
{
return Pa_GetStreamWriteAvailable(stream);
return Pa_GetStreamWriteAvailable(stream);
}
int audio_start_stream(void)
{
PaError error;
PaError error;
error = Pa_StartStream(stream);
if(error != paNoError)
{
printf("Error starting stream:%s\n", Pa_GetErrorText(error));
printf("\tPortAudio error: %s\n", Pa_GetErrorText( error ) );
return -1;
}
error = Pa_StartStream(stream);
if (error != paNoError) {
printf("Error starting stream:%s\n", Pa_GetErrorText(error));
printf("\tPortAudio error: %s\n", Pa_GetErrorText(error));
return -1;
}
return 0;
return 0;
}
inline
void audio_frame_to_interleaved_buffer(char *in_buffer, const audio_frame *pa_buffer, int num_channels)
void audio_frame_to_interleaved_buffer(char *in_buffer,
const audio_frame * pa_buffer,
int num_channels)
{
assert(num_channels == 1);
assert(num_channels == 1);
memcpy(in_buffer, pa_buffer->channels[0], pa_buffer->samples_per_channel * 3);
memcpy(in_buffer, pa_buffer->channels[0],
pa_buffer->samples_per_channel * 3);
}
inline
void audio_frame_to_network_buffer(char *network_buffer, const audio_frame *a_buffer)
void audio_frame_to_network_buffer(char *network_buffer,
const audio_frame * a_buffer)
{
assert(!(a_buffer->samples_per_channel % 8)); // we send data in octets
assert(!(a_buffer->samples_per_channel % 8)); // we send data in octets
unsigned int i;
for(i = 0; i < a_buffer->samples_per_channel * 3; i += 3)
{
unsigned int i;
for (i = 0; i < a_buffer->samples_per_channel * 3; i += 3) {
#ifdef WORDS_BIGENDIAN
printf("Error! Big endian machines are not currenty supported by audio transfer protocol!\n");
printf
("Error! Big endian machines are not currenty supported by audio transfer protocol!\n");
#endif
int j;
for(j = 0; j < 8; j++)
{
// we need to revers the data to network byte order
network_buffer[0] = a_buffer->channels[j][i+2];
network_buffer[1] = a_buffer->channels[j][i+1];
network_buffer[2] = a_buffer->channels[j][i+0];
network_buffer += 3; // iterate over the output buffer
}
}
int j;
for (j = 0; j < 8; j++) {
// we need to revers the data to network byte order
network_buffer[0] = a_buffer->channels[j][i + 2];
network_buffer[1] = a_buffer->channels[j][i + 1];
network_buffer[2] = a_buffer->channels[j][i + 0];
network_buffer += 3; // iterate over the output buffer
}
}
}
// we return first full frame and think about it as being empty since now
audio_frame* audio_buffer_get_full_frame(audio_frame_buffer *buffer)
audio_frame *audio_buffer_get_full_frame(audio_frame_buffer * buffer)
{
if(audio_buffer_empty(buffer))
return NULL;
if (audio_buffer_empty(buffer))
return NULL;
audio_frame *frame = buffer->audio_frames[buffer->start];
audio_frame *frame = buffer->audio_frames[buffer->start];
buffer->start++;
if(buffer->start == buffer->total_number_of_frames)
buffer->start = 0;
buffer->start++;
if (buffer->start == buffer->total_number_of_frames)
buffer->start = 0;
buffer->occupation--;
return frame;
buffer->occupation--;
return frame;
}
// this should be called in case last audio_frame returned by audio_buffer_get_empty_frame should be considered full (used)
void audio_buffer_mark_last_frame_full(audio_frame_buffer *buffer)
void audio_buffer_mark_last_frame_full(audio_frame_buffer * buffer)
{
buffer->end++;
if(buffer->end == buffer->total_number_of_frames)
buffer->end = 0;
buffer->end++;
if (buffer->end == buffer->total_number_of_frames)
buffer->end = 0;
buffer->occupation++;
buffer->occupation++;
}

View File

@@ -10,23 +10,22 @@
* $Revision: 1.1 $
* $Date: 2007/11/08 09:48:59 $
*/
#include "config_unix.h"
#include "config_win32.h"
#include "bitstream.h"
typedef struct s_bitstream {
u_char *buf; /* head of bitstream */
u_char *pos; /* current byte in bitstream */
unsigned int remain; /* bits remaining */
unsigned int len; /* length of bitstream in bytes */
u_char *buf; /* head of bitstream */
u_char *pos; /* current byte in bitstream */
unsigned int remain; /* bits remaining */
unsigned int len; /* length of bitstream in bytes */
} bs;
int
bs_create(bitstream_t **ppb)
int bs_create(bitstream_t ** ppb)
{
bs *pb;
pb = (bs*) malloc(sizeof(bs));
pb = (bs *) malloc(sizeof(bs));
if (pb) {
memset(pb, 0, sizeof(bs));
*ppb = pb;
@@ -35,32 +34,25 @@ bs_create(bitstream_t **ppb)
return FALSE;
}
int
bs_destroy(bitstream_t **ppb)
int bs_destroy(bitstream_t ** ppb)
{
free(*ppb);
return TRUE;
}
int
bs_attach(bitstream_t *b,
u_char *buf,
int blen)
int bs_attach(bitstream_t * b, u_char * buf, int blen)
{
b->buf = b->pos = buf;
b->buf = b->pos = buf;
b->remain = 8;
b->len = blen;
memset(b->buf, 0, b->len);
b->len = blen;
memset(b->buf, 0, b->len);
return TRUE;
}
int
bs_put(bitstream_t *b,
u_char bits,
uint8_t nbits)
int bs_put(bitstream_t * b, u_char bits, uint8_t nbits)
{
assert(nbits != 0 && nbits <= 8);
if (b->remain == 0) {
b->pos++;
b->remain = 8;
@@ -71,19 +63,17 @@ bs_put(bitstream_t *b,
(*b->pos) |= (bits >> over);
b->pos++;
b->remain = 8 - over;
(*b->pos) = (bits << b->remain);
(*b->pos) = (bits << b->remain);
} else {
(*b->pos) |= bits << (b->remain - nbits);
b->remain -= nbits;
}
assert((unsigned int)(b->pos - b->buf) <= b->len);
return TRUE;
}
u_char
bs_get(bitstream_t *b,
uint8_t nbits)
u_char bs_get(bitstream_t * b, uint8_t nbits)
{
u_char out;
@@ -111,8 +101,7 @@ bs_get(bitstream_t *b,
return out;
}
int
bs_bytes_used(bitstream_t *b)
int bs_bytes_used(bitstream_t * b)
{
unsigned int used = (unsigned int)(b->pos - b->buf);
if (b->remain != 8) {
@@ -120,4 +109,3 @@ bs_bytes_used(bitstream_t *b)
}
return used;
}

View File

@@ -7,7 +7,7 @@
double drand48(void)
{
unsigned int x = (rand() << 16) | rand();
return ((double)x / (double)0xffffffff);
return ((double)x / (double)0xffffffff);
}
#endif

View File

@@ -6,12 +6,12 @@
int gettimeofday(struct timeval *tp, void *tz)
{
struct _timeb timebuffer;
struct _timeb timebuffer;
_ftime( &timebuffer );
tp->tv_sec = timebuffer.time;
tp->tv_usec = timebuffer.millitm * 1000;
return 0;
_ftime(&timebuffer);
tp->tv_sec = timebuffer.time;
tp->tv_usec = timebuffer.millitm * 1000;
return 0;
}
#endif

View File

@@ -31,7 +31,7 @@
#define INT16SZ 2
#ifndef AF_INET6
#define AF_INET6 AF_MAX+1 /* just to let this compile */
#define AF_INET6 AF_MAX+1 /* just to let this compile */
#endif
/*
@@ -39,8 +39,8 @@
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
*/
static const char *inet_ntop4(const u_char *src, char *dst, size_t size);
static const char *inet_ntop6(const u_char *src, char *dst, size_t size);
static const char *inet_ntop4(const u_char * src, char *dst, size_t size);
static const char *inet_ntop6(const u_char * src, char *dst, size_t size);
/* char *
* inet_ntop(af, src, dst, size)
@@ -50,23 +50,22 @@ static const char *inet_ntop6(const u_char *src, char *dst, size_t size);
* author:
* Paul Vixie, 1996.
*/
const char *
inet_ntop(af, src, dst, size)
int af;
const void *src;
char *dst;
size_t size;
const char *inet_ntop(af, src, dst, size)
int af;
const void *src;
char *dst;
size_t size;
{
switch (af) {
case AF_INET:
return (inet_ntop4(src, dst, size));
case AF_INET6:
return (inet_ntop6(src, dst, size));
default:
errno = EAFNOSUPPORT;
return (NULL);
}
/* NOTREACHED */
switch (af) {
case AF_INET:
return (inet_ntop4(src, dst, size));
case AF_INET6:
return (inet_ntop6(src, dst, size));
default:
errno = EAFNOSUPPORT;
return (NULL);
}
/* NOTREACHED */
}
/* const char *
@@ -80,22 +79,21 @@ inet_ntop(af, src, dst, size)
* author:
* Paul Vixie, 1996.
*/
static const char *
inet_ntop4(src, dst, size)
const u_char *src;
char *dst;
size_t size;
static const char *inet_ntop4(src, dst, size)
const u_char *src;
char *dst;
size_t size;
{
static const char fmt[] = "%u.%u.%u.%u";
char tmp[sizeof "255.255.255.255"];
static const char fmt[] = "%u.%u.%u.%u";
char tmp[sizeof "255.255.255.255"];
sprintf(tmp, fmt, src[0], src[1], src[2], src[3]);
if ((size_t)strlen(tmp) > size) {
errno = ENOSPC;
return (NULL);
}
strcpy(dst, tmp);
return (dst);
sprintf(tmp, fmt, src[0], src[1], src[2], src[3]);
if ((size_t) strlen(tmp) > size) {
errno = ENOSPC;
return (NULL);
}
strcpy(dst, tmp);
return (dst);
}
/* const char *
@@ -104,96 +102,96 @@ inet_ntop4(src, dst, size)
* author:
* Paul Vixie, 1996.
*/
static const char *
inet_ntop6(src, dst, size)
const u_char *src;
char *dst;
size_t size;
static const char *inet_ntop6(src, dst, size)
const u_char *src;
char *dst;
size_t size;
{
/*
* Note that int32_t and int16_t need only be "at least" large enough
* to contain a value of the specified size. On some systems, like
* Crays, there is no such thing as an integer variable with 16 bits.
* Keep this in mind if you think this function should have been coded
* to use pointer overlays. All the world's not a VAX.
*/
char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
struct { int base, len; } best, cur;
uint32_t words[IN6ADDRSZ / INT16SZ];
int i;
/*
* Note that int32_t and int16_t need only be "at least" large enough
* to contain a value of the specified size. On some systems, like
* Crays, there is no such thing as an integer variable with 16 bits.
* Keep this in mind if you think this function should have been coded
* to use pointer overlays. All the world's not a VAX.
*/
char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
struct {
int base, len;
} best, cur;
uint32_t words[IN6ADDRSZ / INT16SZ];
int i;
/*
* Preprocess:
* Copy the input (bytewise) array into a wordwise array.
* Find the longest run of 0x00's in src[] for :: shorthanding.
*/
memset(words, 0, sizeof words);
for (i = 0; i < IN6ADDRSZ; i++)
words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
best.base = -1;
cur.base = -1;
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
if (words[i] == 0) {
if (cur.base == -1)
cur.base = i, cur.len = 1;
else
cur.len++;
} else {
if (cur.base != -1) {
if (best.base == -1 || cur.len > best.len)
best = cur;
cur.base = -1;
}
}
}
if (cur.base != -1) {
if (best.base == -1 || cur.len > best.len)
best = cur;
}
if (best.base != -1 && best.len < 2)
best.base = -1;
/*
* Preprocess:
* Copy the input (bytewise) array into a wordwise array.
* Find the longest run of 0x00's in src[] for :: shorthanding.
*/
memset(words, 0, sizeof words);
for (i = 0; i < IN6ADDRSZ; i++)
words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
best.base = -1;
cur.base = -1;
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
if (words[i] == 0) {
if (cur.base == -1)
cur.base = i, cur.len = 1;
else
cur.len++;
} else {
if (cur.base != -1) {
if (best.base == -1 || cur.len > best.len)
best = cur;
cur.base = -1;
}
}
}
if (cur.base != -1) {
if (best.base == -1 || cur.len > best.len)
best = cur;
}
if (best.base != -1 && best.len < 2)
best.base = -1;
/*
* Format the result.
*/
tp = tmp;
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
/* Are we inside the best run of 0x00's? */
if (best.base != -1 && i >= best.base &&
i < (best.base + best.len)) {
if (i == best.base)
*tp++ = ':';
continue;
}
/* Are we following an initial run of 0x00s or any real hex? */
if (i != 0)
*tp++ = ':';
/* Is this address an encapsulated IPv4? */
if (i == 6 && best.base == 0 &&
(best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
return (NULL);
tp += strlen(tp);
break;
}
sprintf(tp, "%x", words[i]);
tp += strlen(tp);
}
/* Was it a trailing run of 0x00's? */
if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
*tp++ = ':';
*tp++ = '\0';
/*
* Format the result.
*/
tp = tmp;
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
/* Are we inside the best run of 0x00's? */
if (best.base != -1 && i >= best.base &&
i < (best.base + best.len)) {
if (i == best.base)
*tp++ = ':';
continue;
}
/* Are we following an initial run of 0x00s or any real hex? */
if (i != 0)
*tp++ = ':';
/* Is this address an encapsulated IPv4? */
if (i == 6 && best.base == 0 &&
(best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
if (!inet_ntop4(src + 12, tp, sizeof tmp - (tp - tmp)))
return (NULL);
tp += strlen(tp);
break;
}
sprintf(tp, "%x", words[i]);
tp += strlen(tp);
}
/* Was it a trailing run of 0x00's? */
if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
*tp++ = ':';
*tp++ = '\0';
/*
* Check for overflow, copy, and we're done.
*/
if ((size_t) (tp - tmp) > size) {
errno = ENOSPC;
return (NULL);
}
strcpy(dst, tmp);
return (dst);
/*
* Check for overflow, copy, and we're done.
*/
if ((size_t) (tp - tmp) > size) {
errno = ENOSPC;
return (NULL);
}
strcpy(dst, tmp);
return (dst);
}
#endif

View File

@@ -32,7 +32,7 @@
#define INT16SZ 2
#ifndef AF_INET6
#define AF_INET6 AF_MAX+1 /* just to let this compile */
#define AF_INET6 AF_MAX+1 /* just to let this compile */
#endif
/*
@@ -40,8 +40,8 @@
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
*/
static int inet_pton4(const char *src, u_char *dst);
static int inet_pton6(const char *src, u_char *dst);
static int inet_pton4(const char *src, u_char * dst);
static int inet_pton6(const char *src, u_char * dst);
/* int
* inet_pton(af, src, dst)
@@ -54,22 +54,21 @@ static int inet_pton6(const char *src, u_char *dst);
* author:
* Paul Vixie, 1996.
*/
int
inet_pton(af, src, dst)
int af;
const char *src;
void *dst;
int inet_pton(af, src, dst)
int af;
const char *src;
void *dst;
{
switch (af) {
case AF_INET:
return (inet_pton4(src, dst));
case AF_INET6:
return (inet_pton6(src, dst));
default:
errno = EAFNOSUPPORT;
return (-1);
}
/* NOTREACHED */
switch (af) {
case AF_INET:
return (inet_pton4(src, dst));
case AF_INET6:
return (inet_pton6(src, dst));
default:
errno = EAFNOSUPPORT;
return (-1);
}
/* NOTREACHED */
}
/* int
@@ -82,45 +81,44 @@ inet_pton(af, src, dst)
* author:
* Paul Vixie, 1996.
*/
static int
inet_pton4(src, dst)
const char *src;
u_char *dst;
static int inet_pton4(src, dst)
const char *src;
u_char *dst;
{
static const char digits[] = "0123456789";
int saw_digit, octets, ch;
u_char tmp[INADDRSZ], *tp;
static const char digits[] = "0123456789";
int saw_digit, octets, ch;
u_char tmp[INADDRSZ], *tp;
saw_digit = 0;
octets = 0;
*(tp = tmp) = 0;
while ((ch = *src++) != '\0') {
const char *pch;
saw_digit = 0;
octets = 0;
*(tp = tmp) = 0;
while ((ch = *src++) != '\0') {
const char *pch;
if ((pch = (char *) strchr(digits, ch)) != NULL) {
uint8_t new = *tp * 10 + (pch - digits);
if ((pch = (char *)strchr(digits, ch)) != NULL) {
uint8_t new = *tp * 10 + (pch - digits);
if (new > 255)
return (0);
*tp = new;
if (! saw_digit) {
if (++octets > 4)
return (0);
saw_digit = 1;
}
} else if (ch == '.' && saw_digit) {
if (octets == 4)
return (0);
*++tp = 0;
saw_digit = 0;
} else
return (0);
}
if (octets < 4)
return (0);
/* bcopy(tmp, dst, INADDRSZ); */
memcpy(dst, tmp, INADDRSZ);
return (1);
if (new > 255)
return (0);
*tp = new;
if (!saw_digit) {
if (++octets > 4)
return (0);
saw_digit = 1;
}
} else if (ch == '.' && saw_digit) {
if (octets == 4)
return (0);
*++tp = 0;
saw_digit = 0;
} else
return (0);
}
if (octets < 4)
return (0);
/* bcopy(tmp, dst, INADDRSZ); */
memcpy(dst, tmp, INADDRSZ);
return (1);
}
/* int
@@ -136,91 +134,89 @@ inet_pton4(src, dst)
* author:
* Paul Vixie, 1996.
*/
static int
inet_pton6(src, dst)
const char *src;
u_char *dst;
static int inet_pton6(src, dst)
const char *src;
u_char *dst;
{
static const char xdigits_l[] = "0123456789abcdef",
xdigits_u[] = "0123456789ABCDEF";
u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
const char *xdigits, *curtok;
int ch, saw_xdigit;
unsigned val;
static const char xdigits_l[] = "0123456789abcdef",
xdigits_u[] = "0123456789ABCDEF";
u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
const char *xdigits, *curtok;
int ch, saw_xdigit;
unsigned val;
memset((tp = tmp), 0, IN6ADDRSZ);
endp = tp + IN6ADDRSZ;
colonp = NULL;
/* Leading :: requires some special handling. */
if (*src == ':')
if (*++src != ':')
return (0);
curtok = src;
saw_xdigit = 0;
val = 0;
while ((ch = *src++) != '\0') {
const char *pch;
memset((tp = tmp), 0, IN6ADDRSZ);
endp = tp + IN6ADDRSZ;
colonp = NULL;
/* Leading :: requires some special handling. */
if (*src == ':')
if (*++src != ':')
return (0);
curtok = src;
saw_xdigit = 0;
val = 0;
while ((ch = *src++) != '\0') {
const char *pch;
if ((pch = (char *) strchr((xdigits = xdigits_l), ch)) == NULL)
pch = (char *) strchr((xdigits = xdigits_u), ch);
if (pch != NULL) {
val <<= 4;
val |= (pch - xdigits);
if (val > 0xffff)
return (0);
saw_xdigit = 1;
continue;
}
if (ch == ':') {
curtok = src;
if (!saw_xdigit) {
if (colonp)
return (0);
colonp = tp;
continue;
}
if (tp + INT16SZ > endp)
return (0);
*tp++ = (u_char) (val >> 8) & 0xff;
*tp++ = (u_char) val & 0xff;
saw_xdigit = 0;
val = 0;
continue;
}
if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
inet_pton4(curtok, tp) > 0) {
tp += INADDRSZ;
saw_xdigit = 0;
break; /* '\0' was seen by inet_pton4(). */
}
return (0);
}
if (saw_xdigit) {
if (tp + INT16SZ > endp)
return (0);
*tp++ = (u_char) (val >> 8) & 0xff;
*tp++ = (u_char) val & 0xff;
}
if (colonp != NULL) {
/*
* Since some memmove()'s erroneously fail to handle
* overlapping regions, we'll do the shift by hand.
*/
const int n = tp - colonp;
int i;
if ((pch = (char *)strchr((xdigits = xdigits_l), ch)) == NULL)
pch = (char *)strchr((xdigits = xdigits_u), ch);
if (pch != NULL) {
val <<= 4;
val |= (pch - xdigits);
if (val > 0xffff)
return (0);
saw_xdigit = 1;
continue;
}
if (ch == ':') {
curtok = src;
if (!saw_xdigit) {
if (colonp)
return (0);
colonp = tp;
continue;
}
if (tp + INT16SZ > endp)
return (0);
*tp++ = (u_char) (val >> 8) & 0xff;
*tp++ = (u_char) val & 0xff;
saw_xdigit = 0;
val = 0;
continue;
}
if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
inet_pton4(curtok, tp) > 0) {
tp += INADDRSZ;
saw_xdigit = 0;
break; /* '\0' was seen by inet_pton4(). */
}
return (0);
}
if (saw_xdigit) {
if (tp + INT16SZ > endp)
return (0);
*tp++ = (u_char) (val >> 8) & 0xff;
*tp++ = (u_char) val & 0xff;
}
if (colonp != NULL) {
/*
* Since some memmove()'s erroneously fail to handle
* overlapping regions, we'll do the shift by hand.
*/
const int n = tp - colonp;
int i;
for (i = 1; i <= n; i++) {
endp[- i] = colonp[n - i];
colonp[n - i] = 0;
}
tp = endp;
}
if (tp != endp)
return (0);
/* bcopy(tmp, dst, IN6ADDRSZ); */
memcpy(dst, tmp, IN6ADDRSZ);
return (1);
for (i = 1; i <= n; i++) {
endp[-i] = colonp[n - i];
colonp[n - i] = 0;
}
tp = endp;
}
if (tp != endp)
return (0);
/* bcopy(tmp, dst, IN6ADDRSZ); */
memcpy(dst, tmp, IN6ADDRSZ);
return (1);
}
#endif

View File

@@ -55,34 +55,35 @@
#include <mach/mach.h>
#else
#include <semaphore.h>
#endif /* HAVE_MACOSX */
#endif /* HAVE_MACOSX */
#include "compat/platform_semaphore.h"
inline void platform_sem_init(void * semStructure, int pshared, int initialValue)
inline void platform_sem_init(void *semStructure, int pshared, int initialValue)
{
#ifdef HAVE_MACOSX
UNUSED(pshared);
semaphore_create(mach_task_self(), (semaphore_t *)semStructure, SYNC_POLICY_FIFO, initialValue);
#else
sem_init((sem_t *)semStructure, pshared, initialValue);
#endif /* HAVE_MACOSX */
#ifdef HAVE_MACOSX
UNUSED(pshared);
semaphore_create(mach_task_self(), (semaphore_t *) semStructure,
SYNC_POLICY_FIFO, initialValue);
#else
sem_init((sem_t *) semStructure, pshared, initialValue);
#endif /* HAVE_MACOSX */
}
inline void platform_sem_post(void * semStructure)
inline void platform_sem_post(void *semStructure)
{
#ifdef HAVE_MACOSX
semaphore_signal(*((semaphore_t *)semStructure));
#else
sem_post((sem_t *)semStructure);
#endif /* HAVE_MACOSX */
#ifdef HAVE_MACOSX
semaphore_signal(*((semaphore_t *) semStructure));
#else
sem_post((sem_t *) semStructure);
#endif /* HAVE_MACOSX */
}
inline void platform_sem_wait(void * semStructure)
inline void platform_sem_wait(void *semStructure)
{
#ifdef HAVE_MACOSX
semaphore_wait(*((semaphore_t *)semStructure));
#else
sem_wait((sem_t *)semStructure);
#endif /* HAVE_MACOSX */
#ifdef HAVE_MACOSX
semaphore_wait(*((semaphore_t *) semStructure));
#else
sem_wait((sem_t *) semStructure);
#endif /* HAVE_MACOSX */
}

View File

@@ -45,10 +45,10 @@
#ifndef HAVE_VSNPRINTF
int vsnprintf(char *s, size_t buf_size, const char *format, va_list ap)
{
/* Quick hack replacement for vsnprintf... note that this */
/* doesn't check for buffer overflows, and so is open to */
/* many really nasty attacks! */
UNUSED(buf_size);
return vsprintf(s,format,ap);
/* Quick hack replacement for vsnprintf... note that this */
/* doesn't check for buffer overflows, and so is open to */
/* many really nasty attacks! */
UNUSED(buf_size);
return vsprintf(s, format, ap);
}
#endif

View File

@@ -41,151 +41,175 @@
#include "crypt_aes_impl.h"
#include "crypt_aes.h"
int makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial) {
int i;
char *keyMat;
u8 cipherKey[MAXKB];
if (key == NULL) {
return BAD_KEY_INSTANCE;
}
int makeKey(keyInstance * key, BYTE direction, int keyLen, char *keyMaterial)
{
int i;
char *keyMat;
u8 cipherKey[MAXKB];
if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
key->direction = direction;
} else {
return BAD_KEY_DIR;
}
if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
key->keyLen = keyLen;
} else {
return BAD_KEY_MAT;
}
if (keyMaterial != NULL) {
strncpy(key->keyMaterial, keyMaterial, keyLen/4);
}
/* initialize key schedule: */
keyMat = key->keyMaterial;
for (i = 0; i < key->keyLen/8; i++) {
int t, v;
t = *keyMat++;
if ((t >= '0') && (t <= '9')) v = (t - '0') << 4;
else if ((t >= 'a') && (t <= 'f')) v = (t - 'a' + 10) << 4;
else if ((t >= 'A') && (t <= 'F')) v = (t - 'A' + 10) << 4;
else return BAD_KEY_MAT;
t = *keyMat++;
if ((t >= '0') && (t <= '9')) v ^= (t - '0');
else if ((t >= 'a') && (t <= 'f')) v ^= (t - 'a' + 10);
else if ((t >= 'A') && (t <= 'F')) v ^= (t - 'A' + 10);
else return BAD_KEY_MAT;
cipherKey[i] = (u8)v;
}
if (direction == DIR_ENCRYPT) {
key->Nr = rijndaelKeySetupEnc(key->rk, cipherKey, keyLen);
} else {
key->Nr = rijndaelKeySetupDec(key->rk, cipherKey, keyLen);
}
rijndaelKeySetupEnc(key->ek, cipherKey, keyLen);
return TRUE;
}
int cipherInit(cipherInstance *cipher, BYTE mode, char *IV) {
if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
cipher->mode = mode;
} else {
return BAD_CIPHER_MODE;
}
if (IV != NULL) {
int i;
for (i = 0; i < MAX_IV_SIZE; i++) {
int t, j;
t = IV[2*i];
if ((t >= '0') && (t <= '9')) j = (t - '0') << 4;
else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4;
else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4;
else return BAD_CIPHER_INSTANCE;
t = IV[2*i+1];
if ((t >= '0') && (t <= '9')) j ^= (t - '0');
else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10);
else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10);
else return BAD_CIPHER_INSTANCE;
cipher->IV[i] = (u8)j;
}
} else {
memset(cipher->IV, 0, MAX_IV_SIZE);
}
return TRUE;
}
int blockEncrypt(cipherInstance *cipher, keyInstance *key,
BYTE *input, int inputLen, BYTE *outBuffer) {
int i, k, t, numBlocks;
u8 block[16], *iv;
if (cipher == NULL ||
key == NULL ||
key->direction == DIR_DECRYPT) {
return BAD_CIPHER_STATE;
}
if (input == NULL || inputLen <= 0) {
return 0; /* nothing to do */
}
numBlocks = inputLen/128;
switch (cipher->mode) {
case MODE_ECB:
for (i = numBlocks; i > 0; i--) {
rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
input += 16;
outBuffer += 16;
}
break;
case MODE_CBC:
iv = cipher->IV;
for (i = numBlocks; i > 0; i--) {
((u32*)block)[0] = ((u32*)input)[0] ^ ((u32*)iv)[0];
((u32*)block)[1] = ((u32*)input)[1] ^ ((u32*)iv)[1];
((u32*)block)[2] = ((u32*)input)[2] ^ ((u32*)iv)[2];
((u32*)block)[3] = ((u32*)input)[3] ^ ((u32*)iv)[3];
rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
iv = outBuffer;
input += 16;
outBuffer += 16;
}
break;
case MODE_CFB1:
iv = cipher->IV;
for (i = numBlocks; i > 0; i--) {
memcpy(outBuffer, input, 16);
for (k = 0; k < 128; k++) {
rijndaelEncrypt(key->ek, key->Nr, iv, block);
outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7);
for (t = 0; t < 15; t++) {
iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
}
iv[15] = (iv[15] << 1) | ((outBuffer[k >> 3] >> (7 - (k & 7))) & 1);
}
outBuffer += 16;
input += 16;
if (key == NULL) {
return BAD_KEY_INSTANCE;
}
break;
default:
return BAD_CIPHER_STATE;
}
return 128*numBlocks;
if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
key->direction = direction;
} else {
return BAD_KEY_DIR;
}
if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
key->keyLen = keyLen;
} else {
return BAD_KEY_MAT;
}
if (keyMaterial != NULL) {
strncpy(key->keyMaterial, keyMaterial, keyLen / 4);
}
/* initialize key schedule: */
keyMat = key->keyMaterial;
for (i = 0; i < key->keyLen / 8; i++) {
int t, v;
t = *keyMat++;
if ((t >= '0') && (t <= '9'))
v = (t - '0') << 4;
else if ((t >= 'a') && (t <= 'f'))
v = (t - 'a' + 10) << 4;
else if ((t >= 'A') && (t <= 'F'))
v = (t - 'A' + 10) << 4;
else
return BAD_KEY_MAT;
t = *keyMat++;
if ((t >= '0') && (t <= '9'))
v ^= (t - '0');
else if ((t >= 'a') && (t <= 'f'))
v ^= (t - 'a' + 10);
else if ((t >= 'A') && (t <= 'F'))
v ^= (t - 'A' + 10);
else
return BAD_KEY_MAT;
cipherKey[i] = (u8) v;
}
if (direction == DIR_ENCRYPT) {
key->Nr = rijndaelKeySetupEnc(key->rk, cipherKey, keyLen);
} else {
key->Nr = rijndaelKeySetupDec(key->rk, cipherKey, keyLen);
}
rijndaelKeySetupEnc(key->ek, cipherKey, keyLen);
return TRUE;
}
int cipherInit(cipherInstance * cipher, BYTE mode, char *IV)
{
if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
cipher->mode = mode;
} else {
return BAD_CIPHER_MODE;
}
if (IV != NULL) {
int i;
for (i = 0; i < MAX_IV_SIZE; i++) {
int t, j;
t = IV[2 * i];
if ((t >= '0') && (t <= '9'))
j = (t - '0') << 4;
else if ((t >= 'a') && (t <= 'f'))
j = (t - 'a' + 10) << 4;
else if ((t >= 'A') && (t <= 'F'))
j = (t - 'A' + 10) << 4;
else
return BAD_CIPHER_INSTANCE;
t = IV[2 * i + 1];
if ((t >= '0') && (t <= '9'))
j ^= (t - '0');
else if ((t >= 'a') && (t <= 'f'))
j ^= (t - 'a' + 10);
else if ((t >= 'A') && (t <= 'F'))
j ^= (t - 'A' + 10);
else
return BAD_CIPHER_INSTANCE;
cipher->IV[i] = (u8) j;
}
} else {
memset(cipher->IV, 0, MAX_IV_SIZE);
}
return TRUE;
}
int blockEncrypt(cipherInstance * cipher, keyInstance * key,
BYTE * input, int inputLen, BYTE * outBuffer)
{
int i, k, t, numBlocks;
u8 block[16], *iv;
if (cipher == NULL || key == NULL || key->direction == DIR_DECRYPT) {
return BAD_CIPHER_STATE;
}
if (input == NULL || inputLen <= 0) {
return 0; /* nothing to do */
}
numBlocks = inputLen / 128;
switch (cipher->mode) {
case MODE_ECB:
for (i = numBlocks; i > 0; i--) {
rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
input += 16;
outBuffer += 16;
}
break;
case MODE_CBC:
iv = cipher->IV;
for (i = numBlocks; i > 0; i--) {
((u32 *) block)[0] =
((u32 *) input)[0] ^ ((u32 *) iv)[0];
((u32 *) block)[1] =
((u32 *) input)[1] ^ ((u32 *) iv)[1];
((u32 *) block)[2] =
((u32 *) input)[2] ^ ((u32 *) iv)[2];
((u32 *) block)[3] =
((u32 *) input)[3] ^ ((u32 *) iv)[3];
rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
iv = outBuffer;
input += 16;
outBuffer += 16;
}
break;
case MODE_CFB1:
iv = cipher->IV;
for (i = numBlocks; i > 0; i--) {
memcpy(outBuffer, input, 16);
for (k = 0; k < 128; k++) {
rijndaelEncrypt(key->ek, key->Nr, iv, block);
outBuffer[k >> 3] ^=
(block[0] & 0x80U) >> (k & 7);
for (t = 0; t < 15; t++) {
iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
}
iv[15] =
(iv[15] << 1) |
((outBuffer[k >> 3] >> (7 - (k & 7))) & 1);
}
outBuffer += 16;
input += 16;
}
break;
default:
return BAD_CIPHER_STATE;
}
return 128 * numBlocks;
}
@@ -197,207 +221,213 @@ int blockEncrypt(cipherInstance *cipher, keyInstance *key,
* @param outBuffer encrypted output data
*
* @return length in octets (not bits) of the encrypted output buffer.
int padEncrypt(cipherInstance *cipher, keyInstance *key,
BYTE *input, int inputOctets, BYTE *outBuffer) {
int i, numBlocks, padLen;
u8 block[16], *iv;
*/
int padEncrypt(cipherInstance * cipher, keyInstance * key,
BYTE * input, int inputOctets, BYTE * outBuffer)
{
int i, numBlocks, padLen;
u8 block[16], *iv;
if (cipher == NULL ||
key == NULL ||
key->direction == DIR_DECRYPT) {
return BAD_CIPHER_STATE;
}
if (input == NULL || inputOctets <= 0) {
return 0; /* nothing to do */
}
numBlocks = inputOctets/16;
switch (cipher->mode) {
case MODE_ECB:
for (i = numBlocks; i > 0; i--) {
rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
input += 16;
outBuffer += 16;
}
padLen = 16 - (inputOctets - 16*numBlocks);
assert(padLen > 0 && padLen <= 16);
memcpy(block, input, 16 - padLen);
memset(block + 16 - padLen, padLen, padLen);
rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
break;
case MODE_CBC:
iv = cipher->IV;
for (i = numBlocks; i > 0; i--) {
((u32*)block)[0] = ((u32*)input)[0] ^ ((u32*)iv)[0];
((u32*)block)[1] = ((u32*)input)[1] ^ ((u32*)iv)[1];
((u32*)block)[2] = ((u32*)input)[2] ^ ((u32*)iv)[2];
((u32*)block)[3] = ((u32*)input)[3] ^ ((u32*)iv)[3];
rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
iv = outBuffer;
input += 16;
outBuffer += 16;
}
padLen = 16 - (inputOctets - 16*numBlocks);
assert(padLen > 0 && padLen <= 16);
for (i = 0; i < 16 - padLen; i++) {
block[i] = input[i] ^ iv[i];
}
for (i = 16 - padLen; i < 16; i++) {
block[i] = (BYTE)padLen ^ iv[i];
}
rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
break;
default:
return BAD_CIPHER_STATE;
}
return 16*(numBlocks + 1);
}
int blockDecrypt(cipherInstance *cipher, keyInstance *key,
BYTE *input, int inputLen, BYTE *outBuffer) {
int i, k, t, numBlocks;
u8 block[16], *iv;
if (cipher == NULL ||
key == NULL ||
(cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) {
return BAD_CIPHER_STATE;
}
if (input == NULL || inputLen <= 0) {
return 0; /* nothing to do */
}
numBlocks = inputLen/128;
switch (cipher->mode) {
case MODE_ECB:
for (i = numBlocks; i > 0; i--) {
rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
input += 16;
outBuffer += 16;
}
break;
case MODE_CBC:
iv = cipher->IV;
for (i = numBlocks; i > 0; i--) {
rijndaelDecrypt(key->rk, key->Nr, input, block);
((u32*)block)[0] ^= ((u32*)iv)[0];
((u32*)block)[1] ^= ((u32*)iv)[1];
((u32*)block)[2] ^= ((u32*)iv)[2];
((u32*)block)[3] ^= ((u32*)iv)[3];
memcpy(cipher->IV, input, 16);
memcpy(outBuffer, block, 16);
input += 16;
outBuffer += 16;
}
break;
case MODE_CFB1:
iv = cipher->IV;
for (i = numBlocks; i > 0; i--) {
memcpy(outBuffer, input, 16);
for (k = 0; k < 128; k++) {
rijndaelEncrypt(key->ek, key->Nr, iv, block);
for (t = 0; t < 15; t++) {
iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
}
iv[15] = (iv[15] << 1) | ((input[k >> 3] >> (7 - (k & 7))) & 1);
outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7);
}
outBuffer += 16;
input += 16;
if (cipher == NULL || key == NULL || key->direction == DIR_DECRYPT) {
return BAD_CIPHER_STATE;
}
if (input == NULL || inputOctets <= 0) {
return 0; /* nothing to do */
break;
}
default:
return BAD_CIPHER_STATE;
}
return 128*numBlocks;
numBlocks = inputOctets / 16;
switch (cipher->mode) {
case MODE_ECB:
for (i = numBlocks; i > 0; i--) {
rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
input += 16;
outBuffer += 16;
}
padLen = 16 - (inputOctets - 16 * numBlocks);
assert(padLen > 0 && padLen <= 16);
memcpy(block, input, 16 - padLen);
memset(block + 16 - padLen, padLen, padLen);
rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
break;
case MODE_CBC:
iv = cipher->IV;
for (i = numBlocks; i > 0; i--) {
((u32 *) block)[0] =
((u32 *) input)[0] ^ ((u32 *) iv)[0];
((u32 *) block)[1] =
((u32 *) input)[1] ^ ((u32 *) iv)[1];
((u32 *) block)[2] =
((u32 *) input)[2] ^ ((u32 *) iv)[2];
((u32 *) block)[3] =
((u32 *) input)[3] ^ ((u32 *) iv)[3];
rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
iv = outBuffer;
input += 16;
outBuffer += 16;
}
padLen = 16 - (inputOctets - 16 * numBlocks);
assert(padLen > 0 && padLen <= 16);
for (i = 0; i < 16 - padLen; i++) {
block[i] = input[i] ^ iv[i];
}
for (i = 16 - padLen; i < 16; i++) {
block[i] = (BYTE) padLen ^ iv[i];
}
rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
break;
default:
return BAD_CIPHER_STATE;
}
return 16 * (numBlocks + 1);
}
int padDecrypt(cipherInstance *cipher, keyInstance *key,
BYTE *input, int inputOctets, BYTE *outBuffer) {
int i, numBlocks, padLen;
u8 block[16];
int blockDecrypt(cipherInstance * cipher, keyInstance * key,
BYTE * input, int inputLen, BYTE * outBuffer)
{
int i, k, t, numBlocks;
u8 block[16], *iv;
if (cipher == NULL ||
key == NULL ||
key->direction == DIR_ENCRYPT) {
return BAD_CIPHER_STATE;
}
if (input == NULL || inputOctets <= 0) {
return 0; /* nothing to do */
}
if (inputOctets % 16 != 0) {
return BAD_DATA;
}
if (cipher == NULL ||
key == NULL ||
(cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) {
return BAD_CIPHER_STATE;
}
if (input == NULL || inputLen <= 0) {
return 0; /* nothing to do */
}
numBlocks = inputOctets/16;
numBlocks = inputLen / 128;
switch (cipher->mode) {
case MODE_ECB:
/* all blocks but last */
for (i = numBlocks - 1; i > 0; i--) {
rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
input += 16;
outBuffer += 16;
}
/* last block */
rijndaelDecrypt(key->rk, key->Nr, input, block);
padLen = block[15];
if (padLen >= 16) {
return BAD_DATA;
}
for (i = 16 - padLen; i < 16; i++) {
if (block[i] != padLen) {
return BAD_DATA;
}
}
memcpy(outBuffer, block, 16 - padLen);
break;
case MODE_CBC:
/* all blocks but last */
for (i = numBlocks - 1; i > 0; i--) {
rijndaelDecrypt(key->rk, key->Nr, input, block);
((u32*)block)[0] ^= ((u32*)cipher->IV)[0];
((u32*)block)[1] ^= ((u32*)cipher->IV)[1];
((u32*)block)[2] ^= ((u32*)cipher->IV)[2];
((u32*)block)[3] ^= ((u32*)cipher->IV)[3];
memcpy(cipher->IV, input, 16);
memcpy(outBuffer, block, 16);
input += 16;
outBuffer += 16;
}
/* last block */
rijndaelDecrypt(key->rk, key->Nr, input, block);
((u32*)block)[0] ^= ((u32*)cipher->IV)[0];
((u32*)block)[1] ^= ((u32*)cipher->IV)[1];
((u32*)block)[2] ^= ((u32*)cipher->IV)[2];
((u32*)block)[3] ^= ((u32*)cipher->IV)[3];
padLen = block[15];
if (padLen <= 0 || padLen > 16) {
return BAD_DATA;
}
for (i = 16 - padLen; i < 16; i++) {
if (block[i] != padLen) {
return BAD_DATA;
}
}
memcpy(outBuffer, block, 16 - padLen);
break;
default:
return BAD_CIPHER_STATE;
}
return 16*numBlocks - padLen;
switch (cipher->mode) {
case MODE_ECB:
for (i = numBlocks; i > 0; i--) {
rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
input += 16;
outBuffer += 16;
}
break;
case MODE_CBC:
iv = cipher->IV;
for (i = numBlocks; i > 0; i--) {
rijndaelDecrypt(key->rk, key->Nr, input, block);
((u32 *) block)[0] ^= ((u32 *) iv)[0];
((u32 *) block)[1] ^= ((u32 *) iv)[1];
((u32 *) block)[2] ^= ((u32 *) iv)[2];
((u32 *) block)[3] ^= ((u32 *) iv)[3];
memcpy(cipher->IV, input, 16);
memcpy(outBuffer, block, 16);
input += 16;
outBuffer += 16;
}
break;
case MODE_CFB1:
iv = cipher->IV;
for (i = numBlocks; i > 0; i--) {
memcpy(outBuffer, input, 16);
for (k = 0; k < 128; k++) {
rijndaelEncrypt(key->ek, key->Nr, iv, block);
for (t = 0; t < 15; t++) {
iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
}
iv[15] =
(iv[15] << 1) |
((input[k >> 3] >> (7 - (k & 7))) & 1);
outBuffer[k >> 3] ^=
(block[0] & 0x80U) >> (k & 7);
}
outBuffer += 16;
input += 16;
}
break;
default:
return BAD_CIPHER_STATE;
}
return 128 * numBlocks;
}
int padDecrypt(cipherInstance * cipher, keyInstance * key,
BYTE * input, int inputOctets, BYTE * outBuffer)
{
int i, numBlocks, padLen;
u8 block[16];
if (cipher == NULL || key == NULL || key->direction == DIR_ENCRYPT) {
return BAD_CIPHER_STATE;
}
if (input == NULL || inputOctets <= 0) {
return 0; /* nothing to do */
}
if (inputOctets % 16 != 0) {
return BAD_DATA;
}
numBlocks = inputOctets / 16;
switch (cipher->mode) {
case MODE_ECB:
/* all blocks but last */
for (i = numBlocks - 1; i > 0; i--) {
rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
input += 16;
outBuffer += 16;
}
/* last block */
rijndaelDecrypt(key->rk, key->Nr, input, block);
padLen = block[15];
if (padLen >= 16) {
return BAD_DATA;
}
for (i = 16 - padLen; i < 16; i++) {
if (block[i] != padLen) {
return BAD_DATA;
}
}
memcpy(outBuffer, block, 16 - padLen);
break;
case MODE_CBC:
/* all blocks but last */
for (i = numBlocks - 1; i > 0; i--) {
rijndaelDecrypt(key->rk, key->Nr, input, block);
((u32 *) block)[0] ^= ((u32 *) cipher->IV)[0];
((u32 *) block)[1] ^= ((u32 *) cipher->IV)[1];
((u32 *) block)[2] ^= ((u32 *) cipher->IV)[2];
((u32 *) block)[3] ^= ((u32 *) cipher->IV)[3];
memcpy(cipher->IV, input, 16);
memcpy(outBuffer, block, 16);
input += 16;
outBuffer += 16;
}
/* last block */
rijndaelDecrypt(key->rk, key->Nr, input, block);
((u32 *) block)[0] ^= ((u32 *) cipher->IV)[0];
((u32 *) block)[1] ^= ((u32 *) cipher->IV)[1];
((u32 *) block)[2] ^= ((u32 *) cipher->IV)[2];
((u32 *) block)[3] ^= ((u32 *) cipher->IV)[3];
padLen = block[15];
if (padLen <= 0 || padLen > 16) {
return BAD_DATA;
}
for (i = 16 - padLen; i < 16; i++) {
if (block[i] != padLen) {
return BAD_DATA;
}
}
memcpy(outBuffer, block, 16 - padLen);
break;
default:
return BAD_CIPHER_STATE;
}
return 16 * numBlocks - padLen;
}
@@ -410,32 +440,33 @@ int padDecrypt(cipherInstance *cipher, keyInstance *key,
*
* Returns:
* TRUE - on success
int cipherUpdateRounds(cipherInstance *cipher, keyInstance *key,
BYTE *input, int inputLen, BYTE *outBuffer, int rounds) {
u8 block[16];
* BAD_CIPHER_STATE - cipher in bad state (e.g., not initialized)
*/
int cipherUpdateRounds(cipherInstance * cipher, keyInstance * key,
BYTE * input, int inputLen, BYTE * outBuffer, int rounds)
{
UNUSED(inputLen);
u8 block[16];
if (cipher == NULL || key == NULL) {
return BAD_CIPHER_STATE;
}
UNUSED(inputLen);
if (cipher == NULL || key == NULL) {
return BAD_CIPHER_STATE;
memcpy(block, input, 16);
}
switch (key->direction) {
case DIR_ENCRYPT:
rijndaelEncryptRound(key->rk, key->Nr, block, rounds);
break;
case DIR_DECRYPT:
rijndaelDecryptRound(key->rk, key->Nr, block, rounds);
break;
default:
return BAD_KEY_DIR;
}
memcpy(block, input, 16);
switch (key->direction) {
case DIR_ENCRYPT:
rijndaelEncryptRound(key->rk, key->Nr, block, rounds);
memcpy(outBuffer, block, 16);
return TRUE;
break;
case DIR_DECRYPT:
rijndaelDecryptRound(key->rk, key->Nr, block, rounds);
break;
default:
return BAD_KEY_DIR;
}
memcpy(outBuffer, block, 16);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -52,9 +52,9 @@
#define S44 21
static unsigned char PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
@@ -99,127 +99,125 @@ static unsigned char PADDING[64] = {
* Encodes input (uint32_t) into output (unsigned char). Assumes len is a
* multiple of 4.
*/
static void
Encode(unsigned char *output, uint32_t * input, unsigned int len)
static void Encode(unsigned char *output, uint32_t * input, unsigned int len)
{
unsigned int i, j;
unsigned int i, j;
assert((len % 4) == 0);
assert((len % 4) == 0);
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (unsigned char) (input[i] & 0xff);
output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
}
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (unsigned char)(input[i] & 0xff);
output[j + 1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j + 2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j + 3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
/*
* Decodes input (unsigned char) into output (uint32_t). Assumes len is a
* multiple of 4.
*/
static void
Decode(uint32_t * output, unsigned char *input, unsigned int len)
static void Decode(uint32_t * output, unsigned char *input, unsigned int len)
{
unsigned int i, j;
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((uint32_t) input[j]) | (((uint32_t) input[j + 1]) << 8) |
(((uint32_t) input[j + 2]) << 16) | (((uint32_t) input[j + 3]) << 24);
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] =
((uint32_t) input[j]) | (((uint32_t) input[j + 1]) << 8) |
(((uint32_t) input[j + 2]) << 16) |
(((uint32_t) input[j + 3]) << 24);
}
/*
* MD5 basic transformation. Transforms state based on block.
*/
static void
MD5Transform(uint32_t state[4], unsigned char block[64])
static void MD5Transform(uint32_t state[4], unsigned char block[64])
{
uint32_t a = state[0], b = state[1], c = state[2], d = state[3],
x[16];
uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode(x, block, 64);
Decode(x, block, 64);
/* Round 1 */
FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 1 */
FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 2 */
GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
/* Round 3 */
HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
/* Round 4 */
II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/*
* Zeroize sensitive information.
*/
memset((unsigned char *) x, 0, sizeof(x));
/*
* Zeroize sensitive information.
*/
memset((unsigned char *)x, 0, sizeof(x));
}
/**
@@ -228,15 +226,14 @@ MD5Transform(uint32_t state[4], unsigned char block[64])
*
* Initializes MD5 context for the start of message digest computation.
**/
void
MD5Init(MD5_CTX * context)
void MD5Init(MD5_CTX * context)
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants. */
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants. */
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}
/**
@@ -249,38 +246,40 @@ MD5Init(MD5_CTX * context)
* processing another message block, and updating the context.
**/
void
MD5Update(MD5_CTX * context, unsigned char *input, unsigned int inputLen)
void MD5Update(MD5_CTX * context, unsigned char *input, unsigned int inputLen)
{
unsigned int i, index, partLen;
unsigned int i, index, partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
/* Compute number of bytes mod 64 */
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) {
context->count[1]++;
}
context->count[1] += ((uint32_t) inputLen >> 29);
/* Update number of bits */
if ((context->count[0] +=
((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) {
context->count[1]++;
}
context->count[1] += ((uint32_t) inputLen >> 29);
partLen = 64 - index;
partLen = 64 - index;
/* Transform as many times as possible. */
if (inputLen >= partLen) {
memcpy((unsigned char *) & context->buffer[index], (unsigned char *) input, partLen);
MD5Transform(context->state, context->buffer);
/* Transform as many times as possible. */
if (inputLen >= partLen) {
memcpy((unsigned char *)&context->buffer[index],
(unsigned char *)input, partLen);
MD5Transform(context->state, context->buffer);
for (i = partLen; i + 63 < inputLen; i += 64) {
MD5Transform(context->state, &input[i]);
}
index = 0;
} else {
i = 0;
}
/* Buffer remaining input */
if ((inputLen - i) != 0) {
memcpy((unsigned char *) & context->buffer[index], (unsigned char *) & input[i], inputLen - i);
}
for (i = partLen; i + 63 < inputLen; i += 64) {
MD5Transform(context->state, &input[i]);
}
index = 0;
} else {
i = 0;
}
/* Buffer remaining input */
if ((inputLen - i) != 0) {
memcpy((unsigned char *)&context->buffer[index],
(unsigned char *)&input[i], inputLen - i);
}
}
/**
@@ -293,30 +292,28 @@ MD5Update(MD5_CTX * context, unsigned char *input, unsigned int inputLen)
* with MD5Init() before being used for other MD5 checksum calculations.
**/
void
MD5Final(unsigned char digest[16], MD5_CTX * context)
void MD5Final(unsigned char digest[16], MD5_CTX * context)
{
unsigned char bits[8];
unsigned int index, padLen;
unsigned char bits[8];
unsigned int index, padLen;
/* Save number of bits */
Encode(bits, context->count, 8);
/* Save number of bits */
Encode(bits, context->count, 8);
/*
* Pad out to 56 mod 64.
*/
index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD5Update(context, PADDING, padLen);
/*
* Pad out to 56 mod 64.
*/
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD5Update(context, PADDING, padLen);
/* Append length (before padding) */
MD5Update(context, bits, 8);
/* Store state in digest */
Encode(digest, context->state, 16);
/* Append length (before padding) */
MD5Update(context, bits, 8);
/* Store state in digest */
Encode(digest, context->state, 16);
/*
* Zeroize sensitive information.
*/
memset((unsigned char *) context, 0, sizeof(*context));
/*
* Zeroize sensitive information.
*/
memset((unsigned char *)context, 0, sizeof(*context));
}

View File

@@ -53,41 +53,38 @@
static uint32_t randseed = 1;
void
lbl_srandom(uint32_t seed)
void lbl_srandom(uint32_t seed)
{
randseed = seed;
randseed = seed;
}
uint32_t
lbl_random(void)
uint32_t lbl_random(void)
{
#ifdef HAVE_DEV_URANDOM
int fd, res, l;
int fd, res, l;
fd = open("/dev/urandom", O_RDONLY);
if (fd == -1) {
perror("Cannot open random sequence generator");
abort();
}
l = read(fd, &res, sizeof(res));
if (l != sizeof(res)) {
perror("Cannot read random data");
abort();
}
close(fd);
return res;
fd = open("/dev/urandom", O_RDONLY);
if (fd == -1) {
perror("Cannot open random sequence generator");
abort();
}
l = read(fd, &res, sizeof(res));
if (l != sizeof(res)) {
perror("Cannot read random data");
abort();
}
close(fd);
return res;
#else
register uint32_t x = randseed;
register uint32_t hi, lo, t;
register uint32_t x = randseed;
register uint32_t hi, lo, t;
hi = x / 127773;
lo = x % 127773;
t = 16807 * lo - 2836 * hi;
if (t <= 0)
t += 0x7fffffff;
randseed = t;
return (t);
hi = x / 127773;
lo = x % 127773;
t = 16807 * lo - 2836 * hi;
if (t <= 0)
t += 0x7fffffff;
randseed = t;
return (t);
#endif
}

View File

@@ -52,21 +52,21 @@ void _dprintf(const char *format, ...)
#ifdef WIN32
char msg[65535];
va_list ap;
va_start(ap, format);
_vsnprintf(msg, 65535, format, ap);
_vsnprintf(msg, 65535, format, ap);
va_end(ap);
OutputDebugString(msg);
#else
#else
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
#endif /* WIN32 */
#endif /* WIN32 */
#else
UNUSED (format);
#endif /* DEBUG */
UNUSED(format);
#endif /* DEBUG */
}
/**
@@ -78,72 +78,64 @@ void _dprintf(const char *format, ...)
* hexadecimal and an ascii representation of the memory region.
*
**/
void debug_dump(void*lp, int len)
void debug_dump(void *lp, int len)
{
char * p;
int i, j, start;
char Buff[81];
char stuffBuff[10];
char tmpBuf[10];
_dprintf("Dump of %ld=%lx bytes\n",len, len);
start = 0L;
while (start < len)
{
/* start line with pointer position key */
p = (char*)lp + start;
sprintf(Buff,"%p: ",p);
/* display each character as hex value */
for (i=start, j=0; j < 16; p++,i++, j++)
{
if (i < len)
{
sprintf(tmpBuf,"%X",((int)(*p) & 0xFF));
if (strlen((char *)tmpBuf) < 2)
{
stuffBuff[0] = '0';
stuffBuff[1] = tmpBuf[0];
stuffBuff[2] = ' ';
stuffBuff[3] = '\0';
} else
{
stuffBuff[0] = tmpBuf[0];
stuffBuff[1] = tmpBuf[1];
stuffBuff[2] = ' ';
stuffBuff[3] = '\0';
}
strcat(Buff, stuffBuff);
} else
strcat(Buff," ");
if (j == 7) /* space between groups of 8 */
strcat(Buff," ");
}
/* fill out incomplete lines */
for(;j<16;j++)
{
strcat(Buff," ");
if (j == 7)
strcat(Buff," ");
}
strcat(Buff," ");
/* display each character as character value */
for (i=start,j=0,p=(char*)lp+start;
(i < len && j < 16); p++,i++, j++)
{
if ( ((*p) >= ' ') && ((*p) <= '~') ) /* test displayable */
sprintf(tmpBuf,"%c", *p);
else
sprintf(tmpBuf,"%c", '.');
strcat(Buff,tmpBuf);
if (j == 7) /* space between groups of 8 */
strcat(Buff," ");
}
_dprintf("%s\n", Buff);
start = i; /* next line starting byte */
}
}
char *p;
int i, j, start;
char Buff[81];
char stuffBuff[10];
char tmpBuf[10];
_dprintf("Dump of %ld=%lx bytes\n", len, len);
start = 0L;
while (start < len) {
/* start line with pointer position key */
p = (char *)lp + start;
sprintf(Buff, "%p: ", p);
/* display each character as hex value */
for (i = start, j = 0; j < 16; p++, i++, j++) {
if (i < len) {
sprintf(tmpBuf, "%X", ((int)(*p) & 0xFF));
if (strlen((char *)tmpBuf) < 2) {
stuffBuff[0] = '0';
stuffBuff[1] = tmpBuf[0];
stuffBuff[2] = ' ';
stuffBuff[3] = '\0';
} else {
stuffBuff[0] = tmpBuf[0];
stuffBuff[1] = tmpBuf[1];
stuffBuff[2] = ' ';
stuffBuff[3] = '\0';
}
strcat(Buff, stuffBuff);
} else
strcat(Buff, " ");
if (j == 7) /* space between groups of 8 */
strcat(Buff, " ");
}
/* fill out incomplete lines */
for (; j < 16; j++) {
strcat(Buff, " ");
if (j == 7)
strcat(Buff, " ");
}
strcat(Buff, " ");
/* display each character as character value */
for (i = start, j = 0, p = (char *)lp + start;
(i < len && j < 16); p++, i++, j++) {
if (((*p) >= ' ') && ((*p) <= '~')) /* test displayable */
sprintf(tmpBuf, "%c", *p);
else
sprintf(tmpBuf, "%c", '.');
strcat(Buff, tmpBuf);
if (j == 7) /* space between groups of 8 */
strcat(Buff, " ");
}
_dprintf("%s\n", Buff);
start = i; /* next line starting byte */
}
}

View File

@@ -62,105 +62,105 @@
void init_reciever(void);
int
ihdtv_init_rx_session(ihdtv_connection *connection, const char* address_1, const char* address_2, unsigned int port1, unsigned int port2, long mtu)
ihdtv_init_rx_session(ihdtv_connection * connection, const char *address_1,
const char *address_2, unsigned int port1,
unsigned int port2, long mtu)
{
connection->rx_port_1 = port1;
connection->rx_port_2 = port2;
connection->tx_port = 0;
connection->tx_socket_1 = 0;
connection->tx_socket_2 = 0;
connection->rx_port_1 = port1;
connection->rx_port_2 = port2;
connection->tx_port = 0;
connection->tx_socket_1 = 0;
connection->tx_socket_2 = 0;
connection->check_peer_ip = 0;
connection->check_peer_ip = 0;
if( (connection->rx_socket_1 = socket(AF_INET, SOCK_DGRAM, 0)) == -1 )
{
fprintf(stderr, "Error creating first recieving socket");
exit(1);
}
if ((connection->rx_socket_1 = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
fprintf(stderr, "Error creating first recieving socket");
exit(1);
}
if( (connection->rx_socket_2 = socket(AF_INET, SOCK_DGRAM, 0)) == -1 )
{
fprintf(stderr, "Error creating second recieving socket");
exit(1);
}
if ((connection->rx_socket_2 = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
fprintf(stderr, "Error creating second recieving socket");
exit(1);
}
if( address_1 != NULL) // we want to accept packets only from certain address so we connect() the socket
{
struct hostent *target = gethostbyname(address_1); // FIXME: should free?
if(target == NULL)
{
printf("Unknown target 1");
exit(1); // FIXME: maybe should just return but it requires not returnin ihdtv_connection
}
if (address_1 != NULL) // we want to accept packets only from certain address so we connect() the socket
{
struct hostent *target = gethostbyname(address_1); // FIXME: should free?
if (target == NULL) {
printf("Unknown target 1");
exit(1); // FIXME: maybe should just return but it requires not returnin ihdtv_connection
}
connection->peer_address_1 = *(struct in_addr *) target->h_addr;
connection->check_peer_ip = 1;
}
connection->peer_address_1 = *(struct in_addr *)target->h_addr;
if( address_2 != NULL) // we want to accept packets only from certain address so we connect() the socket
{
struct hostent *target = gethostbyname(address_2); // FIXME: should free?
if(target == NULL)
{
printf("Unknown target 2");
exit(1); // FIXME: maybe should just return but it requires not returnin ihdtv_connection
}
connection->check_peer_ip = 1;
}
connection->peer_address_2 = *(struct in_addr *) target->h_addr;
if (address_2 != NULL) // we want to accept packets only from certain address so we connect() the socket
{
struct hostent *target = gethostbyname(address_2); // FIXME: should free?
if (target == NULL) {
printf("Unknown target 2");
exit(1); // FIXME: maybe should just return but it requires not returnin ihdtv_connection
}
connection->check_peer_ip = 1;
}
connection->peer_address_2 = *(struct in_addr *)target->h_addr;
connection->check_peer_ip = 1;
}
struct sockaddr_in rx_address;
rx_address.sin_family = AF_INET;
rx_address.sin_addr.s_addr = htonl(INADDR_ANY);
rx_address.sin_port = htons(connection->rx_port_1);
memset(rx_address.sin_zero, '\0', sizeof(rx_address.sin_zero));
if( bind(connection->rx_socket_1, (struct sockaddr *) &rx_address, sizeof(rx_address)) == -1)
{
fprintf(stderr, "Error binding reciever to the first socket");
exit(1);
}
struct sockaddr_in rx_address;
rx_address.sin_family = AF_INET;
rx_address.sin_addr.s_addr = htonl(INADDR_ANY);
rx_address.sin_port = htons(connection->rx_port_1);
memset(rx_address.sin_zero, '\0', sizeof(rx_address.sin_zero));
if (bind
(connection->rx_socket_1, (struct sockaddr *)&rx_address,
sizeof(rx_address)) == -1) {
fprintf(stderr, "Error binding reciever to the first socket");
exit(1);
}
rx_address.sin_family = AF_INET;
rx_address.sin_addr.s_addr = htonl(INADDR_ANY);
rx_address.sin_port = htons(connection->rx_port_2);
memset(rx_address.sin_zero, '\0', sizeof(rx_address.sin_zero));
if( bind(connection->rx_socket_2, (struct sockaddr *) &rx_address, sizeof(rx_address)) == -1)
{
fprintf(stderr, "Error binding reciever to the second socket");
exit(1);
}
rx_address.sin_family = AF_INET;
rx_address.sin_addr.s_addr = htonl(INADDR_ANY);
rx_address.sin_port = htons(connection->rx_port_2);
memset(rx_address.sin_zero, '\0', sizeof(rx_address.sin_zero));
if (bind
(connection->rx_socket_2, (struct sockaddr *)&rx_address,
sizeof(rx_address)) == -1) {
fprintf(stderr, "Error binding reciever to the second socket");
exit(1);
}
connection->video_data_per_packet = mtu;
if (mtu == 0) {
fprintf(stderr, "Error: mtu must be > 0");
return -1;
}
connection->video_data_per_packet = mtu;
if(mtu == 0){
fprintf(stderr, "Error: mtu must be > 0");
return -1;
}
connection->bytes_per_frame = 5529600;
connection->bytes_per_half_frame = connection->bytes_per_frame / 2;
connection->bytes_per_frame = 5529600;
connection->bytes_per_half_frame = connection->bytes_per_frame / 2;
// we will count the number of packets/frame and the size of the last packet
connection->video_packets_per_half_frame =
connection->bytes_per_half_frame /
connection->video_data_per_packet;
if (connection->bytes_per_half_frame % connection->video_data_per_packet) // we have the final packet of each half of the frame smaller than video_data_per_packet
{
connection->video_data_per_last_packet =
connection->bytes_per_half_frame %
connection->video_data_per_packet;
connection->video_packets_per_half_frame++;
} else {
connection->video_data_per_last_packet =
connection->video_data_per_packet;
}
// we will count the number of packets/frame and the size of the last packet
connection->video_packets_per_half_frame = connection->bytes_per_half_frame / connection->video_data_per_packet;
if(connection->bytes_per_half_frame % connection->video_data_per_packet) // we have the final packet of each half of the frame smaller than video_data_per_packet
{
connection->video_data_per_last_packet = connection->bytes_per_half_frame % connection->video_data_per_packet;
connection->video_packets_per_half_frame++;
}
else
{
connection->video_data_per_last_packet = connection->video_data_per_packet;
}
connection->video_packets_per_frame = 2 * connection->video_packets_per_half_frame;
// fprintf(stderr,"Video_packets_per_frame=%u, video_data_per_packet=%d, video_data_per_last_packet %d\n", connection->video_packets_per_frame, (int)connection->video_data_per_packet, connection->video_data_per_last_packet);
connection->video_packets_per_frame =
2 * connection->video_packets_per_half_frame;
// fprintf(stderr,"Video_packets_per_frame=%u, video_data_per_packet=%d, video_data_per_last_packet %d\n", connection->video_packets_per_frame, (int)connection->video_data_per_packet, connection->video_data_per_last_packet);
/*
connection->video_packets_per_frame = 682;
@@ -168,327 +168,343 @@ ihdtv_init_rx_session(ihdtv_connection *connection, const char* address_1, const
connection->bytes_per_half_frame = connection->bytes_per_frame / 2;
*/
connection->current_frame = 0;
connection->pending_packet = 0;
connection->current_frame = 0;
connection->pending_packet = 0;
// set sockets to nonblocking(will utilitize 100% of a CPU)
if(fcntl(connection->rx_socket_1, F_SETFL, O_NONBLOCK) < 0)
{
fprintf(stderr, "Error setting rx_socket_1 as nonblocking\n");
exit(1);
}
// set sockets to nonblocking(will utilitize 100% of a CPU)
if (fcntl(connection->rx_socket_1, F_SETFL, O_NONBLOCK) < 0) {
fprintf(stderr, "Error setting rx_socket_1 as nonblocking\n");
exit(1);
}
if(fcntl(connection->rx_socket_2, F_SETFL, O_NONBLOCK) < 0)
{
fprintf(stderr, "Error setting rx_socket_2 as nonblocking\n");
exit(1);
}
return 0;
if (fcntl(connection->rx_socket_2, F_SETFL, O_NONBLOCK) < 0) {
fprintf(stderr, "Error setting rx_socket_2 as nonblocking\n");
exit(1);
}
return 0;
}
int
ihdtv_init_tx_session(ihdtv_connection *connection, const char* address_1, const char *address_2, long mtu)
ihdtv_init_tx_session(ihdtv_connection * connection, const char *address_1,
const char *address_2, long mtu)
{
connection->rx_port_1 = 0;
connection->rx_port_2 = 0;
connection->tx_port = 0; // not used so far
connection->tx_socket_1 = 0;
connection->tx_socket_2 = 0;
connection->rx_port_1 = 0;
connection->rx_port_2 = 0;
connection->tx_port = 0; // not used so far
connection->tx_socket_1 = 0;
connection->tx_socket_2 = 0;
struct hostent *target_1 = gethostbyname(address_1);
if(target_1 == NULL)
{
printf("Unknown target 1");
exit(1); // FIXME: maybe should just return but it requires not returnin ihdtv_connection
}
struct hostent *target_2 = gethostbyname(address_2);
if(target_2 == NULL)
{
printf("Unknown target 2");
exit(1); // FIXME: maybe should just return but it requires not returnin ihdtv_connection
}
struct hostent *target_1 = gethostbyname(address_1);
if (target_1 == NULL) {
printf("Unknown target 1");
exit(1); // FIXME: maybe should just return but it requires not returnin ihdtv_connection
}
if( (connection->tx_socket_1 = socket(AF_INET, SOCK_DGRAM, 0)) == -1 )
{
fprintf(stderr, "Error creating sending socket 1");
exit(1);
}
if( (connection->tx_socket_2 = socket(AF_INET, SOCK_DGRAM, 0)) == -1 )
{
fprintf(stderr, "Error creating sending socket 2");
exit(1);
}
struct hostent *target_2 = gethostbyname(address_2);
if (target_2 == NULL) {
printf("Unknown target 2");
exit(1); // FIXME: maybe should just return but it requires not returnin ihdtv_connection
}
if ((connection->tx_socket_1 = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
fprintf(stderr, "Error creating sending socket 1");
exit(1);
}
if ((connection->tx_socket_2 = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
fprintf(stderr, "Error creating sending socket 2");
exit(1);
}
connection->target_sockaddress_1.sin_family = AF_INET;
connection->target_sockaddress_1.sin_port = htons(3000); // FIXME: target port
connection->target_sockaddress_1.sin_addr = *((struct in_addr *) target_1->h_addr);
memset(connection->target_sockaddress_1.sin_zero, '\0', sizeof(connection->target_sockaddress_1.sin_zero));
connection->target_sockaddress_2.sin_family = AF_INET;
connection->target_sockaddress_2.sin_port = htons(3001); // FIXME: target port
connection->target_sockaddress_2.sin_addr = *((struct in_addr *) target_2->h_addr);
memset(connection->target_sockaddress_2.sin_zero, '\0', sizeof(connection->target_sockaddress_2.sin_zero));
connection->target_sockaddress_1.sin_family = AF_INET;
connection->target_sockaddress_1.sin_port = htons(3000); // FIXME: target port
connection->target_sockaddress_1.sin_addr =
*((struct in_addr *)target_1->h_addr);
memset(connection->target_sockaddress_1.sin_zero, '\0',
sizeof(connection->target_sockaddress_1.sin_zero));
connection->target_sockaddress_2.sin_family = AF_INET;
connection->target_sockaddress_2.sin_port = htons(3001); // FIXME: target port
connection->target_sockaddress_2.sin_addr =
*((struct in_addr *)target_2->h_addr);
memset(connection->target_sockaddress_2.sin_zero, '\0',
sizeof(connection->target_sockaddress_2.sin_zero));
connection->video_data_per_packet = mtu;
if(mtu == 0){
fprintf(stderr, "Error: mtu must be > 0");
return -1;
}
connection->video_data_per_packet = mtu;
if (mtu == 0) {
fprintf(stderr, "Error: mtu must be > 0");
return -1;
}
connection->bytes_per_frame = 5529600;
connection->bytes_per_half_frame = connection->bytes_per_frame / 2;
connection->bytes_per_frame = 5529600;
connection->bytes_per_half_frame = connection->bytes_per_frame / 2;
// we will count the number of packets/frame and the size of the last packet
connection->video_packets_per_half_frame =
connection->bytes_per_half_frame /
connection->video_data_per_packet;
if (connection->bytes_per_half_frame % connection->video_data_per_packet) // we have the final packet of each half of the frame smaller than video_data_per_packet
{
connection->video_data_per_last_packet =
connection->bytes_per_half_frame %
connection->video_data_per_packet;
connection->video_packets_per_half_frame++;
} else {
connection->video_data_per_last_packet =
connection->video_data_per_packet;
}
// we will count the number of packets/frame and the size of the last packet
connection->video_packets_per_half_frame = connection->bytes_per_half_frame / connection->video_data_per_packet;
if(connection->bytes_per_half_frame % connection->video_data_per_packet) // we have the final packet of each half of the frame smaller than video_data_per_packet
{
connection->video_data_per_last_packet = connection->bytes_per_half_frame % connection->video_data_per_packet;
connection->video_packets_per_half_frame++;
}
else
{
connection->video_data_per_last_packet = connection->video_data_per_packet;
}
connection->video_packets_per_frame = 2 * connection->video_packets_per_half_frame;
connection->video_packets_per_frame =
2 * connection->video_packets_per_half_frame;
// fprintf(stderr,"Video_packets_per_frame=%u, video_data_per_packet=%d, video_data_per_last_packet %d\n", connection->video_packets_per_frame, (int)connection->video_data_per_packet, connection->video_data_per_last_packet);
// fprintf(stderr,"Video_packets_per_frame=%u, video_data_per_packet=%d, video_data_per_last_packet %d\n", connection->video_packets_per_frame, (int)connection->video_data_per_packet, connection->video_data_per_last_packet);
connection->current_frame = 0;
connection->pending_packet = 0;
connection->current_frame = 0;
connection->pending_packet = 0;
return 0;
return 0;
}
int
ihdtv_send(ihdtv_connection *connection, struct video_frame *tx_frame, unsigned long buffer_length)
ihdtv_send(ihdtv_connection * connection, struct video_frame *tx_frame,
unsigned long buffer_length)
{
struct msghdr msg1, msg2;
struct msghdr msg1, msg2;
msg1.msg_name = &connection->target_sockaddress_1;
msg2.msg_name = &connection->target_sockaddress_2;
msg1.msg_name = &connection->target_sockaddress_1;
msg2.msg_name = &connection->target_sockaddress_2;
msg1.msg_namelen = sizeof(connection->target_sockaddress_1);
msg2.msg_namelen = sizeof(connection->target_sockaddress_2);
msg1.msg_namelen = sizeof(connection->target_sockaddress_1);
msg2.msg_namelen = sizeof(connection->target_sockaddress_2);
// header + data
struct iovec vector1[2];
struct iovec vector2[2];
// header + data
struct iovec vector1[2];
struct iovec vector2[2];
msg1.msg_iov = &vector1;
msg2.msg_iov = &vector2;
msg1.msg_iov = &vector1;
msg2.msg_iov = &vector2;
msg1.msg_iovlen = 2;
msg2.msg_iovlen = 2;
msg1.msg_iovlen = 2;
msg2.msg_iovlen = 2;
msg1.msg_control = 0;
msg2.msg_control = 0;
msg1.msg_controllen = 0;
msg2.msg_controllen = 0;
msg1.msg_flags = 0;
msg2.msg_flags = 0;
// only used for headers
ihdtv_packet packet_1;
ihdtv_packet packet_2;
msg1.msg_control = 0;
msg2.msg_control = 0;
msg1.msg_controllen = 0;
msg2.msg_controllen = 0;
msg1.msg_flags = 0;
msg2.msg_flags = 0;
packet_1.frame_number = connection->current_frame;
packet_2.frame_number = connection->current_frame;
// only used for headers
ihdtv_packet packet_1;
ihdtv_packet packet_2;
packet_1.stream_id = 0; // top half
packet_2.stream_id = 1; // bottom half
packet_1.frame_number = connection->current_frame;
packet_2.frame_number = connection->current_frame;
unsigned int offset_absolut_1 = 0; // offset to buffer ( in bytes )
unsigned int offset_absolut_2 = connection->bytes_per_half_frame;
packet_1.stream_id = 0; // top half
packet_2.stream_id = 1; // bottom half
unsigned int packet_relative_offset=0; // this is the number we put into buffer
unsigned int offset_absolut_1 = 0; // offset to buffer ( in bytes )
unsigned int offset_absolut_2 = connection->bytes_per_half_frame;
unsigned int i;
for(i = 0; i < connection->video_packets_per_half_frame - 1;i++)
{
packet_1.offset = packet_relative_offset;
vector1[0].iov_base = &packet_1;
vector1[0].iov_len = 16; // we only use the header
vector1[1].iov_base = (tx_frame->data) + offset_absolut_1;
vector1[1].iov_len = connection->video_data_per_packet;
if(sendmsg(connection->tx_socket_1, &msg1, 0) == -1)
{
perror("Sending data to address 1");
exit(1);
}
unsigned int packet_relative_offset = 0; // this is the number we put into buffer
unsigned int i;
for (i = 0; i < connection->video_packets_per_half_frame - 1; i++) {
packet_1.offset = packet_relative_offset;
vector1[0].iov_base = &packet_1;
vector1[0].iov_len = 16; // we only use the header
vector1[1].iov_base = (tx_frame->data) + offset_absolut_1;
vector1[1].iov_len = connection->video_data_per_packet;
if (sendmsg(connection->tx_socket_1, &msg1, 0) == -1) {
perror("Sending data to address 1");
exit(1);
}
packet_2.offset = packet_relative_offset;
vector2[0].iov_base = &packet_2;
vector2[0].iov_len = 16; // we only use the header
vector2[1].iov_base = (tx_frame->data) + offset_absolut_2;
vector2[1].iov_len = connection->video_data_per_packet;
if(sendmsg(connection->tx_socket_2, &msg2, 0) == -1)
{
perror("Sending data to address 2");
exit(1);
}
packet_2.offset = packet_relative_offset;
vector2[0].iov_base = &packet_2;
vector2[0].iov_len = 16; // we only use the header
vector2[1].iov_base = (tx_frame->data) + offset_absolut_2;
vector2[1].iov_len = connection->video_data_per_packet;
if (sendmsg(connection->tx_socket_2, &msg2, 0) == -1) {
perror("Sending data to address 2");
exit(1);
}
++packet_relative_offset;
offset_absolut_1 += connection->video_data_per_packet;
offset_absolut_2 += connection->video_data_per_packet;
}
++packet_relative_offset;
offset_absolut_1 += connection->video_data_per_packet;
offset_absolut_2 += connection->video_data_per_packet;
}
packet_1.offset = packet_relative_offset;
vector1[0].iov_base = &packet_1;
vector1[0].iov_len = 16; // we only use the header
vector1[1].iov_base = (tx_frame->data) + offset_absolut_1;
vector1[1].iov_len = connection->video_data_per_last_packet;
if(sendmsg(connection->tx_socket_1, &msg1, 0) == -1)
{
perror("Sending data to address 1");
exit(1);
}
packet_1.offset = packet_relative_offset;
vector1[0].iov_base = &packet_1;
vector1[0].iov_len = 16; // we only use the header
vector1[1].iov_base = (tx_frame->data) + offset_absolut_1;
vector1[1].iov_len = connection->video_data_per_last_packet;
if (sendmsg(connection->tx_socket_1, &msg1, 0) == -1) {
perror("Sending data to address 1");
exit(1);
}
packet_2.offset = packet_relative_offset;
vector2[0].iov_base = &packet_2;
vector2[0].iov_len = 16; // we only use the header
vector2[1].iov_base = (tx_frame->data) + offset_absolut_2;
vector2[1].iov_len = connection->video_data_per_last_packet;
if (sendmsg(connection->tx_socket_2, &msg2, 0) == -1) {
perror("Sending data to address 2");
exit(1);
}
packet_2.offset = packet_relative_offset;
vector2[0].iov_base = &packet_2;
vector2[0].iov_len = 16; // we only use the header
vector2[1].iov_base = (tx_frame->data) + offset_absolut_2;
vector2[1].iov_len = connection->video_data_per_last_packet;
if(sendmsg(connection->tx_socket_2, &msg2, 0) == -1)
{
perror("Sending data to address 2");
exit(1);
}
++(connection->current_frame);
++(connection->current_frame);
}
inline static int
packet_to_buffer(const ihdtv_connection *connection, char *buffer, const unsigned long buffer_length, const ihdtv_packet *packet, const int packet_length) // returns number of written packets (1 or 0)
inline static int packet_to_buffer(const ihdtv_connection * connection, char *buffer, const unsigned long buffer_length, const ihdtv_packet * packet, const int packet_length) // returns number of written packets (1 or 0)
{
if( buffer_length < ( packet->offset * connection->video_data_per_packet + (packet_length - 16)) )
return 0;
if( packet->stream_id == 0)
{
memcpy(buffer + (packet->offset) * connection->video_data_per_packet, packet->data, packet_length - 16);
return 1;
}
if (buffer_length <
(packet->offset * connection->video_data_per_packet +
(packet_length - 16)))
return 0;
if( packet->stream_id == 1)
{
memcpy(buffer + (packet->offset) * connection->video_data_per_packet + connection->bytes_per_half_frame, packet->data, packet_length - 16);
return 1;
}
if (packet->stream_id == 0) {
memcpy(buffer +
(packet->offset) * connection->video_data_per_packet,
packet->data, packet_length - 16);
return 1;
}
return 0;
if (packet->stream_id == 1) {
memcpy(buffer +
(packet->offset) * connection->video_data_per_packet +
connection->bytes_per_half_frame, packet->data,
packet_length - 16);
return 1;
}
return 0;
}
int
ihdtv_recieve(ihdtv_connection *connection, char *buffer, const unsigned long buffer_length)
ihdtv_recieve(ihdtv_connection * connection, char *buffer,
const unsigned long buffer_length)
{
int packets_number = 0;
int packets_number = 0;
ihdtv_packet packet;
int num_bytes;
struct sockaddr_in sender_address; // where did the packets come from
socklen_t sender_address_length = sizeof(sender_address);
ihdtv_packet packet;
int num_bytes;
struct sockaddr_in sender_address; // where did the packets come from
socklen_t sender_address_length = sizeof(sender_address);
int dont_check_ip = !(connection->check_peer_ip);
int dont_check_ip = !(connection->check_peer_ip);
if(buffer == NULL)
{
fprintf(stderr, "iHDTV reciever: buffer is empty, not recieving.\n");
return -1;
}
if (buffer == NULL) {
fprintf(stderr,
"iHDTV reciever: buffer is empty, not recieving.\n");
return -1;
}
// memset(buffer, 0, buffer_length); // make holes in frame more visible -- your computer might not be fast enough for this, if you experience performance problems, try to comment this out
// memset(buffer, 0, buffer_length); // make holes in frame more visible -- your computer might not be fast enough for this, if you experience performance problems, try to comment this out
// if we have some data from previous session, we use it
if (connection->pending_packet) {
packet_to_buffer(connection, buffer, buffer_length,
&(connection->ppacket),
connection->ppacket_size);
// printf("processing pending packet %ld\n", connection->ppacket.frame_number); // FIXME: delete this
// if we have some data from previous session, we use it
if(connection->pending_packet)
{
packet_to_buffer(connection, buffer, buffer_length, &(connection->ppacket), connection->ppacket_size);
// printf("processing pending packet %ld\n", connection->ppacket.frame_number); // FIXME: delete this
connection->pending_packet = 0;
++packets_number;
}
connection->pending_packet = 0;
++packets_number;
}
while (1) {
if ((num_bytes =
recvfrom(connection->rx_socket_1, &packet, sizeof(packet),
0, (struct sockaddr *)&sender_address,
&sender_address_length)) > -1) {
if ((dont_check_ip)
|| (connection->peer_address_1.s_addr ==
sender_address.sin_addr.s_addr)
|| (connection->peer_address_2.s_addr ==
sender_address.sin_addr.s_addr)) {
if (packet.stream_id == 0 || packet.stream_id == 1) { // it is strange, but ihdtv seems to be sending video and audio with different frame numbers in some cases, so we only work with video here
if ((connection->current_frame < packet.frame_number) || (packet.frame_number + 10 < connection->current_frame)) // we just recieved frame we didn't expect
{
// printf("current frame: %llu (packets: %u) incoming frame: %llu\n", connection->current_frame, packets_number, packet.frame_number);
connection->current_frame =
packet.frame_number;
connection->pending_packet++;
connection->ppacket = packet;
connection->ppacket_size =
num_bytes;
while(1)
{
if( (num_bytes = recvfrom(connection->rx_socket_1, &packet, sizeof(packet), 0, (struct sockaddr *)& sender_address, &sender_address_length)) > -1)
{
if( (dont_check_ip) || (connection->peer_address_1.s_addr == sender_address.sin_addr.s_addr) || (connection->peer_address_2.s_addr == sender_address.sin_addr.s_addr))
{
if( packet.stream_id == 0 || packet.stream_id == 1){ // it is strange, but ihdtv seems to be sending video and audio with different frame numbers in some cases, so we only work with video here
if((connection->current_frame < packet.frame_number) || (packet.frame_number + 10 < connection->current_frame )) // we just recieved frame we didn't expect
{
// printf("current frame: %llu (packets: %u) incoming frame: %llu\n", connection->current_frame, packets_number, packet.frame_number);
connection->current_frame = packet.frame_number;
connection->pending_packet++;
connection->ppacket = packet;
connection->ppacket_size = num_bytes;
break;
}
break;
}
if (packet.frame_number ==
connection->current_frame)
packets_number +=
packet_to_buffer(connection,
buffer,
buffer_length,
&packet,
num_bytes);
if(packet.frame_number == connection->current_frame)
packets_number += packet_to_buffer(connection, buffer, buffer_length, &packet, num_bytes);
if (packets_number == connection->video_packets_per_frame) // we have all packets of a frame
{
connection->current_frame++;
break;
}
}
}
if(packets_number == connection->video_packets_per_frame) // we have all packets of a frame
{
connection->current_frame++;
break;
}
}
}
} else if (errno != EWOULDBLOCK) {
fprintf(stderr, "Error recieving packet\n");
exit(1);
}
}
else
if(errno != EWOULDBLOCK)
{
fprintf(stderr, "Error recieving packet\n");
exit(1);
}
if ((num_bytes =
recvfrom(connection->rx_socket_2, &packet, sizeof(packet),
0, (struct sockaddr *)&sender_address,
&sender_address_length)) > -1) {
if ((dont_check_ip)
|| (connection->peer_address_1.s_addr ==
sender_address.sin_addr.s_addr)
|| (connection->peer_address_2.s_addr ==
sender_address.sin_addr.s_addr)) {
if (packet.stream_id == 0 || packet.stream_id == 1) { // it is strange, but ihdtv seems to be sending video and audio with different frame numbers in some cases, so we only work with video here
if ((connection->current_frame < packet.frame_number) || (packet.frame_number + 10 < connection->current_frame)) // we just recieved frame we didn't expect
{
// printf("current frame: %llu (packets: %u) incoming frame: %llu\n", connection->current_frame, packets_number, packet.frame_number);
connection->current_frame =
packet.frame_number;
connection->pending_packet++;
connection->ppacket = packet;
connection->ppacket_size =
num_bytes;
if( (num_bytes = recvfrom(connection->rx_socket_2, &packet, sizeof(packet), 0, (struct sockaddr *)& sender_address, &sender_address_length)) > -1)
{
if( (dont_check_ip) || (connection->peer_address_1.s_addr == sender_address.sin_addr.s_addr) || (connection->peer_address_2.s_addr == sender_address.sin_addr.s_addr))
{
if( packet.stream_id == 0 || packet.stream_id == 1){ // it is strange, but ihdtv seems to be sending video and audio with different frame numbers in some cases, so we only work with video here
if((connection->current_frame < packet.frame_number) || (packet.frame_number + 10 < connection->current_frame)) // we just recieved frame we didn't expect
{
// printf("current frame: %llu (packets: %u) incoming frame: %llu\n", connection->current_frame, packets_number, packet.frame_number);
connection->current_frame = packet.frame_number;
connection->pending_packet++;
connection->ppacket = packet;
connection->ppacket_size = num_bytes;
break;
}
if (packet.frame_number ==
connection->current_frame)
packets_number +=
packet_to_buffer(connection,
buffer,
buffer_length,
&packet,
num_bytes);
break;
}
if(packet.frame_number == connection->current_frame)
packets_number += packet_to_buffer(connection, buffer, buffer_length, &packet, num_bytes);
if (packets_number == connection->video_packets_per_frame) // we have all packets of a frame
{
connection->current_frame++;
break;
}
}
}
if(packets_number == connection->video_packets_per_frame) // we have all packets of a frame
{
connection->current_frame++;
break;
}
}
}
} else if (errno != EWOULDBLOCK) {
fprintf(stderr, "Error recieving packet\n");
exit(1);
}
}
}
else
if(errno != EWOULDBLOCK)
{
fprintf(stderr, "Error recieving packet\n");
exit(1);
}
}
return 0;
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -22,17 +22,15 @@
#define SECS_BETWEEN_1900_1970 2208988800u
void
ntp64_time(uint32_t *ntp_sec, uint32_t *ntp_frac)
void ntp64_time(uint32_t * ntp_sec, uint32_t * ntp_frac)
{
struct timeval now;
uint32_t tmp; /* now.tv_usec is signed on many platforms; compensate */
uint32_t tmp; /* now.tv_usec is signed on many platforms; compensate */
gettimeofday(&now, NULL);
/* NB ntp_frac is in units of 1 / (2^32 - 1) secs. */
*ntp_sec = now.tv_sec + SECS_BETWEEN_1900_1970;
tmp = now.tv_usec;
*ntp_sec = now.tv_sec + SECS_BETWEEN_1900_1970;
tmp = now.tv_usec;
*ntp_frac = (tmp << 12) + (tmp << 8) - ((tmp * 3650) >> 6);
}

View File

@@ -64,7 +64,7 @@
#include "config_unix.h"
#include "config_win32.h"
#include "debug.h"
#include "rtp/rtp.h" /* Needed by pbuf.h */
#include "rtp/rtp.h" /* Needed by pbuf.h */
#include "rtp/pbuf.h"
#include "tfrc.h"
#include "pdb.h"
@@ -73,19 +73,19 @@
#define PDB_NODE_MAGIC 0x01010101
typedef struct s_pdb_node {
uint32_t key;
void *data;
uint32_t key;
void *data;
struct s_pdb_node *parent;
struct s_pdb_node *left;
struct s_pdb_node *right;
uint32_t magic;
uint32_t magic;
} pdb_node_t;
struct pdb {
struct pdb {
pdb_node_t *root;
pdb_node_t *iter;
uint32_t magic;
int count;
pdb_node_t *iter;
uint32_t magic;
int count;
};
/*****************************************************************************/
@@ -97,10 +97,9 @@ struct pdb {
static int pdb_count;
static void
pdb_validate_node(pdb_node_t *node, pdb_node_t *parent)
static void pdb_validate_node(pdb_node_t * node, pdb_node_t * parent)
{
assert(node->magic == BTREE_NODE_MAGIC);
assert(node->magic == BTREE_NODE_MAGIC);
assert(node->parent == parent);
pdb_count++;
if (node->left != NULL) {
@@ -111,8 +110,7 @@ pdb_validate_node(pdb_node_t *node, pdb_node_t *parent)
}
}
static void
pdb_validate(struct pdb *t)
static void pdb_validate(struct pdb *t)
{
assert(t->magic == BTREE_MAGIC);
#ifdef DEBUG
@@ -124,25 +122,22 @@ pdb_validate(struct pdb *t)
#endif
}
/*****************************************************************************/
/* Utility functions */
/*****************************************************************************/
static pdb_node_t*
pdb_min(pdb_node_t *x)
static pdb_node_t *pdb_min(pdb_node_t * x)
{
if (x == NULL) {
return NULL;
}
while(x->left) {
while (x->left) {
x = x->left;
}
return x;
}
static pdb_node_t*
pdb_successor(pdb_node_t *x)
static pdb_node_t *pdb_successor(pdb_node_t * x)
{
pdb_node_t *y;
@@ -159,8 +154,7 @@ pdb_successor(pdb_node_t *x)
return y;
}
static pdb_node_t*
pdb_search(pdb_node_t *x, uint32_t key)
static pdb_node_t *pdb_search(pdb_node_t * x, uint32_t key)
{
while (x != NULL && key != x->key) {
if (key < x->key) {
@@ -169,14 +163,14 @@ pdb_search(pdb_node_t *x, uint32_t key)
x = x->right;
}
}
return x;
return x;
}
static void
pdb_insert_node(struct pdb *tree, pdb_node_t *z) {
static void pdb_insert_node(struct pdb *tree, pdb_node_t * z)
{
pdb_node_t *x, *y;
pdb_validate(tree);
pdb_validate(tree);
y = NULL;
x = tree->root;
while (x != NULL) {
@@ -197,16 +191,15 @@ pdb_insert_node(struct pdb *tree, pdb_node_t *z) {
} else {
y->right = z;
}
tree->count++;
pdb_validate(tree);
tree->count++;
pdb_validate(tree);
}
static pdb_node_t*
pdb_delete_node(struct pdb *tree, pdb_node_t *z)
static pdb_node_t *pdb_delete_node(struct pdb *tree, pdb_node_t * z)
{
pdb_node_t *x, *y;
pdb_validate(tree);
pdb_validate(tree);
if (z->left == NULL || z->right == NULL) {
y = z;
} else {
@@ -231,109 +224,105 @@ pdb_delete_node(struct pdb *tree, pdb_node_t *z)
y->parent->right = x;
}
z->key = y->key;
z->key = y->key;
z->data = y->data;
tree->count--;
tree->count--;
pdb_validate(tree);
pdb_validate(tree);
return y;
}
/*****************************************************************************/
struct pdb *
pdb_init(void)
struct pdb *pdb_init(void)
{
struct pdb *db = malloc(sizeof(struct pdb));
if (db != NULL) {
db->magic = PDB_MAGIC;
db->count = 0;
db->root = NULL;
db->iter = NULL;
}
return db;
struct pdb *db = malloc(sizeof(struct pdb));
if (db != NULL) {
db->magic = PDB_MAGIC;
db->count = 0;
db->root = NULL;
db->iter = NULL;
}
return db;
}
void
pdb_destroy(struct pdb **db_p)
void pdb_destroy(struct pdb **db_p)
{
struct pdb *db = *db_p;
struct pdb *db = *db_p;
pdb_validate(db);
if (db->root != NULL) {
printf("WARNING: participant database not empty - cannot destroy\n");
// TODO: participants should be removed using pdb_remove()
}
pdb_validate(db);
if (db->root != NULL) {
printf
("WARNING: participant database not empty - cannot destroy\n");
// TODO: participants should be removed using pdb_remove()
}
free(db);
*db_p = NULL;
free(db);
*db_p = NULL;
}
static struct pdb_e *
pdb_create_item(uint32_t ssrc)
static struct pdb_e *pdb_create_item(uint32_t ssrc)
{
struct pdb_e *p = malloc(sizeof(struct pdb_e));
if (p != NULL) {
gettimeofday(&(p->creation_time), NULL);
p->ssrc = ssrc;
p->sdes_cname = NULL;
p->sdes_name = NULL;
p->sdes_email = NULL;
p->sdes_phone = NULL;
p->sdes_loc = NULL;
p->sdes_tool = NULL;
p->sdes_note = NULL;
p->video_decoder_state = NULL;
p->pt = 255;
p->playout_buffer = pbuf_init();
p->tfrc_state = tfrc_init(p->creation_time);
}
return p;
struct pdb_e *p = malloc(sizeof(struct pdb_e));
if (p != NULL) {
gettimeofday(&(p->creation_time), NULL);
p->ssrc = ssrc;
p->sdes_cname = NULL;
p->sdes_name = NULL;
p->sdes_email = NULL;
p->sdes_phone = NULL;
p->sdes_loc = NULL;
p->sdes_tool = NULL;
p->sdes_note = NULL;
p->video_decoder_state = NULL;
p->pt = 255;
p->playout_buffer = pbuf_init();
p->tfrc_state = tfrc_init(p->creation_time);
}
return p;
}
int
pdb_add(struct pdb *db, uint32_t ssrc)
int pdb_add(struct pdb *db, uint32_t ssrc)
{
/* Add an item to the participant database, indexed by ssrc. */
/* Returns 0 on success, 1 if the participant is already in */
/* the database, 2 for other failures. */
pdb_node_t *x;
struct pdb_e *i;
/* Add an item to the participant database, indexed by ssrc. */
/* Returns 0 on success, 1 if the participant is already in */
/* the database, 2 for other failures. */
pdb_node_t *x;
struct pdb_e *i;
pdb_validate(db);
pdb_validate(db);
x = pdb_search(db->root, ssrc);
if (x != NULL) {
debug_msg("Item already exists - ssrc %x\n", ssrc);
return 1;
}
i = pdb_create_item(ssrc);
if (i == NULL) {
debug_msg("Unable to create database entry - ssrc %x\n", ssrc);
return 2;
}
i = pdb_create_item(ssrc);
if (i == NULL) {
debug_msg("Unable to create database entry - ssrc %x\n", ssrc);
return 2;
}
x = (pdb_node_t *) malloc(sizeof(pdb_node_t));
x->key = ssrc;
x->data = i;
x->key = ssrc;
x->data = i;
x->parent = NULL;
x->left = NULL;
x->right = NULL;
x->magic = BTREE_NODE_MAGIC;
x->left = NULL;
x->right = NULL;
x->magic = BTREE_NODE_MAGIC;
pdb_insert_node(db, x);
debug_msg("Added participant %x\n", ssrc);
debug_msg("Added participant %x\n", ssrc);
return 0;
}
struct pdb_e *
pdb_get(struct pdb *db, uint32_t ssrc)
struct pdb_e *pdb_get(struct pdb *db, uint32_t ssrc)
{
/* Return a pointer to the item indexed by ssrc, or NULL if */
/* the item is not present in the database. */
/* Return a pointer to the item indexed by ssrc, or NULL if */
/* the item is not present in the database. */
pdb_node_t *x;
pdb_validate(db);
pdb_validate(db);
x = pdb_search(db->root, ssrc);
if (x != NULL) {
return x->data;
@@ -341,13 +330,12 @@ pdb_get(struct pdb *db, uint32_t ssrc)
return NULL;
}
int
pdb_remove(struct pdb *db, uint32_t ssrc, struct pdb_e **item)
int pdb_remove(struct pdb *db, uint32_t ssrc, struct pdb_e **item)
{
/* Remove the item indexed by ssrc. Return zero on success. */
/* Remove the item indexed by ssrc. Return zero on success. */
pdb_node_t *x;
pdb_validate(db);
pdb_validate(db);
x = pdb_search(db->root, ssrc);
if (x == NULL) {
debug_msg("Item not on tree - ssrc %ul\n", ssrc);
@@ -355,10 +343,10 @@ pdb_remove(struct pdb *db, uint32_t ssrc, struct pdb_e **item)
return 1;
}
/* Note value that gets freed is not necessarily the the same as node
* that gets removed from tree since there is an optimization to avoid
* pointer updates in tree which means sometimes we just copy key and
* data from one node to another.
/* Note value that gets freed is not necessarily the the same as node
* that gets removed from tree since there is an optimization to avoid
* pointer updates in tree which means sometimes we just copy key and
* data from one node to another.
*/
*item = x->data;
x = pdb_delete_node(db, x);
@@ -366,35 +354,30 @@ pdb_remove(struct pdb *db, uint32_t ssrc, struct pdb_e **item)
return 0;
}
/*
* Iterator functions
*/
struct pdb_e *
pdb_iter_init(struct pdb *db)
struct pdb_e *pdb_iter_init(struct pdb *db)
{
if (db->root == NULL) {
return NULL; /* The database is empty */
}
db->iter = pdb_min(db->root);
return db->iter->data;
if (db->root == NULL) {
return NULL; /* The database is empty */
}
db->iter = pdb_min(db->root);
return db->iter->data;
}
struct pdb_e *
pdb_iter_next(struct pdb *db)
struct pdb_e *pdb_iter_next(struct pdb *db)
{
assert(db->iter != NULL);
db->iter = pdb_successor(db->iter);
if (db->iter == NULL) {
return NULL;
}
return db->iter->data;
assert(db->iter != NULL);
db->iter = pdb_successor(db->iter);
if (db->iter == NULL) {
return NULL;
}
return db->iter->data;
}
void
pdb_iter_done(struct pdb *db)
void pdb_iter_done(struct pdb *db)
{
db->iter = NULL;
db->iter = NULL;
}

View File

@@ -55,24 +55,23 @@
//#define DEBUG 1
//#define DEBUG_TIMING 1
void
decode_frame(struct coded_data *cdata, struct video_frame *frame)
void decode_frame(struct coded_data *cdata, struct video_frame *frame)
{
uint32_t width;
uint32_t height;
uint32_t offset;
int len;
int len;
codec_t color_spec;
rtp_packet *pckt;
unsigned char *source;
payload_hdr_t *hdr;
payload_hdr_t *hdr;
uint32_t data_pos;
#ifdef DEBUG_TIMING
struct timeval tv,tv1;
int packets=0;
struct timeval tv, tv1;
int packets = 0;
#endif
#ifdef DEBUG
long pos=0;
long pos = 0;
#endif
#ifdef DEBUG_TIMING
gettimeofday(&tv, NULL);
@@ -83,7 +82,7 @@ decode_frame(struct coded_data *cdata, struct video_frame *frame)
packets++;
#endif
pckt = cdata->data;
hdr = (payload_hdr_t *)pckt->data;
hdr = (payload_hdr_t *) pckt->data;
width = ntohs(hdr->width);
height = ntohs(hdr->height);
color_spec = hdr->colorspc;
@@ -93,44 +92,53 @@ decode_frame(struct coded_data *cdata, struct video_frame *frame)
/* Critical section
* each thread *MUST* wait here if this condition is true
*/
if(!(frame->width == width &&
frame->height == height &&
frame->color_spec == color_spec)) {
frame->reconfigure(frame->state, width, height, color_spec);
frame->src_linesize = vc_getsrc_linesize(width, color_spec);
if (!(frame->width == width &&
frame->height == height &&
frame->color_spec == color_spec)) {
frame->reconfigure(frame->state, width, height,
color_spec);
frame->src_linesize =
vc_getsrc_linesize(width, color_spec);
}
/* End of critical section */
#ifdef DEBUG
fprintf(stdout, "Setup: src line size: %d, dst line size %d, pitch %d\n",
frame->src_linesize, frame->dst_linesize, frame->dst_pitch);
int b=0;
fprintf(stdout,
"Setup: src line size: %d, dst line size %d, pitch %d\n",
frame->src_linesize, frame->dst_linesize,
frame->dst_pitch);
int b = 0;
#endif
/* MAGIC, don't touch it, you definitely break it */
int y = (data_pos / frame->src_linesize)*frame->dst_pitch;
int y = (data_pos / frame->src_linesize) * frame->dst_pitch;
int s_x = data_pos % frame->src_linesize;
int d_x = ((int)((s_x)/frame->src_bpp))*frame->dst_bpp;
int d_x = ((int)((s_x) / frame->src_bpp)) * frame->dst_bpp;
source = pckt->data + sizeof(payload_hdr_t);
#ifdef DEBUG
fprintf(stdout, "Computed start x %d, %d (%d %d), start y %d\n", s_x, d_x, (int)(s_x/frame->src_bpp),
(int)(d_x/frame->dst_bpp), y/frame->dst_linesize);
fprintf(stdout, "Computed start x %d, %d (%d %d), start y %d\n",
s_x, d_x, (int)(s_x / frame->src_bpp),
(int)(d_x / frame->dst_bpp), y / frame->dst_linesize);
#endif
while(len > 0){
int l = ((int)(len/frame->src_bpp))*frame->dst_bpp;
if(l + d_x > frame->dst_linesize) {
while (len > 0) {
int l = ((int)(len / frame->src_bpp)) * frame->dst_bpp;
if (l + d_x > frame->dst_linesize) {
l = frame->dst_linesize - d_x;
}
offset = y + d_x;
if(l + offset < frame->data_len) {
if (l + offset < frame->data_len) {
#ifdef DEBUG
if(b < 5) {
fprintf(stdout, "Computed offset: %d, original offset %d, memcpy length %d (pixels %d), original length %d, stored length %d, next line %d\n",
offset, data_pos, l, (int)(l/frame->dst_bpp), len, pos, offset + l);
if (b < 5) {
fprintf(stdout,
"Computed offset: %d, original offset %d, memcpy length %d (pixels %d), original length %d, stored length %d, next line %d\n",
offset, data_pos, l,
(int)(l / frame->dst_bpp), len,
pos, offset + l);
b++;
}
}
#endif
frame->decoder(frame->data+offset, source, l,
frame->rshift, frame->gshift, frame->bshift);
frame->decoder(frame->data + offset, source, l,
frame->rshift, frame->gshift,
frame->bshift);
len -= frame->src_linesize - s_x;
source += frame->src_linesize - s_x;
#ifdef DEBUG
@@ -139,23 +147,24 @@ decode_frame(struct coded_data *cdata, struct video_frame *frame)
#endif
} else {
#ifdef DEBUG
fprintf(stderr, "Discarding data, framebuffer too small.\n");
fprintf(stderr,
"Discarding data, framebuffer too small.\n");
#endif
len = 0;
}
d_x = 0; /* next line from beginning */
d_x = 0; /* next line from beginning */
s_x = 0;
y += frame->dst_pitch; /* next line */
y += frame->dst_pitch; /* next line */
}
cdata = cdata->nxt;
}
cdata = cdata->nxt;
}
#ifdef DEBUG_TIMING
gettimeofday(&tv1, NULL);
fprintf(stdout, "Frame encoded in %fms, %d packets\n", (tv1.tv_usec - tv.tv_usec)/1000.0, packets);
gettimeofday(&tv1, NULL);
fprintf(stdout, "Frame encoded in %fms, %d packets\n",
(tv1.tv_usec - tv.tv_usec) / 1000.0, packets);
#endif
#ifdef DEBUG
fprintf(stdout, "Frame end\n");
fprintf(stdout, "Frame end\n");
#endif
}

File diff suppressed because it is too large Load Diff

View File

@@ -73,316 +73,314 @@
extern long frame_begin[2];
struct pbuf_node {
struct pbuf_node *nxt;
struct pbuf_node *prv;
uint32_t rtp_timestamp; /* RTP timestamp for the frame */
struct timeval arrival_time; /* Arrival time of first packet in frame */
struct timeval playout_time; /* Playout time for the frame */
struct coded_data *cdata; /* */
int decoded; /* Non-zero if we've decoded this frame */
int mbit; /* determines if mbit of frame had been seen */
uint32_t magic; /* For debugging */
struct pbuf_node *nxt;
struct pbuf_node *prv;
uint32_t rtp_timestamp; /* RTP timestamp for the frame */
struct timeval arrival_time; /* Arrival time of first packet in frame */
struct timeval playout_time; /* Playout time for the frame */
struct coded_data *cdata; /* */
int decoded; /* Non-zero if we've decoded this frame */
int mbit; /* determines if mbit of frame had been seen */
uint32_t magic; /* For debugging */
};
struct pbuf {
struct pbuf_node *frst;
struct pbuf_node *last;
struct pbuf_node *frst;
struct pbuf_node *last;
};
/*********************************************************************************/
static void
pbuf_validate(struct pbuf *playout_buf)
static void pbuf_validate(struct pbuf *playout_buf)
{
/* Run through the entire playout buffer, checking pointers, etc. */
/* Only used in debugging mode, since it's a lot of overhead [csp] */
/* Run through the entire playout buffer, checking pointers, etc. */
/* Only used in debugging mode, since it's a lot of overhead [csp] */
#ifdef NDEF
struct pbuf_node *cpb, *ppb;
struct coded_data *ccd, *pcd;
struct pbuf_node *cpb, *ppb;
struct coded_data *ccd, *pcd;
cpb = playout_buf->frst;
ppb = NULL;
while (cpb != NULL) {
assert(cpb->magic == PBUF_MAGIC);
assert(cpb->prv == ppb);
if (cpb->prv != NULL) {
assert(cpb->prv->nxt == cpb);
/* stored in RTP timestamp order */
assert(cpb->rtp_timestamp > ppb->rtp_timestamp);
/* stored in playout time order */
/* TODO: eventually check why is this assert always failng */
// assert(tv_gt(cpb->ptime, ppb->ptime));
}
if (cpb->nxt != NULL) {
assert(cpb->nxt->prv == cpb);
} else {
assert(cpb = playout_buf->last);
}
if (cpb->cdata != NULL) {
/* We have coded data... check all the pointers on that list too */
ccd = cpb->cdata;
pcd = NULL;
while (ccd != NULL) {
assert(ccd->prv == pcd);
if (ccd->prv != NULL) {
assert(ccd->prv->nxt == ccd);
/* list is descending - cant really check this now*/
//assert(ccd->seqno < pcd->seqno);
assert(ccd->data != NULL);
}
if (ccd->nxt != NULL) {
assert(ccd->nxt->prv == ccd);
}
pcd = ccd;
ccd = ccd->nxt;
}
}
ppb = cpb;
cpb = cpb->nxt;
}
cpb = playout_buf->frst;
ppb = NULL;
while (cpb != NULL) {
assert(cpb->magic == PBUF_MAGIC);
assert(cpb->prv == ppb);
if (cpb->prv != NULL) {
assert(cpb->prv->nxt == cpb);
/* stored in RTP timestamp order */
assert(cpb->rtp_timestamp > ppb->rtp_timestamp);
/* stored in playout time order */
/* TODO: eventually check why is this assert always failng */
// assert(tv_gt(cpb->ptime, ppb->ptime));
}
if (cpb->nxt != NULL) {
assert(cpb->nxt->prv == cpb);
} else {
assert(cpb = playout_buf->last);
}
if (cpb->cdata != NULL) {
/* We have coded data... check all the pointers on that list too */
ccd = cpb->cdata;
pcd = NULL;
while (ccd != NULL) {
assert(ccd->prv == pcd);
if (ccd->prv != NULL) {
assert(ccd->prv->nxt == ccd);
/* list is descending - cant really check this now */
//assert(ccd->seqno < pcd->seqno);
assert(ccd->data != NULL);
}
if (ccd->nxt != NULL) {
assert(ccd->nxt->prv == ccd);
}
pcd = ccd;
ccd = ccd->nxt;
}
}
ppb = cpb;
cpb = cpb->nxt;
}
#else
UNUSED(playout_buf);
UNUSED(playout_buf);
#endif
}
struct pbuf *
pbuf_init(void)
{
struct pbuf *playout_buf = NULL;
struct pbuf *pbuf_init(void)
{
struct pbuf *playout_buf = NULL;
playout_buf = malloc(sizeof(struct pbuf));
if (playout_buf != NULL) {
playout_buf->frst=NULL;
playout_buf->last=NULL;
} else {
debug_msg("Failed to allocate memory for playout buffer\n");
}
return playout_buf;
playout_buf = malloc(sizeof(struct pbuf));
if (playout_buf != NULL) {
playout_buf->frst = NULL;
playout_buf->last = NULL;
} else {
debug_msg("Failed to allocate memory for playout buffer\n");
}
return playout_buf;
}
static void
add_coded_unit(struct pbuf_node *node, rtp_packet *pkt)
static void add_coded_unit(struct pbuf_node *node, rtp_packet * pkt)
{
/* Add "pkt" to the frame represented by "node". The "node" has */
/* previously been created, and has some coded data already... */
/* Add "pkt" to the frame represented by "node". The "node" has */
/* previously been created, and has some coded data already... */
/* New arrivals are added at the head of the list, which is stored */
/* in descending order of packets as they arrive (NOT necessarily */
/* descending sequence number order, as the network might reorder) */
/* New arrivals are added at the head of the list, which is stored */
/* in descending order of packets as they arrive (NOT necessarily */
/* descending sequence number order, as the network might reorder) */
struct coded_data *tmp;
struct coded_data *tmp;
assert(node->rtp_timestamp == pkt->ts);
assert(node->cdata != NULL);
assert(node->rtp_timestamp == pkt->ts);
assert(node->cdata != NULL);
tmp = malloc(sizeof(struct coded_data));
if (tmp != NULL) {
tmp->seqno = pkt->seq;
tmp->data = pkt;
tmp->prv = NULL;
tmp->nxt = node->cdata;
node->cdata->prv = tmp;
node->cdata = tmp;
node->mbit |= pkt->m;
} else {
/* this is bad, out of memory, drop the packet... */
free(pkt);
}
tmp = malloc(sizeof(struct coded_data));
if (tmp != NULL) {
tmp->seqno = pkt->seq;
tmp->data = pkt;
tmp->prv = NULL;
tmp->nxt = node->cdata;
node->cdata->prv = tmp;
node->cdata = tmp;
node->mbit |= pkt->m;
} else {
/* this is bad, out of memory, drop the packet... */
free(pkt);
}
}
static struct pbuf_node *
create_new_pnode(rtp_packet *pkt)
static struct pbuf_node *create_new_pnode(rtp_packet * pkt)
{
struct pbuf_node *tmp;
struct pbuf_node *tmp;
tmp = malloc(sizeof(struct pbuf_node));
if (tmp != NULL) {
tmp->magic = PBUF_MAGIC;
tmp->nxt = NULL;
tmp->prv = NULL;
tmp->decoded = 0;
tmp->rtp_timestamp = pkt->ts;
tmp->mbit = pkt->m;
gettimeofday(&(tmp->arrival_time), NULL);
gettimeofday(&(tmp->playout_time), NULL);
/* Playout delay... should really be adaptive, based on the */
/* jitter, but we use a (conservative) fixed 32ms delay for */
/* now (2 video frames at 60fps). */
tv_add(&(tmp->playout_time), 0.032);
tmp = malloc(sizeof(struct pbuf_node));
if (tmp != NULL) {
tmp->magic = PBUF_MAGIC;
tmp->nxt = NULL;
tmp->prv = NULL;
tmp->decoded = 0;
tmp->rtp_timestamp = pkt->ts;
tmp->mbit = pkt->m;
gettimeofday(&(tmp->arrival_time), NULL);
gettimeofday(&(tmp->playout_time), NULL);
/* Playout delay... should really be adaptive, based on the */
/* jitter, but we use a (conservative) fixed 32ms delay for */
/* now (2 video frames at 60fps). */
tv_add(&(tmp->playout_time), 0.032);
tmp->cdata = malloc(sizeof(struct coded_data));
if (tmp->cdata != NULL) {
tmp->cdata->nxt = NULL;
tmp->cdata->prv = NULL;
tmp->cdata->seqno = pkt->seq;
tmp->cdata->data = pkt;
} else {
free(pkt);
free(tmp);
return NULL;
}
} else {
free(pkt);
}
return tmp;
tmp->cdata = malloc(sizeof(struct coded_data));
if (tmp->cdata != NULL) {
tmp->cdata->nxt = NULL;
tmp->cdata->prv = NULL;
tmp->cdata->seqno = pkt->seq;
tmp->cdata->data = pkt;
} else {
free(pkt);
free(tmp);
return NULL;
}
} else {
free(pkt);
}
return tmp;
}
void
pbuf_insert(struct pbuf *playout_buf, rtp_packet *pkt)
void pbuf_insert(struct pbuf *playout_buf, rtp_packet * pkt)
{
struct pbuf_node *tmp;
struct pbuf_node *tmp;
pbuf_validate(playout_buf);
pbuf_validate(playout_buf);
if (playout_buf->frst==NULL && playout_buf->last==NULL) {
/* playout buffer is empty - add new frame */
playout_buf->frst = create_new_pnode(pkt);
playout_buf->last = playout_buf->frst;
return;
}
if (playout_buf->last->rtp_timestamp == pkt->ts) {
/* Packet belongs to last frame in playout_buf this is the */
/* most likely scenario - although... */
add_coded_unit(playout_buf->last, pkt);
} else {
if (playout_buf->last->rtp_timestamp < pkt->ts) {
/* Packet belongs to a new frame... */
tmp = create_new_pnode (pkt);
playout_buf->last->nxt = tmp;
tmp->prv = playout_buf->last;
playout_buf->last = tmp;
} else {
/* Packet belongs to a previous frame... */
if (playout_buf->frst->rtp_timestamp > pkt->ts) {
debug_msg("A very old packet - discarded\n");
} else {
debug_msg("A packet for a previous frame, but might still be useful\n");
/* Should probably insert this into the playout buffer here... */
}
if (pkt->m) {
debug_msg("Oops... dropped packet with M bit set\n");
}
free(pkt);
}
}
pbuf_validate(playout_buf);
}
static void
free_cdata(struct coded_data *head)
{
struct coded_data *tmp;
while (head != NULL) {
free(head->data);
tmp = head;
head = head->nxt;
free(tmp);
}
}
void
pbuf_remove(struct pbuf *playout_buf, struct timeval curr_time)
{
/* Remove previously decoded frames that have passed their playout */
/* time from the playout buffer. Incomplete frames that have passed */
/* their playout time are also discarded. */
struct pbuf_node *curr, *temp;
pbuf_validate(playout_buf);
curr=playout_buf->frst;
while (curr != NULL) {
temp = curr->nxt;
if (tv_gt(curr_time, curr->playout_time)) {
if (curr == playout_buf->frst) {
playout_buf->frst = curr->nxt;
}
if (curr == playout_buf->last) {
playout_buf->last = curr->prv;
}
if (curr->nxt != NULL) {
curr->nxt->prv = curr->prv;
}
if (curr->prv != NULL) {
curr->prv->nxt = curr->nxt;
}
free_cdata(curr->cdata);
free (curr);
} else {
/* The playout buffer is stored in order, so once */
/* we see one packet that has not yet reached it's */
/* playout time, we can be sure none of the others */
/* will have done so... */
break;
}
curr = temp;
if (playout_buf->frst == NULL && playout_buf->last == NULL) {
/* playout buffer is empty - add new frame */
playout_buf->frst = create_new_pnode(pkt);
playout_buf->last = playout_buf->frst;
return;
}
pbuf_validate(playout_buf);
return;
if (playout_buf->last->rtp_timestamp == pkt->ts) {
/* Packet belongs to last frame in playout_buf this is the */
/* most likely scenario - although... */
add_coded_unit(playout_buf->last, pkt);
} else {
if (playout_buf->last->rtp_timestamp < pkt->ts) {
/* Packet belongs to a new frame... */
tmp = create_new_pnode(pkt);
playout_buf->last->nxt = tmp;
tmp->prv = playout_buf->last;
playout_buf->last = tmp;
} else {
/* Packet belongs to a previous frame... */
if (playout_buf->frst->rtp_timestamp > pkt->ts) {
debug_msg("A very old packet - discarded\n");
} else {
debug_msg
("A packet for a previous frame, but might still be useful\n");
/* Should probably insert this into the playout buffer here... */
}
if (pkt->m) {
debug_msg
("Oops... dropped packet with M bit set\n");
}
free(pkt);
}
}
pbuf_validate(playout_buf);
}
static int
frame_complete(struct pbuf_node *frame)
static void free_cdata(struct coded_data *head)
{
/* Return non-zero if the list of coded_data represents a */
/* complete frame of video. This might have to be passed the */
/* seqnum of the last packet in the previous frame, too? */
/* i dont think that would reflect correctly of weather this */
/* frame is complete or not - however we should check for all*/
/* the packtes of a frame being present - perhaps we should */
/* keep a bit vector in pbuf_node? LG. */
return (frame->mbit==1);
struct coded_data *tmp;
while (head != NULL) {
free(head->data);
tmp = head;
head = head->nxt;
free(tmp);
}
}
int
pbuf_decode(struct pbuf *playout_buf, struct timeval curr_time, struct video_frame *framebuffer, int i)
void pbuf_remove(struct pbuf *playout_buf, struct timeval curr_time)
{
/* Find the first complete frame that has reached it's playout */
/* time, and decode it into the framebuffer. Mark the frame as */
/* decoded, but otherwise leave it in the playout buffer. */
struct pbuf_node *curr;
/* Remove previously decoded frames that have passed their playout */
/* time from the playout buffer. Incomplete frames that have passed */
/* their playout time are also discarded. */
pbuf_validate(playout_buf);
struct pbuf_node *curr, *temp;
pbuf_validate(playout_buf);
curr = playout_buf->frst;
while (curr != NULL) {
if (!curr->decoded && tv_gt(curr_time, curr->playout_time)) {
if (frame_complete(curr)) {
decode_frame(curr->cdata, framebuffer);
curr->decoded = 1;
return 1;
} else {
debug_msg("Unable to decode frame due to missing data (RTP TS=%u)\n", curr->rtp_timestamp);
}
}
temp = curr->nxt;
if (tv_gt(curr_time, curr->playout_time)) {
if (curr == playout_buf->frst) {
playout_buf->frst = curr->nxt;
}
if (curr == playout_buf->last) {
playout_buf->last = curr->prv;
}
if (curr->nxt != NULL) {
curr->nxt->prv = curr->prv;
}
if (curr->prv != NULL) {
curr->prv->nxt = curr->nxt;
}
free_cdata(curr->cdata);
free(curr);
} else {
/* The playout buffer is stored in order, so once */
/* we see one packet that has not yet reached it's */
/* playout time, we can be sure none of the others */
/* will have done so... */
break;
}
curr = temp;
}
pbuf_validate(playout_buf);
return;
}
static int frame_complete(struct pbuf_node *frame)
{
/* Return non-zero if the list of coded_data represents a */
/* complete frame of video. This might have to be passed the */
/* seqnum of the last packet in the previous frame, too? */
/* i dont think that would reflect correctly of weather this */
/* frame is complete or not - however we should check for all */
/* the packtes of a frame being present - perhaps we should */
/* keep a bit vector in pbuf_node? LG. */
return (frame->mbit == 1);
}
int
pbuf_decode(struct pbuf *playout_buf, struct timeval curr_time,
struct video_frame *framebuffer, int i)
{
/* Find the first complete frame that has reached it's playout */
/* time, and decode it into the framebuffer. Mark the frame as */
/* decoded, but otherwise leave it in the playout buffer. */
struct pbuf_node *curr;
pbuf_validate(playout_buf);
curr = playout_buf->frst;
while (curr != NULL) {
if (!curr->decoded && tv_gt(curr_time, curr->playout_time)) {
if (frame_complete(curr)) {
decode_frame(curr->cdata, framebuffer);
curr->decoded = 1;
return 1;
} else {
debug_msg
("Unable to decode frame due to missing data (RTP TS=%u)\n",
curr->rtp_timestamp);
}
}
curr = curr->nxt;
}
return 0;
return 0;
}
#ifdef HAVE_AUDIO
int
audio_pbuf_decode(struct pbuf *playout_buf, struct timeval curr_time, audio_frame *buffer)
audio_pbuf_decode(struct pbuf *playout_buf, struct timeval curr_time,
audio_frame * buffer)
{
struct pbuf_node *curr;
struct pbuf_node *curr;
pbuf_validate(playout_buf); // should be run in debug mode
pbuf_validate(playout_buf); // should be run in debug mode
curr = playout_buf->frst;
while (curr != NULL){
if (!curr->decoded) { // FIXME: in the original function (pbuf_decode) is some time comparison
network_buffer_to_audio_frame(buffer, curr->cdata->data->data);
curr->decoded = 1;
return 1;
}
curr = curr->nxt;
}
return 0;
curr = playout_buf->frst;
while (curr != NULL) {
if (!curr->decoded) { // FIXME: in the original function (pbuf_decode) is some time comparison
network_buffer_to_audio_frame(buffer,
curr->cdata->data->data);
curr->decoded = 1;
return 1;
}
curr = curr->nxt;
}
return 0;
}
#endif /* HAVE_AUDIO */
#endif /* HAVE_AUDIO */

View File

@@ -56,82 +56,77 @@
#include "rtp/ptime.h"
#define SKEW_THRESHOLD 1500
#define W 10 /* Window size for mapping to local timeline. */
#define W 10 /* Window size for mapping to local timeline. */
#ifdef NDEF
/* Colin's book pg. 178 */
static uint32_t
adjustment_due_to_skew(uint32_t ts, uint32_t curr_time){
static uint32_t adjustment_due_to_skew(uint32_t ts, uint32_t curr_time)
{
static int first_time = 1;
static uint32_t delay_estimate;
static uint32_t active_delay;
int adjustment = 0;
uint32_t d_n = ts - curr_time;
static int first_time = 1;
static uint32_t delay_estimate;
static uint32_t active_delay;
int adjustment = 0;
uint32_t d_n = ts - curr_time;
if (first_time){
if (first_time) {
first_time = 0;
delay_estimate = d_n;
active_delay = d_n;
}else{
delay_estimate = (31 * delay_estimate + d_n) / 32.0;
}
first_time = 0;
delay_estimate = d_n;
active_delay = d_n;
} else {
delay_estimate = (31 * delay_estimate + d_n) / 32.0;
}
if (active_delay - delay_estimate > SKEW_THRESHOLD){
adjustment = SKEW_THRESHOLD;
active_delay = delay_estimate;
}
if ((double) active_delay - (double) delay_estimate < -SKEW_THRESHOLD){
adjustment = -SKEW_THRESHOLD;
active_delay = delay_estimate;
}
if (active_delay - delay_estimate > SKEW_THRESHOLD) {
return (uint32_t)((double) active_delay + (double) adjustment);
adjustment = SKEW_THRESHOLD;
active_delay = delay_estimate;
}
if ((double)active_delay - (double)delay_estimate < -SKEW_THRESHOLD) {
adjustment = -SKEW_THRESHOLD;
active_delay = delay_estimate;
}
return (uint32_t) ((double)active_delay + (double)adjustment);
}
#endif
#ifdef NDEF
static uint32_t
map_local_timeline(uint32_t ts, uint32_t curr_time)
{
static uint32_t d[W];
static int w = 0;
static int FULL = 0;
uint32_t min;
uint32_t new_difference = ts - curr_time;
int i;
d[w++] = new_difference;
/* Do we have enough records? If so, begin to rewrite oldest first. */
if (w >= W - 1){
FULL = 1;
w = 0;
}
min = d[0];
if (!FULL){
for (i = 1 ; i<w ; i++)
if (d[i] < min)
//if (((d[i] - min) & (1<<15)) != 0)
min = d[i];
}
else
for (i = 1 ; i<W ; i++)
if (d[i] < min)
//if (((d[i] - min) & (1<<15)) != 0)
min = d[i];
return(min);
static uint32_t map_local_timeline(uint32_t ts, uint32_t curr_time)
{
static uint32_t d[W];
static int w = 0;
static int FULL = 0;
uint32_t min;
uint32_t new_difference = ts - curr_time;
int i;
d[w++] = new_difference;
/* Do we have enough records? If so, begin to rewrite oldest first. */
if (w >= W - 1) {
FULL = 1;
w = 0;
}
min = d[0];
if (!FULL) {
for (i = 1; i < w; i++)
if (d[i] < min)
//if (((d[i] - min) & (1<<15)) != 0)
min = d[i];
} else
for (i = 1; i < W; i++)
if (d[i] < min)
//if (((d[i] - min) & (1<<15)) != 0)
min = d[i];
return (min);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -68,169 +68,180 @@
#include "rtp/rtp_callback.h"
#include "tfrc.h"
extern int should_exit;
extern char *frame;
extern int should_exit;
extern char *frame;
char hdr_buf[100];
struct msghdr msg;
struct iovec iov[10];
char hdr_buf[100];
struct msghdr msg;
struct iovec iov[10];
extern uint32_t RTT;
extern uint32_t RTT;
static void
process_rr(struct rtp *session, rtp_event *e)
static void process_rr(struct rtp *session, rtp_event * e)
{
float fract_lost, tmp;
uint32_t ntp_sec, ntp_frac, now;
rtcp_rr *r = (rtcp_rr *) e->data;
float fract_lost, tmp;
uint32_t ntp_sec, ntp_frac, now;
rtcp_rr *r = (rtcp_rr *) e->data;
if (e->ssrc == rtp_my_ssrc(session)) {
/* Filter out loopback reports */
return;
}
if (e->ssrc == rtp_my_ssrc(session)) {
/* Filter out loopback reports */
return;
}
if (r->ssrc == rtp_my_ssrc(session)) {
/* Received a reception quality report for data we are sending. */
/* */
/* Check for excessive congestion: exit if it occurs, to protect */
/* other users of the network. */
fract_lost = (r->fract_lost * 100.0) / 256.0; /* percentage lost packets */
if (fract_lost > 20) {
printf("Receiver 0x%08x reports excessive congestion\n", e->ssrc);
}
if (r->ssrc == rtp_my_ssrc(session)) {
/* Received a reception quality report for data we are sending. */
/* */
/* Check for excessive congestion: exit if it occurs, to protect */
/* other users of the network. */
fract_lost = (r->fract_lost * 100.0) / 256.0; /* percentage lost packets */
if (fract_lost > 20) {
printf("Receiver 0x%08x reports excessive congestion\n",
e->ssrc);
}
/* Compute network round-trip time: */
if (r->lsr != 0) {
ntp64_time(&ntp_sec, &ntp_frac);
now = ntp64_to_ntp32(ntp_sec, ntp_frac);
/* Compute network round-trip time: */
if (r->lsr != 0) {
ntp64_time(&ntp_sec, &ntp_frac);
now = ntp64_to_ntp32(ntp_sec, ntp_frac);
if ((now < r->lsr) || (now - r->lsr < r->dlsr)) {
/* Packet arrived before it was sent, ignore. This represents */
/* a bug in the remote: either our timestamp was incorrectly */
/* echoed back to us, or the remote miscalculated in time for */
/* which it held the packet. */
debug_msg("Bogus RTT from 0x%08x ignored\n", e->ssrc);
} else {
tmp = ((float) (now-r->lsr-r->dlsr))/65536.0; /* RTT in seconds */
RTT = tmp * 1000000; /* RTT in usec */
}
debug_msg(" RTT=%d usec\n", RTT);
}
}
if ((now < r->lsr) || (now - r->lsr < r->dlsr)) {
/* Packet arrived before it was sent, ignore. This represents */
/* a bug in the remote: either our timestamp was incorrectly */
/* echoed back to us, or the remote miscalculated in time for */
/* which it held the packet. */
debug_msg("Bogus RTT from 0x%08x ignored\n",
e->ssrc);
} else {
tmp = ((float)(now - r->lsr - r->dlsr)) / 65536.0; /* RTT in seconds */
RTT = tmp * 1000000; /* RTT in usec */
}
debug_msg(" RTT=%d usec\n", RTT);
}
}
}
static void
process_sdes(struct pdb *participants, uint32_t ssrc, rtcp_sdes_item *d)
process_sdes(struct pdb *participants, uint32_t ssrc, rtcp_sdes_item * d)
{
struct pdb_e *e;
char *sdes_item;
struct pdb_e *e;
char *sdes_item;
e = pdb_get(participants, ssrc);
if (e == NULL) {
/* We got an SDES packet for a participant we haven't previously seen. */
/* This can happen, for example, in a partitioned multicast group. Log */
/* the event, and add the new participant to the database. */
debug_msg("Added previously unseen participant 0x%08x due to receipt of SDES\n", ssrc);
pdb_add(participants, ssrc);
e = pdb_get(participants, ssrc);
}
e = pdb_get(participants, ssrc);
if (e == NULL) {
/* We got an SDES packet for a participant we haven't previously seen. */
/* This can happen, for example, in a partitioned multicast group. Log */
/* the event, and add the new participant to the database. */
debug_msg
("Added previously unseen participant 0x%08x due to receipt of SDES\n",
ssrc);
pdb_add(participants, ssrc);
e = pdb_get(participants, ssrc);
}
sdes_item = calloc(d->length+1, 1);
strncpy(sdes_item, d->data, d->length);
sdes_item = calloc(d->length + 1, 1);
strncpy(sdes_item, d->data, d->length);
switch (d->type) {
case RTCP_SDES_END:
/* This is the end of the SDES list of a packet. */
/* Nothing for us to deal with. */
break;
case RTCP_SDES_CNAME:
if (e->sdes_cname != NULL) free(e->sdes_cname);
e->sdes_cname = sdes_item;
break;
case RTCP_SDES_NAME:
if (e->sdes_name != NULL) free(e->sdes_name);
e->sdes_name = sdes_item;
break;
case RTCP_SDES_EMAIL:
if (e->sdes_email != NULL) free(e->sdes_email);
e->sdes_email = sdes_item;
break;
case RTCP_SDES_PHONE:
if (e->sdes_phone != NULL) free(e->sdes_phone);
e->sdes_phone = sdes_item;
break;
case RTCP_SDES_LOC:
if (e->sdes_loc != NULL) free(e->sdes_loc);
e->sdes_loc = sdes_item;
break;
case RTCP_SDES_TOOL:
if (e->sdes_tool != NULL) free(e->sdes_tool);
e->sdes_tool = sdes_item;
break;
case RTCP_SDES_NOTE:
if (e->sdes_note != NULL) free(e->sdes_note);
e->sdes_note = sdes_item;
break;
case RTCP_SDES_PRIV:
break; /* Ignore private extensions */
default:
debug_msg("Ignored unknown SDES item (type=0x%02x) from 0x%08x\n", ssrc);
}
switch (d->type) {
case RTCP_SDES_END:
/* This is the end of the SDES list of a packet. */
/* Nothing for us to deal with. */
break;
case RTCP_SDES_CNAME:
if (e->sdes_cname != NULL)
free(e->sdes_cname);
e->sdes_cname = sdes_item;
break;
case RTCP_SDES_NAME:
if (e->sdes_name != NULL)
free(e->sdes_name);
e->sdes_name = sdes_item;
break;
case RTCP_SDES_EMAIL:
if (e->sdes_email != NULL)
free(e->sdes_email);
e->sdes_email = sdes_item;
break;
case RTCP_SDES_PHONE:
if (e->sdes_phone != NULL)
free(e->sdes_phone);
e->sdes_phone = sdes_item;
break;
case RTCP_SDES_LOC:
if (e->sdes_loc != NULL)
free(e->sdes_loc);
e->sdes_loc = sdes_item;
break;
case RTCP_SDES_TOOL:
if (e->sdes_tool != NULL)
free(e->sdes_tool);
e->sdes_tool = sdes_item;
break;
case RTCP_SDES_NOTE:
if (e->sdes_note != NULL)
free(e->sdes_note);
e->sdes_note = sdes_item;
break;
case RTCP_SDES_PRIV:
break; /* Ignore private extensions */
default:
debug_msg
("Ignored unknown SDES item (type=0x%02x) from 0x%08x\n",
ssrc);
}
}
void
rtp_recv_callback(struct rtp *session, rtp_event *e)
void rtp_recv_callback(struct rtp *session, rtp_event * e)
{
rtcp_app *pckt_app = (rtcp_app *) e->data;
rtp_packet *pckt_rtp = (rtp_packet *) e->data;
struct pdb *participants = (struct pdb *) rtp_get_userdata(session);
struct pdb_e *state = pdb_get(participants, e->ssrc);
struct timeval curr_time;
rtcp_app *pckt_app = (rtcp_app *) e->data;
rtp_packet *pckt_rtp = (rtp_packet *) e->data;
struct pdb *participants = (struct pdb *)rtp_get_userdata(session);
struct pdb_e *state = pdb_get(participants, e->ssrc);
struct timeval curr_time;
switch (e->type) {
case RX_RTP:
if (pckt_rtp->data_len > 0) { /* Only process packets that contain data... */
pbuf_insert(state->playout_buffer, pckt_rtp);
}
tfrc_recv_data(state->tfrc_state, curr_time, pckt_rtp->seq, pckt_rtp->data_len+40);
break;
case RX_TFRC_RX:
/* compute TCP friendly data rate */
break;
case RX_RTCP_START:
break;
case RX_RTCP_FINISH:
break;
case RX_SR:
break;
case RX_RR:
process_rr(session, e);
break;
case RX_RR_EMPTY:
break;
case RX_SDES:
process_sdes(participants, e->ssrc, (rtcp_sdes_item *) e->data);
break;
case RX_APP:
pckt_app = (rtcp_app *) e->data;
if (strncmp(pckt_app->name, "RTT_", 4) == 0) {
assert(pckt_app->length = 3);
assert(pckt_app->subtype = 0);
gettimeofday(&curr_time, NULL);
// tfrc_recv_rtt(state->tfrc_state, curr_time, ntohl(*((int *) pckt_app->data)));
}
break;
case RX_BYE:
break;
case SOURCE_DELETED:
break;
case SOURCE_CREATED:
pdb_add(participants, e->ssrc);
break;
case RR_TIMEOUT:
break;
default:
debug_msg("Unknown RTP event (type=%d)\n", e->type);
}
switch (e->type) {
case RX_RTP:
if (pckt_rtp->data_len > 0) { /* Only process packets that contain data... */
pbuf_insert(state->playout_buffer, pckt_rtp);
}
tfrc_recv_data(state->tfrc_state, curr_time, pckt_rtp->seq,
pckt_rtp->data_len + 40);
break;
case RX_TFRC_RX:
/* compute TCP friendly data rate */
break;
case RX_RTCP_START:
break;
case RX_RTCP_FINISH:
break;
case RX_SR:
break;
case RX_RR:
process_rr(session, e);
break;
case RX_RR_EMPTY:
break;
case RX_SDES:
process_sdes(participants, e->ssrc, (rtcp_sdes_item *) e->data);
break;
case RX_APP:
pckt_app = (rtcp_app *) e->data;
if (strncmp(pckt_app->name, "RTT_", 4) == 0) {
assert(pckt_app->length = 3);
assert(pckt_app->subtype = 0);
gettimeofday(&curr_time, NULL);
// tfrc_recv_rtt(state->tfrc_state, curr_time, ntohl(*((int *) pckt_app->data)));
}
break;
case RX_BYE:
break;
case SOURCE_DELETED:
break;
case SOURCE_CREATED:
pdb_add(participants, e->ssrc);
break;
case RR_TIMEOUT:
break;
default:
debug_msg("Unknown RTP event (type=%d)\n", e->type);
}
}

View File

@@ -52,10 +52,10 @@
#include "tv.h"
#include "tfrc.h"
#define TFRC_MAGIC 0xbaef03b7 /* For debugging */
#define TFRC_MAGIC 0xbaef03b7 /* For debugging */
#define MAX_HISTORY 1000
#define N 8 /* number of intervals */
#define N 8 /* number of intervals */
#define MAX_DROPOUT 100
#define RTP_SEQ_MOD 0x10000
#define MAX_MISORDER 100
@@ -67,300 +67,294 @@
*
*/
struct tfrc {
int total_pckts;
int ooo;
int cycles; /* number of times seq number cycles 65535 */
uint32_t RTT; /* received from sender in app packet */
struct timeval feedback_timer; /* indicates points in time when p should be computed */
double p, p_prev;
int s;
struct timeval start_time;
int loss_count;
int interval_count;
int gap[20];
int jj; /* index for arrival -1<=i<=MAX_HISTORY */
int ii; /* index for loss -1<=ii<=10 */
double W_tot;
double weight[N+5]; /* Weights for loss event calculation. In the RFC, the numbering is the other way around */
uint32_t magic; /* For debugging */
int total_pckts;
int ooo;
int cycles; /* number of times seq number cycles 65535 */
uint32_t RTT; /* received from sender in app packet */
struct timeval feedback_timer; /* indicates points in time when p should be computed */
double p, p_prev;
int s;
struct timeval start_time;
int loss_count;
int interval_count;
int gap[20];
int jj; /* index for arrival -1<=i<=MAX_HISTORY */
int ii; /* index for loss -1<=ii<=10 */
double W_tot;
double weight[N + 5]; /* Weights for loss event calculation. In the RFC, the numbering is the other way around */
uint32_t magic; /* For debugging */
};
static void
validate_tfrc_state(struct tfrc *state)
static void validate_tfrc_state(struct tfrc *state)
{
/* Debugging routine. Called each time we enter TFRC code, */
/* to ensure that the state information we've been given */
/* is valid. */
assert(state->magic == TFRC_MAGIC);
/* Debugging routine. Called each time we enter TFRC code, */
/* to ensure that the state information we've been given */
/* is valid. */
assert(state->magic == TFRC_MAGIC);
#ifdef DEBUG
/* ...do some fancy debugging... */
/* ...do some fancy debugging... */
#endif
}
static struct {
uint32_t seq;
uint32_t ts;
uint32_t seq;
uint32_t ts;
} arrival[MAX_HISTORY];
static struct {
uint32_t seq;
uint32_t ts;
uint32_t seq;
uint32_t ts;
} loss[MAX_HISTORY];
#ifdef NDEF
static double
transfer_rate(double p)
static double transfer_rate(double p)
{
double t, t1, t2, t3, t4, rtt, tRTO;
if (p == 0) {
return 0;
}
double t, t1, t2, t3, t4, rtt, tRTO;
if (p == 0) {
return 0;
}
/* convert RTT from usec to sec */
rtt = ((double) RTT) / 1000000.0;
tRTO = 4 * rtt;
/* convert RTT from usec to sec */
rtt = ((double)RTT) / 1000000.0;
tRTO = 4 * rtt;
t1 = rtt * sqrt(2 * p / 3);
t2 = (1 + 32 * p * p);
t3 = 3 * sqrt(3 * p / 8);
t4 = t1 + tRTO * t3 * p * t2;
t = ((double) s) / t4;
t1 = rtt * sqrt(2 * p / 3);
t2 = (1 + 32 * p * p);
t3 = 3 * sqrt(3 * p / 8);
t4 = t1 + tRTO * t3 * p * t2;
t = ((double)s) / t4;
return (t);
return (t);
}
static void
compute_transfer_rate(void)
static void compute_transfer_rate(void)
{
double t1;
struct timeval now;
double t1;
struct timeval now;
t1 = transfer_rate(p);
gettimeofday(&now, NULL);
t1 = transfer_rate(p);
gettimeofday(&now, NULL);
}
#endif
static int
set_zero(int first, int last, uint16_t u)
static int set_zero(int first, int last, uint16_t u)
{
int i, count = 0;;
int i, count = 0;;
assert((first >= 0) && (first < MAX_HISTORY));
assert((last >= 0) && (last < MAX_HISTORY));
assert((first >= 0) && (first < MAX_HISTORY));
assert((last >= 0) && (last < MAX_HISTORY));
if (first == last)
return (0);
if ((first + 1) % MAX_HISTORY == last)
return (1);
if (first == last)
return (0);
if ((first + 1) % MAX_HISTORY == last)
return (1);
if (first < last) {
for (i = first + 1; i < last; i++) {
arrival[i].seq = 0;
arrival[i].ts = 0;
count++;
}
} else {
for (i = first + 1; i < MAX_HISTORY; i++) {
arrival[i].seq = 0;
arrival[i].ts = 0;
count++;
}
for (i = 0; i < last; i++) {
arrival[i].seq = 0;
arrival[i].ts = 0;
count++;
}
}
assert(count == (u - 1));
return (count);
if (first < last) {
for (i = first + 1; i < last; i++) {
arrival[i].seq = 0;
arrival[i].ts = 0;
count++;
}
} else {
for (i = first + 1; i < MAX_HISTORY; i++) {
arrival[i].seq = 0;
arrival[i].ts = 0;
count++;
}
for (i = 0; i < last; i++) {
arrival[i].seq = 0;
arrival[i].ts = 0;
count++;
}
}
assert(count == (u - 1));
return (count);
}
static int
arrived(int first, int last)
static int arrived(int first, int last)
{
int i, count = 0;
int i, count = 0;
assert((first >= 0) && (first < MAX_HISTORY));
assert((last >= 0) && (last < MAX_HISTORY));
assert((first >= 0) && (first < MAX_HISTORY));
assert((last >= 0) && (last < MAX_HISTORY));
if (first == last)
return (0);
if ((first + 1) % MAX_HISTORY == last)
return (0);
if (first == last)
return (0);
if ((first + 1) % MAX_HISTORY == last)
return (0);
if (first < last) {
for (i = first; i <= last; i++) {
if (arrival[i].seq != 0)
count++;
}
} else {
for (i = first; i < MAX_HISTORY; i++) {
if (arrival[i].seq != 0)
count++;
}
for (i = 0; i <= last; i++) {
if (arrival[i].seq != 0)
count++;
}
}
return (count);
if (first < last) {
for (i = first; i <= last; i++) {
if (arrival[i].seq != 0)
count++;
}
} else {
for (i = first; i < MAX_HISTORY; i++) {
if (arrival[i].seq != 0)
count++;
}
for (i = 0; i <= last; i++) {
if (arrival[i].seq != 0)
count++;
}
}
return (count);
}
static void
record_loss(struct tfrc *state, uint32_t s1, uint32_t s2, uint32_t ts1, uint32_t ts2)
record_loss(struct tfrc *state, uint32_t s1, uint32_t s2, uint32_t ts1,
uint32_t ts2)
{
/* Mark all packets between s1 (which arrived at time ts1) and */
/* s2 (which arrived at time ts2) as lost. */
int i;
uint32_t est;
uint32_t seq = s1 + 1;
/* Mark all packets between s1 (which arrived at time ts1) and */
/* s2 (which arrived at time ts2) as lost. */
int i;
uint32_t est;
uint32_t seq = s1 + 1;
est = ts1 + (ts2 - ts1) * ((seq - s1) / (s2 - seq));
est = ts1 + (ts2 - ts1) * ((seq - s1) / (s2 - seq));
state->loss_count++;
if (state->ii <= -1) {
/* first loss! */
state->ii++;
loss[state->ii].seq = seq;
loss[state->ii].ts = est;
return;
}
state->loss_count++;
if (state->ii <= -1) {
/* first loss! */
state->ii++;
loss[state->ii].seq = seq;
loss[state->ii].ts = est;
return;
}
if (est - loss[state->ii].ts <= state->RTT) { /* not a new event */
return;
}
if (est - loss[state->ii].ts <= state->RTT) { /* not a new event */
return;
}
state->interval_count++;
if (state->ii > (N + 1)) {
printf("how did this happen?\n");
}
state->interval_count++;
if (state->ii > (N + 1)) {
printf("how did this happen?\n");
}
if (state->ii >= (N + 1)) { /* shift */
for (i = 0; i < (N + 1); i++) {
loss[i].seq = loss[i + 1].seq;
loss[i].ts = loss[i + 1].ts;
}
state->ii = N;
}
if (state->ii >= (N + 1)) { /* shift */
for (i = 0; i < (N + 1); i++) {
loss[i].seq = loss[i + 1].seq;
loss[i].ts = loss[i + 1].ts;
}
state->ii = N;
}
state->ii++;
loss[state->ii].seq = seq;
loss[state->ii].ts = est;
state->ii++;
loss[state->ii].seq = seq;
loss[state->ii].ts = est;
}
static void
save_arrival(struct tfrc *state, struct timeval curr_time, uint16_t seq)
{
int kk, inc, last_jj;
uint16_t udelta;
uint32_t now;
uint32_t ext_seq;
static uint16_t last_seq;
static uint32_t ext_last_ack;
static int last_ack_jj = 0;
int kk, inc, last_jj;
uint16_t udelta;
uint32_t now;
uint32_t ext_seq;
static uint16_t last_seq;
static uint32_t ext_last_ack;
static int last_ack_jj = 0;
gettimeofday(&curr_time, NULL);
now = tv_diff_usec(curr_time, state->start_time);
gettimeofday(&curr_time, NULL);
now = tv_diff_usec(curr_time, state->start_time);
if (state->jj == -1) {
/* first packet arrival */
state->jj = 0;
last_seq = seq;
ext_last_ack = seq;
last_ack_jj = 0;
arrival[state->jj].seq = seq;
arrival[state->jj].ts = now;
return;
}
if (state->jj == -1) {
/* first packet arrival */
state->jj = 0;
last_seq = seq;
ext_last_ack = seq;
last_ack_jj = 0;
arrival[state->jj].seq = seq;
arrival[state->jj].ts = now;
return;
}
udelta = seq - last_seq;
udelta = seq - last_seq;
state->total_pckts++;
if (udelta < MAX_DROPOUT) {
/* in order, with permissible gap */
if (seq < last_seq) {
state->cycles++;
}
/* record arrival */
last_jj = state->jj;
state->jj = (state->jj + udelta) % MAX_HISTORY;
set_zero(last_jj, state->jj, udelta);
ext_seq = seq + state->cycles * RTP_SEQ_MOD;
last_seq = seq;
arrival[state->jj].seq = ext_seq;
arrival[state->jj].ts = now;
if (udelta < 10)
state->gap[udelta - 1]++;
state->total_pckts++;
if (udelta < MAX_DROPOUT) {
/* in order, with permissible gap */
if (seq < last_seq) {
state->cycles++;
}
/* record arrival */
last_jj = state->jj;
state->jj = (state->jj + udelta) % MAX_HISTORY;
set_zero(last_jj, state->jj, udelta);
ext_seq = seq + state->cycles * RTP_SEQ_MOD;
last_seq = seq;
arrival[state->jj].seq = ext_seq;
arrival[state->jj].ts = now;
if (udelta < 10)
state->gap[udelta - 1]++;
if ((ext_seq - ext_last_ack) == 1) {
/* We got two consecutive packets, no loss */
ext_last_ack = ext_seq;
last_ack_jj = state->jj;
} else {
/* Sequence number jumped, we've missed a packet for some reason */
if (arrived(last_ack_jj, state->jj) >= 4) {
record_loss(state, ext_last_ack, ext_seq,
arrival[last_ack_jj].ts, now);
ext_last_ack = ext_seq;
last_ack_jj = state->jj;
}
}
} else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) {
printf(" -- seq:%u last seq:%u ", seq, arrival[state->jj].seq);
abort(); /* FIXME */
} else {
/* duplicate or reordered packet */
ext_seq = seq + state->cycles * RTP_SEQ_MOD;
state->ooo++;
if (ext_seq > ext_last_ack) {
inc = ext_seq - arrival[state->jj].seq;
if ((ext_seq - ext_last_ack) == 1) {
/* We got two consecutive packets, no loss */
ext_last_ack = ext_seq;
last_ack_jj = state->jj;
} else {
/* Sequence number jumped, we've missed a packet for some reason */
if (arrived(last_ack_jj, state->jj) >= 4) {
record_loss(state, ext_last_ack, ext_seq,
arrival[last_ack_jj].ts, now);
ext_last_ack = ext_seq;
last_ack_jj = state->jj;
}
}
} else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) {
printf(" -- seq:%u last seq:%u ", seq, arrival[state->jj].seq);
abort(); /* FIXME */
} else {
/* duplicate or reordered packet */
ext_seq = seq + state->cycles * RTP_SEQ_MOD;
state->ooo++;
if (ext_seq > ext_last_ack) {
inc = ext_seq - arrival[state->jj].seq;
kk = (state->jj + inc) % MAX_HISTORY;
if (arrival[kk].seq == 0) {
arrival[kk].seq = ext_seq;
arrival[kk].ts = (arrival[last_ack_jj].ts + now) / 2; /* NOT the best interpolation */
}
while (arrival[last_ack_jj + 1].seq != 0
&& last_ack_jj < state->jj) {
last_ack_jj = (last_ack_jj + 1) % MAX_HISTORY;
}
ext_last_ack = arrival[last_ack_jj].seq;
}
}
kk = (state->jj + inc) % MAX_HISTORY;
if (arrival[kk].seq == 0) {
arrival[kk].seq = ext_seq;
arrival[kk].ts = (arrival[last_ack_jj].ts + now) / 2; /* NOT the best interpolation */
}
while (arrival[last_ack_jj + 1].seq != 0
&& last_ack_jj < state->jj) {
last_ack_jj = (last_ack_jj + 1) % MAX_HISTORY;
}
ext_last_ack = arrival[last_ack_jj].seq;
}
}
}
static double
compute_loss_event(struct tfrc *state)
static double compute_loss_event(struct tfrc *state)
{
int i;
uint32_t t, temp, I_tot0 = 0, I_tot1 = 0, I_tot = 0;
struct timeval now;
double I_mean, p;
int i;
uint32_t t, temp, I_tot0 = 0, I_tot1 = 0, I_tot = 0;
struct timeval now;
double I_mean, p;
if (state->ii < N) {
return 0;
}
if (state->ii < N) {
return 0;
}
for (i = state->ii - N; i < state->ii; i++) {
temp = loss[i + 1].seq - loss[i].seq;
I_tot0 = I_tot0 + temp * state->weight[i];
if (i >= (state->ii - N + 1)) {
I_tot1 = I_tot1 + temp * state->weight[i - 1];
}
}
I_tot1 = I_tot1 + (arrival[state->jj].seq - loss[state->ii].seq) * state->weight[N - 1];
for (i = state->ii - N; i < state->ii; i++) {
temp = loss[i + 1].seq - loss[i].seq;
I_tot0 = I_tot0 + temp * state->weight[i];
if (i >= (state->ii - N + 1)) {
I_tot1 = I_tot1 + temp * state->weight[i - 1];
}
}
I_tot1 =
I_tot1 + (arrival[state->jj].seq -
loss[state->ii].seq) * state->weight[N - 1];
I_tot = (I_tot1 > I_tot0) ? I_tot1 : I_tot0;
I_mean = I_tot / state->W_tot;
p = 1 / I_mean;
I_tot = (I_tot1 > I_tot0) ? I_tot1 : I_tot0;
I_mean = I_tot / state->W_tot;
p = 1 / I_mean;
gettimeofday(&now, NULL);
t = tv_diff_usec(now, state->start_time);
gettimeofday(&now, NULL);
t = tv_diff_usec(now, state->start_time);
return p;
return p;
}
@@ -369,144 +363,141 @@ compute_loss_event(struct tfrc *state)
*
*/
struct tfrc *
tfrc_init(struct timeval curr_time)
struct tfrc *tfrc_init(struct timeval curr_time)
{
struct tfrc *state;
int i;
struct tfrc *state;
int i;
state = (struct tfrc *) malloc(sizeof(struct tfrc));
if (state != NULL) {
state->magic = TFRC_MAGIC;
state->total_pckts = 0;
state->ooo = 0;
state->cycles = 0;
state->RTT = 0;
state->feedback_timer = curr_time;
state->p = 0.0;
state->p_prev = 0.0;
state->s = 0;
state->start_time = curr_time;
state->loss_count = 0;
state->interval_count = 0;
state->jj = -1;
state->ii = -1;
state->W_tot = 0;
state->weight[0] = 0.2;
state->weight[1] = 0.4;
state->weight[2] = 0.6;
state->weight[3] = 0.8;
state->weight[4] = 1.0;
state->weight[5] = 1.0;
state->weight[6] = 1.0;
state->weight[7] = 1.0;
state->weight[8] = 1.0;
state = (struct tfrc *)malloc(sizeof(struct tfrc));
if (state != NULL) {
state->magic = TFRC_MAGIC;
state->total_pckts = 0;
state->ooo = 0;
state->cycles = 0;
state->RTT = 0;
state->feedback_timer = curr_time;
state->p = 0.0;
state->p_prev = 0.0;
state->s = 0;
state->start_time = curr_time;
state->loss_count = 0;
state->interval_count = 0;
state->jj = -1;
state->ii = -1;
state->W_tot = 0;
state->weight[0] = 0.2;
state->weight[1] = 0.4;
state->weight[2] = 0.6;
state->weight[3] = 0.8;
state->weight[4] = 1.0;
state->weight[5] = 1.0;
state->weight[6] = 1.0;
state->weight[7] = 1.0;
state->weight[8] = 1.0;
for (i = 0; i < 20; i++) {
state->gap[i] = 0;
}
for (i = 0; i < 20; i++) {
state->gap[i] = 0;
}
for (i = 0; i < N; i++) {
state->W_tot = state->W_tot + state->weight[i];
}
}
for (i = 0; i < N; i++) {
state->W_tot = state->W_tot + state->weight[i];
}
}
for (i = 0; i < MAX_HISTORY; i++) {
arrival[i].seq = 0;
arrival[i].ts = 0;
loss[i].seq = 0;
loss[i].ts = 0;
}
return state;
for (i = 0; i < MAX_HISTORY; i++) {
arrival[i].seq = 0;
arrival[i].ts = 0;
loss[i].seq = 0;
loss[i].ts = 0;
}
return state;
}
void
tfrc_done(struct tfrc *state)
void tfrc_done(struct tfrc *state)
{
int i;
int i;
validate_tfrc_state(state);
validate_tfrc_state(state);
for (i = 0; i < 10; i++) {
printf("\n%2d %8d", i, state->gap[i]);
}
printf("\n");
printf("\nLost: %8d", state->loss_count);
printf("\nIntervals: %8d", state->interval_count);
printf("\nTotal: %8d", state->total_pckts);
printf("\nooo: %8d -- %7.5f\n\n", state->ooo, (state->ooo * 100) / (double) state->total_pckts);
for (i = 0; i < 10; i++) {
printf("\n%2d %8d", i, state->gap[i]);
}
printf("\n");
printf("\nLost: %8d", state->loss_count);
printf("\nIntervals: %8d", state->interval_count);
printf("\nTotal: %8d", state->total_pckts);
printf("\nooo: %8d -- %7.5f\n\n", state->ooo,
(state->ooo * 100) / (double)state->total_pckts);
}
void
tfrc_recv_data(struct tfrc *state, struct timeval curr_time, uint16_t seqnum, unsigned length)
tfrc_recv_data(struct tfrc *state, struct timeval curr_time, uint16_t seqnum,
unsigned length)
{
/* This is called each time an RTP packet is received. Accordingly, */
/* it needs to be _very_ fast, otherwise we'll drop packets. */
/* This is called each time an RTP packet is received. Accordingly, */
/* it needs to be _very_ fast, otherwise we'll drop packets. */
validate_tfrc_state(state);
validate_tfrc_state(state);
if (state->RTT > 0) {
save_arrival(state, curr_time, seqnum);
state->p_prev = state->p;
if (state->RTT > 0) {
save_arrival(state, curr_time, seqnum);
state->p_prev = state->p;
#ifdef NDEF
state->p = compute_loss_event(state);
if (state->p - state->p_prev > 0.00000000001) {
gettimeofday(&(state->feedback_timer), NULL);
tv_add(&(state->feedback_timer), (unsigned int) state->RTT);
compute_transfer_rate();
}
state->p = compute_loss_event(state);
if (state->p - state->p_prev > 0.00000000001) {
gettimeofday(&(state->feedback_timer), NULL);
tv_add(&(state->feedback_timer),
(unsigned int)state->RTT);
compute_transfer_rate();
}
#endif
}
state->s = length; /* packet size is needed transfer_rate */
}
state->s = length; /* packet size is needed transfer_rate */
}
void
tfrc_recv_rtt(struct tfrc *state, struct timeval curr_time, uint32_t rtt)
void tfrc_recv_rtt(struct tfrc *state, struct timeval curr_time, uint32_t rtt)
{
/* Called whenever the receiver gets an RTCP APP packet telling */
/* it the RTT to the sender. Not performance critical. */
/* Note: RTT is in microseconds. */
/* Called whenever the receiver gets an RTCP APP packet telling */
/* it the RTT to the sender. Not performance critical. */
/* Note: RTT is in microseconds. */
validate_tfrc_state(state);
validate_tfrc_state(state);
if (state->RTT == 0) {
state->feedback_timer = curr_time;
tv_add(&(state->feedback_timer), rtt);
}
state->RTT = rtt;
if (state->RTT == 0) {
state->feedback_timer = curr_time;
tv_add(&(state->feedback_timer), rtt);
}
state->RTT = rtt;
}
int
tfrc_feedback_is_due(struct tfrc *state, struct timeval curr_time)
int tfrc_feedback_is_due(struct tfrc *state, struct timeval curr_time)
{
/* Determine if it is time to send feedback to the sender */
validate_tfrc_state(state);
/* Determine if it is time to send feedback to the sender */
validate_tfrc_state(state);
if ((state->RTT == 0) || tv_gt(state->feedback_timer, curr_time)){
/* Not yet time to send feedback to the sender... */
return FALSE;
}
return TRUE;
if ((state->RTT == 0) || tv_gt(state->feedback_timer, curr_time)) {
/* Not yet time to send feedback to the sender... */
return FALSE;
}
return TRUE;
}
double
tfrc_feedback_txrate(struct tfrc *state, struct timeval curr_time)
double tfrc_feedback_txrate(struct tfrc *state, struct timeval curr_time)
{
/* Calculate the appropriate transmission rate, to be included */
/* in a feedback message to the sender. */
/* Calculate the appropriate transmission rate, to be included */
/* in a feedback message to the sender. */
validate_tfrc_state(state);
validate_tfrc_state(state);
assert(tfrc_feedback_is_due(state, curr_time));
assert(tfrc_feedback_is_due(state, curr_time));
state->feedback_timer.tv_sec = curr_time.tv_sec;
state->feedback_timer.tv_usec = curr_time.tv_usec;
tv_add(&(state->feedback_timer), state->RTT);
state->p = compute_loss_event(state);
//compute_transfer_rate ();
if (state->ii >= N) {
abort(); /* FIXME */
}
return 0.0; /* FIXME */
state->feedback_timer.tv_sec = curr_time.tv_sec;
state->feedback_timer.tv_usec = curr_time.tv_usec;
tv_add(&(state->feedback_timer), state->RTT);
state->p = compute_loss_event(state);
//compute_transfer_rate ();
if (state->ii >= N) {
abort(); /* FIXME */
}
return 0.0; /* FIXME */
}

View File

@@ -73,103 +73,101 @@ extern long packet_rate;
#define GET_STARTTIME gettimeofday(&start, NULL)
#define GET_STOPTIME gettimeofday(&stop, NULL)
#define GET_DELTA delta = (stop.tv_usec - start.tv_usec) * 1000L
#else /* HAVE_MACOSX */
#else /* HAVE_MACOSX */
#define GET_STARTTIME clock_gettime(CLOCK_REALTIME, &start)
#define GET_STOPTIME clock_gettime(CLOCK_REALTIME, &stop)
#define GET_DELTA delta = stop.tv_nsec - start.tv_nsec
#endif /* HAVE_MACOSX */
#endif /* HAVE_MACOSX */
struct video_tx {
uint32_t magic;
unsigned mtu;
uint32_t magic;
unsigned mtu;
};
struct video_tx *
tx_init(unsigned mtu)
struct video_tx *tx_init(unsigned mtu)
{
struct video_tx *tx;
struct video_tx *tx;
tx = (struct video_tx *) malloc(sizeof(struct video_tx));
if (tx != NULL) {
tx->magic = TRANSMIT_MAGIC;
tx->mtu = mtu;
}
return tx;
tx = (struct video_tx *)malloc(sizeof(struct video_tx));
if (tx != NULL) {
tx->magic = TRANSMIT_MAGIC;
tx->mtu = mtu;
}
return tx;
}
void
tx_done(struct video_tx *tx)
void tx_done(struct video_tx *tx)
{
assert(tx->magic == TRANSMIT_MAGIC);
free(tx);
assert(tx->magic == TRANSMIT_MAGIC);
free(tx);
}
void
tx_send(struct video_tx *tx, struct video_frame *frame, struct rtp *rtp_session)
{
int m, data_len;
payload_hdr_t payload_hdr;
int pt = 96; /* A dynamic payload type for the tests... */
static uint32_t ts = 0;
char *data;
unsigned int pos;
int m, data_len;
payload_hdr_t payload_hdr;
int pt = 96; /* A dynamic payload type for the tests... */
static uint32_t ts = 0;
char *data;
unsigned int pos;
#if HAVE_MACOSX
struct timeval start, stop;
#else /* HAVE_MACOSX */
struct timeval start, stop;
#else /* HAVE_MACOSX */
struct timespec start, stop;
#endif /* HAVE_MACOSX */
long delta;
#endif /* HAVE_MACOSX */
long delta;
assert(tx->magic == TRANSMIT_MAGIC);
assert(tx->magic == TRANSMIT_MAGIC);
m = 0;
ts = get_local_mediatime();
m = 0;
ts = get_local_mediatime();
pos = 0;
payload_hdr.width = htons(frame->width);
payload_hdr.height = htons(frame->height);
payload_hdr.colorspc = frame->color_spec;
do {
payload_hdr.offset = htonl(pos);
payload_hdr.flags = htons(1<<15);
do {
payload_hdr.offset = htonl(pos);
payload_hdr.flags = htons(1 << 15);
data = frame->data + pos;
data = frame->data + pos;
data_len = tx->mtu - 40 - (sizeof(payload_hdr_t));
if(pos + data_len > frame->data_len) {
m = 1;
data_len = frame->data_len - pos;
if (pos + data_len > frame->data_len) {
m = 1;
data_len = frame->data_len - pos;
}
pos += data_len;
payload_hdr.length = htons(data_len);
GET_STARTTIME;
rtp_send_data_hdr(rtp_session, ts, pt, m, 0, 0, (char *)&payload_hdr,
sizeof(payload_hdr_t), data, data_len, 0, 0, 0);
do {
GET_STOPTIME;
GET_DELTA;
if(delta < 0)
delta += 1000000000L;
} while(packet_rate - delta > 0);
payload_hdr.length = htons(data_len);
GET_STARTTIME;
rtp_send_data_hdr(rtp_session, ts, pt, m, 0, 0,
(char *)&payload_hdr, sizeof(payload_hdr_t),
data, data_len, 0, 0, 0);
do {
GET_STOPTIME;
GET_DELTA;
if (delta < 0)
delta += 1000000000L;
} while (packet_rate - delta > 0);
} while (pos < frame->data_len);
} while (pos < frame->data_len);
}
#ifdef HAVE_AUDIO
void
audio_tx_send(struct rtp *rtp_session, audio_frame *buffer)
void audio_tx_send(struct rtp *rtp_session, audio_frame * buffer)
{
audio_frame_to_network_buffer(buffer->tmp_buffer, buffer);
audio_frame_to_network_buffer(buffer->tmp_buffer, buffer);
//uint32_t timestamp = get_local_mediatime();
static uint32_t timestamp;
timestamp++;
//uint32_t timestamp = get_local_mediatime();
static uint32_t timestamp;
timestamp++;
int marker_bit = 0; // FIXME: probably should define last packet of a frame, but is payload dependand so...think this through
rtp_send_data(rtp_session, timestamp, audio_payload_type, marker_bit,
0, /* contributing sources */
0, /* contributing sources length*/
buffer->tmp_buffer, buffer->samples_per_channel * 3 * 8, 0, 0, 0);
int marker_bit = 0; // FIXME: probably should define last packet of a frame, but is payload dependand so...think this through
rtp_send_data(rtp_session, timestamp, audio_payload_type, marker_bit, 0, /* contributing sources */
0, /* contributing sources length */
buffer->tmp_buffer, buffer->samples_per_channel * 3 * 8,
0, 0, 0);
}
#endif /* HAVE_AUDIO */
#endif /* HAVE_AUDIO */

View File

@@ -51,14 +51,13 @@
#include "crypto/random.h"
#include "tv.h"
uint32_t
get_local_mediatime(void)
uint32_t get_local_mediatime(void)
{
static struct timeval start_time;
static uint32_t random_offset;
static int first = 0;
struct timeval curr_time;
static struct timeval start_time;
static uint32_t random_offset;
static int first = 0;
struct timeval curr_time;
if (first == 0) {
gettimeofday(&start_time, NULL);
@@ -70,41 +69,39 @@ get_local_mediatime(void)
return (tv_diff(curr_time, start_time) * 90000) + random_offset;
}
double
tv_diff(struct timeval curr_time, struct timeval prev_time)
double tv_diff(struct timeval curr_time, struct timeval prev_time)
{
/* Return (curr_time - prev_time) in seconds */
double ct, pt;
/* Return (curr_time - prev_time) in seconds */
double ct, pt;
ct = (double) curr_time.tv_sec + (((double) curr_time.tv_usec) / 1000000.0);
pt = (double) prev_time.tv_sec + (((double) prev_time.tv_usec) / 1000000.0);
return (ct - pt);
ct = (double)curr_time.tv_sec +
(((double)curr_time.tv_usec) / 1000000.0);
pt = (double)prev_time.tv_sec +
(((double)prev_time.tv_usec) / 1000000.0);
return (ct - pt);
}
uint32_t
tv_diff_usec (struct timeval curr_time, struct timeval prev_time)
{
/* Return curr_time - prev_time in usec - i wonder if these numbers will be too big?*/
uint32_t tmp, tmp1, tmp2;
uint32_t tv_diff_usec(struct timeval curr_time, struct timeval prev_time)
{
/* Return curr_time - prev_time in usec - i wonder if these numbers will be too big? */
uint32_t tmp, tmp1, tmp2;
/* We return an unsigned, so fail is prev_time is later than curr_time */
assert(curr_time.tv_sec >= prev_time.tv_sec);
if (curr_time.tv_sec == prev_time.tv_sec) {
assert(curr_time.tv_usec >= prev_time.tv_usec);
}
/* We return an unsigned, so fail is prev_time is later than curr_time */
assert(curr_time.tv_sec >= prev_time.tv_sec);
if (curr_time.tv_sec == prev_time.tv_sec) {
assert(curr_time.tv_usec >= prev_time.tv_usec);
}
tmp1 = (curr_time.tv_sec - prev_time.tv_sec)*((uint32_t)1000000);
tmp1 = (curr_time.tv_sec - prev_time.tv_sec) * ((uint32_t) 1000000);
tmp2 = curr_time.tv_usec - prev_time.tv_usec;
tmp = tmp1+tmp2;
tmp = tmp1 + tmp2;
return tmp;
return tmp;
}
void
tv_add(struct timeval *ts, double offset_secs)
void tv_add(struct timeval *ts, double offset_secs)
{
unsigned int offset = (unsigned long) (offset_secs * 1000000.0);
unsigned int offset = (unsigned long)(offset_secs * 1000000.0);
ts->tv_usec += offset;
while (ts->tv_usec >= 1000000) {
@@ -113,8 +110,7 @@ tv_add(struct timeval *ts, double offset_secs)
}
}
int
tv_gt(struct timeval a, struct timeval b)
int tv_gt(struct timeval a, struct timeval b)
{
/* Returns (a>b) */
if (a.tv_sec > b.tv_sec) {
@@ -126,4 +122,3 @@ tv_gt(struct timeval a, struct timeval b)
assert(a.tv_sec == b.tv_sec);
return a.tv_usec > b.tv_usec;
}

View File

@@ -68,184 +68,171 @@
#define VIDCAP_MAGIC 0x76ae98f0
struct vidcap {
void *state;
int index;
uint32_t magic; /* For debugging */
void *state;
int index;
uint32_t magic; /* For debugging */
};
struct vidcap_device_api {
vidcap_id_t id;
struct vidcap_type *(*func_probe)(void);
void *(*func_init)(char *fmt);
void (*func_done)(void *state);
struct video_frame *(*func_grab)(void *state);
vidcap_id_t id;
struct vidcap_type *(*func_probe) (void);
void *(*func_init) (char *fmt);
void (*func_done) (void *state);
struct video_frame *(*func_grab) (void *state);
};
struct vidcap_device_api vidcap_device_table[] = {
#ifdef HAVE_FIREWIRE_DV_FREEBSD
{
/* A FireWire DV capture card, on FreeBSD */
0,
vidcap_dvbsd_probe,
vidcap_dvbsd_init,
vidcap_dvbsd_done,
vidcap_dvbsd_grab
},
#endif /* HAVE_FIREWIRE_DV_FREEBSD */
#ifdef HAVE_HDSTATION
{
/* The DVS HDstation capture card */
0,
vidcap_hdstation_probe,
vidcap_hdstation_init,
vidcap_hdstation_done,
vidcap_hdstation_grab
},
#endif /* HAVE_HDSTATION */
#ifdef HAVE_DECKLINK
{
/* The Blackmagic DeckLink capture card */
0,
vidcap_decklink_probe,
vidcap_decklink_init,
vidcap_decklink_done,
vidcap_decklink_grab
},
#endif /* HAVE_DECKLINK */
#ifdef HAVE_QUAD
{
/* The HD-SDI Master Quad capture card */
0,
vidcap_quad_probe,
vidcap_quad_init,
vidcap_quad_done,
vidcap_quad_grab
},
#endif /* HAVE_QUAD */
/* A FireWire DV capture card, on FreeBSD */
0,
vidcap_dvbsd_probe,
vidcap_dvbsd_init,
vidcap_dvbsd_done,
vidcap_dvbsd_grab},
#endif /* HAVE_FIREWIRE_DV_FREEBSD */
#ifdef HAVE_HDSTATION
{
/* The DVS HDstation capture card */
0,
vidcap_hdstation_probe,
vidcap_hdstation_init,
vidcap_hdstation_done,
vidcap_hdstation_grab},
#endif /* HAVE_HDSTATION */
#ifdef HAVE_DECKLINK
{
/* The Blackmagic DeckLink capture card */
0,
vidcap_decklink_probe,
vidcap_decklink_init,
vidcap_decklink_done,
vidcap_decklink_grab},
#endif /* HAVE_DECKLINK */
#ifdef HAVE_QUAD
{
/* The HD-SDI Master Quad capture card */
0,
vidcap_quad_probe,
vidcap_quad_init,
vidcap_quad_done,
vidcap_quad_grab},
#endif /* HAVE_QUAD */
#ifdef HAVE_MACOSX
{
/* The QuickTime API */
0,
vidcap_quicktime_probe,
vidcap_quicktime_init,
vidcap_quicktime_done,
vidcap_quicktime_grab
},
#endif /* HAVE_MACOSX */
{
/* Dummy sender for testing purposes */
0,
vidcap_testcard_probe,
vidcap_testcard_init,
vidcap_testcard_done,
vidcap_testcard_grab
},
{
0,
vidcap_null_probe,
vidcap_null_init,
vidcap_null_done,
vidcap_null_grab
}
{
/* The QuickTime API */
0,
vidcap_quicktime_probe,
vidcap_quicktime_init,
vidcap_quicktime_done,
vidcap_quicktime_grab},
#endif /* HAVE_MACOSX */
{
/* Dummy sender for testing purposes */
0,
vidcap_testcard_probe,
vidcap_testcard_init,
vidcap_testcard_done,
vidcap_testcard_grab},
{
0,
vidcap_null_probe,
vidcap_null_init,
vidcap_null_done,
vidcap_null_grab}
};
#define VIDCAP_DEVICE_TABLE_SIZE (sizeof(vidcap_device_table)/sizeof(struct vidcap_device_api))
/* API for probing capture devices ****************************************************************/
static struct vidcap_type *available_devices[VIDCAP_DEVICE_TABLE_SIZE];
static int available_device_count = 0;
static struct vidcap_type *available_devices[VIDCAP_DEVICE_TABLE_SIZE];
static int available_device_count = 0;
int
vidcap_init_devices(void)
int vidcap_init_devices(void)
{
unsigned int i;
struct vidcap_type *dt;
unsigned int i;
struct vidcap_type *dt;
assert(available_device_count == 0);
assert(available_device_count == 0);
for (i = 0; i < VIDCAP_DEVICE_TABLE_SIZE; i++) {
//printf("probe: %d\n",i);
dt = vidcap_device_table[i].func_probe();
if (dt != NULL) {
vidcap_device_table[i].id = dt->id;
available_devices[available_device_count++] = dt;
}
}
for (i = 0; i < VIDCAP_DEVICE_TABLE_SIZE; i++) {
//printf("probe: %d\n",i);
dt = vidcap_device_table[i].func_probe();
if (dt != NULL) {
vidcap_device_table[i].id = dt->id;
available_devices[available_device_count++] = dt;
}
}
return available_device_count;
return available_device_count;
}
void
vidcap_free_devices(void)
void vidcap_free_devices(void)
{
int i;
int i;
for (i = 0; i < available_device_count; i++) {
free(available_devices[i]);
available_devices[i] = NULL;
}
available_device_count = 0;
for (i = 0; i < available_device_count; i++) {
free(available_devices[i]);
available_devices[i] = NULL;
}
available_device_count = 0;
}
int
vidcap_get_device_count(void)
int vidcap_get_device_count(void)
{
return available_device_count;
return available_device_count;
}
struct vidcap_type *
vidcap_get_device_details(int index)
struct vidcap_type *vidcap_get_device_details(int index)
{
assert(index < available_device_count);
assert(available_devices[index] != NULL);
assert(index < available_device_count);
assert(available_devices[index] != NULL);
return available_devices[index];
return available_devices[index];
}
vidcap_id_t
vidcap_get_null_device_id(void)
vidcap_id_t vidcap_get_null_device_id(void)
{
return VIDCAP_NULL_ID;
return VIDCAP_NULL_ID;
}
/* API for video capture **************************************************************************/
struct vidcap *
vidcap_init(vidcap_id_t id, char *fmt)
struct vidcap *vidcap_init(vidcap_id_t id, char *fmt)
{
unsigned int i;
unsigned int i;
for (i = 0; i < VIDCAP_DEVICE_TABLE_SIZE; i++) {
if (vidcap_device_table[i].id == id) {
struct vidcap *d = (struct vidcap *) malloc(sizeof(struct vidcap));
d->magic = VIDCAP_MAGIC;
d->state = vidcap_device_table[i].func_init(fmt);
d->index = i;
if (d->state == NULL) {
debug_msg("Unable to start video capture device 0x%08lx\n", id);
free(d);
return NULL;
}
return d;
}
}
debug_msg("Unknown video capture device: 0x%08x\n", id);
return NULL;
for (i = 0; i < VIDCAP_DEVICE_TABLE_SIZE; i++) {
if (vidcap_device_table[i].id == id) {
struct vidcap *d =
(struct vidcap *)malloc(sizeof(struct vidcap));
d->magic = VIDCAP_MAGIC;
d->state = vidcap_device_table[i].func_init(fmt);
d->index = i;
if (d->state == NULL) {
debug_msg
("Unable to start video capture device 0x%08lx\n",
id);
free(d);
return NULL;
}
return d;
}
}
debug_msg("Unknown video capture device: 0x%08x\n", id);
return NULL;
}
void
vidcap_done(struct vidcap *state)
void vidcap_done(struct vidcap *state)
{
assert(state->magic == VIDCAP_MAGIC);
vidcap_device_table[state->index].func_done(state->state);
free(state);
assert(state->magic == VIDCAP_MAGIC);
vidcap_device_table[state->index].func_done(state->state);
free(state);
}
struct video_frame *
vidcap_grab(struct vidcap *state)
struct video_frame *vidcap_grab(struct vidcap *state)
{
assert(state->magic == VIDCAP_MAGIC);
return vidcap_device_table[state->index].func_grab(state->state);
assert(state->magic == VIDCAP_MAGIC);
return vidcap_device_table[state->index].func_grab(state->state);
}

View File

@@ -56,93 +56,87 @@
#include "video_capture/firewire_dv_freebsd.h"
struct vidcap_dvbsd_state {
int fd; /* File descriptor for the device */
// int fps;
int fd; /* File descriptor for the device */
// int fps;
};
void *
vidcap_dvbsd_init(char *fmt)
void *vidcap_dvbsd_init(char *fmt)
{
int fps = atoi(fmt); //FIXME What is fps good for?
struct vidcap_dvbsd_state *s;
struct fw_isochreq isoreq;
struct fw_isobufreq bufreq;
int fps = atoi(fmt); //FIXME What is fps good for?
struct vidcap_dvbsd_state *s;
struct fw_isochreq isoreq;
struct fw_isobufreq bufreq;
s = malloc(sizeof(struct vidcap_dvbsd_state));
if (s == NULL) {
return NULL;
}
s = malloc(sizeof(struct vidcap_dvbsd_state));
if (s == NULL) {
return NULL;
}
// s->fps = fps;
// s->fps = fps;
s->fd = open("/dev/fw0.0", O_RDWR);
if (s->fd < 0) {
perror("Unable to open /dev/fw0.0");
free(s);
return NULL;
}
s->fd = open("/dev/fw0.0", O_RDWR);
if (s->fd < 0) {
perror("Unable to open /dev/fw0.0");
free(s);
return NULL;
}
bufreq.rx.nchunk = 8;
bufreq.rx.npacket = 256;
bufreq.rx.psize = 512;
bufreq.tx.nchunk = 0;
bufreq.tx.npacket = 0;
bufreq.tx.psize = 0;
if (ioctl(s->fd, FW_SSTBUF, &bufreq) < 0) {
perror("Unable to configure IEEE-1394 capture device");
close(s->fd);
free(s);
return NULL;
}
bufreq.rx.nchunk = 8;
bufreq.rx.npacket = 256;
bufreq.rx.psize = 512;
bufreq.tx.nchunk = 0;
bufreq.tx.npacket = 0;
bufreq.tx.psize = 0;
if (ioctl(s->fd, FW_SSTBUF, &bufreq) < 0) {
perror("Unable to configure IEEE-1394 capture device");
close(s->fd);
free(s);
return NULL;
}
isoreq.ch = 63;
isoreq.tag = 1 << 6;
if (ioctl(s->fd, FW_SRSTREAM, &isoreq) < 0) {
perror("Unable to start IEEE-1394 capture device");
close(s->fd);
free(s);
return NULL;
}
isoreq.ch = 63;
isoreq.tag = 1<<6;
if (ioctl(s->fd, FW_SRSTREAM, &isoreq) < 0) {
perror("Unable to start IEEE-1394 capture device");
close(s->fd);
free(s);
return NULL;
}
return s;
return s;
}
void
vidcap_dvbsd_done(void *state)
void vidcap_dvbsd_done(void *state)
{
struct vidcap_dvbsd_state *s = (struct vidcap_dvbsd_state *) state;
struct vidcap_dvbsd_state *s = (struct vidcap_dvbsd_state *)state;
assert(s != NULL);
close(s->fd);
free(s);
assert(s != NULL);
close(s->fd);
free(s);
}
struct video_frame *
vidcap_dvbsd_grab(void *state)
struct video_frame *vidcap_dvbsd_grab(void *state)
{
struct vidcap_dvbsd_state *s = (struct vidcap_dvbsd_state *) state;
struct vidcap_dvbsd_state *s = (struct vidcap_dvbsd_state *)state;
assert(s != NULL);
assert(s != NULL);
return NULL;
return NULL;
}
struct vidcap_type *
vidcap_dvbsd_probe(void)
struct vidcap_type *vidcap_dvbsd_probe(void)
{
struct vidcap_type *vt;
struct vidcap_type *vt;
vt = (struct vidcap_type *) malloc(sizeof(struct vidcap_type));
vt = (struct vidcap_type *)malloc(sizeof(struct vidcap_type));
if (vt != NULL) {
vt->id = VIDCAP_DVBSD_ID;
vt->name = "dv";
vt->id = VIDCAP_DVBSD_ID;
vt->name = "dv";
vt->description = "IEEE-1394/DV";
vt->width = 720; /* PAL frame size */
vt->height = 576;
vt->width = 720; /* PAL frame size */
vt->height = 576;
vt->colour_mode = YUV_422;
}
return vt;
}
#endif /* HAVE_FIREWIRE_DV_FREEBSD */
#endif /* HAVE_FIREWIRE_DV_FREEBSD */

View File

@@ -57,281 +57,282 @@
#include "config_unix.h"
#include "config_win32.h"
#ifdef HAVE_HDSTATION /* From config.h */
#ifdef HAVE_HDSTATION /* From config.h */
#include "debug.h"
#include "video_capture.h"
#include "video_capture/hdstation.h"
#include "video_codec.h"
#include "tv.h"
#include "dvs_clib.h" /* From the DVS SDK */
#include "dvs_fifo.h" /* From the DVS SDK */
#include "dvs_clib.h" /* From the DVS SDK */
#include "dvs_fifo.h" /* From the DVS SDK */
struct vidcap_hdstation_state {
sv_handle *sv;
sv_fifo *fifo;
sv_fifo_buffer *dma_buffer;
char *rtp_buffer;
char *tmp_buffer;
int buffer_size;
pthread_t thread_id;
pthread_mutex_t lock;
pthread_cond_t boss_cv;
pthread_cond_t worker_cv;
int boss_waiting;
int worker_waiting;
int work_to_do;
char *bufs[2];
int bufs_index;
codec_t codec;
uint32_t hd_video_mode;
double bpp;
sv_handle *sv;
sv_fifo *fifo;
sv_fifo_buffer *dma_buffer;
char *rtp_buffer;
char *tmp_buffer;
int buffer_size;
pthread_t thread_id;
pthread_mutex_t lock;
pthread_cond_t boss_cv;
pthread_cond_t worker_cv;
int boss_waiting;
int worker_waiting;
int work_to_do;
char *bufs[2];
int bufs_index;
codec_t codec;
uint32_t hd_video_mode;
double bpp;
};
static void *
vidcap_hdstation_grab_thread(void *arg)
static void *vidcap_hdstation_grab_thread(void *arg)
{
int res;
struct vidcap_hdstation_state *s = (struct vidcap_hdstation_state *) arg;
int res;
struct vidcap_hdstation_state *s = (struct vidcap_hdstation_state *)arg;
while (1) {
s->dma_buffer = NULL;
res = sv_fifo_vsyncwait(s->sv, s->fifo);
while (1) {
s->dma_buffer = NULL;
res = sv_fifo_vsyncwait(s->sv, s->fifo);
res = sv_fifo_getbuffer(s->sv, s->fifo, &(s->dma_buffer), NULL, SV_FIFO_FLAG_VIDEOONLY|SV_FIFO_FLAG_FLUSH);
if (res != SV_OK) {
printf("Unable to getbuffer %s\n", sv_geterrortext(res));
continue;
}
s->bufs_index = (s->bufs_index + 1) % 2;
s->dma_buffer->dma.addr = s->bufs[s->bufs_index];
s->dma_buffer->dma.size = s->buffer_size;
res =
sv_fifo_getbuffer(s->sv, s->fifo, &(s->dma_buffer), NULL,
SV_FIFO_FLAG_VIDEOONLY |
SV_FIFO_FLAG_FLUSH);
if (res != SV_OK) {
printf("Unable to getbuffer %s\n",
sv_geterrortext(res));
continue;
}
s->bufs_index = (s->bufs_index + 1) % 2;
s->dma_buffer->dma.addr = s->bufs[s->bufs_index];
s->dma_buffer->dma.size = s->buffer_size;
res = sv_fifo_putbuffer(s->sv, s->fifo, s->dma_buffer, NULL);
if (res != SV_OK) {
printf("Unable to putbuffer %s\n", sv_geterrortext(res));
}
res = sv_fifo_putbuffer(s->sv, s->fifo, s->dma_buffer, NULL);
if (res != SV_OK) {
printf("Unable to putbuffer %s\n",
sv_geterrortext(res));
}
pthread_mutex_lock(&(s->lock));
pthread_mutex_lock(&(s->lock));
while (s->work_to_do == FALSE) {
s->worker_waiting = TRUE;
pthread_cond_wait(&(s->worker_cv), &(s->lock));
s->worker_waiting = FALSE;
}
while (s->work_to_do == FALSE) {
s->worker_waiting = TRUE;
pthread_cond_wait(&(s->worker_cv), &(s->lock));
s->worker_waiting = FALSE;
}
s->tmp_buffer = s->dma_buffer->dma.addr;
s->work_to_do = FALSE;
s->tmp_buffer = s->dma_buffer->dma.addr;
s->work_to_do = FALSE;
if (s->boss_waiting) {
pthread_cond_signal(&(s->boss_cv));
}
pthread_mutex_unlock(&(s->lock));
}
return NULL;
if (s->boss_waiting) {
pthread_cond_signal(&(s->boss_cv));
}
pthread_mutex_unlock(&(s->lock));
}
return NULL;
}
/* External API ***********************************************************************************/
struct vidcap_type *
vidcap_hdstation_probe(void)
struct vidcap_type *vidcap_hdstation_probe(void)
{
struct vidcap_type *vt;
sv_handle *sv;
struct vidcap_type *vt;
sv_handle *sv;
sv = sv_open("");
if (sv == NULL) {
debug_msg("Cannot probe HDTV capture device\n");
return NULL;
}
sv_close(sv);
sv = sv_open("");
if (sv == NULL) {
debug_msg("Cannot probe HDTV capture device\n");
return NULL;
}
sv_close(sv);
hd_size_x = 1920;
hd_size_y = 1080;
hd_size_x = 1920;
hd_size_y = 1080;
vt = (struct vidcap_type *) malloc(sizeof(struct vidcap_type));
if (vt != NULL) {
vt->id = VIDCAP_HDSTATION_ID;
vt->name = "hdtv";
vt->description = "DVS HDstation (SMPTE 274M/25i)";
vt->width = hd_size_x;
vt->height = hd_size_y;
}
return vt;
vt = (struct vidcap_type *)malloc(sizeof(struct vidcap_type));
if (vt != NULL) {
vt->id = VIDCAP_HDSTATION_ID;
vt->name = "hdtv";
vt->description = "DVS HDstation (SMPTE 274M/25i)";
vt->width = hd_size_x;
vt->height = hd_size_y;
}
return vt;
}
void *
vidcap_hdstation_init(char *fmt)
void *vidcap_hdstation_init(char *fmt)
{
int fps = 29;
struct vidcap_hdstation_state *s;
int i;
int res;
int fps = 29;
struct vidcap_hdstation_state *s;
int i;
int res;
if (fmt != NULL) {
if (strcmp(fmt, "help") == 0) {
printf("hdstation options:\n");
printf("\tfps:codec\n");
if (fmt != NULL) {
if (strcmp(fmt, "help") == 0) {
printf("hdstation options:\n");
printf("\tfps:codec\n");
return 0;
}
return 0;
}
char *tmp;
char *tmp;
tmp = strtok(fmt, ":");
if (!tmp) {
fprintf(stderr, "Wrong config %s\n", fmt);
return 0;
}
fps = atoi(tmp);
tmp = strtok(NULL, ":");
if (!tmp) {
fprintf(stderr, "Wrong config %s\n", fmt);
return 0;
}
s->codec = 0xffffffff;
for(i = 0; codec_info[i].name != NULL; i++) {
if(strcmp(tmp, codec_info[i].name) == 0) {
s->codec = codec_info[i].codec;
s->bpp = codec_info[i].bpp;
tmp = strtok(fmt, ":");
if (!tmp) {
fprintf(stderr, "Wrong config %s\n", fmt);
return 0;
}
fps = atoi(tmp);
tmp = strtok(NULL, ":");
if (!tmp) {
fprintf(stderr, "Wrong config %s\n", fmt);
return 0;
}
s->codec = 0xffffffff;
for (i = 0; codec_info[i].name != NULL; i++) {
if (strcmp(tmp, codec_info[i].name) == 0) {
s->codec = codec_info[i].codec;
s->bpp = codec_info[i].bpp;
}
}
if (s->codec == 0xffffffff) {
fprintf(stderr, "hdstation: unknown codec: %s\n", tmp);
free(tmp);
return 0;
}
}
if(s->codec == 0xffffffff) {
fprintf(stderr, "hdstation: unknown codec: %s\n", tmp);
free(tmp);
return 0;
s->hd_video_mode = SV_MODE_COLOR_YUV422 | SV_MODE_ACTIVE_STREAMER;
if (s->codec == DVS10) {
s->hd_video_mode |= SV_MODE_NBIT_10BDVS;
}
}
s->hd_video_mode=SV_MODE_COLOR_YUV422 | SV_MODE_ACTIVE_STREAMER;
if (s->codec == DVS10) {
s->hd_video_mode |= SV_MODE_NBIT_10BDVS;
}
if (fps == 25) {
s->hd_video_mode |= SV_MODE_SMPTE274_25P;
} else if (fps == 29) {
s->hd_video_mode |= SV_MODE_SMPTE274_29I;
} else {
fprintf(stderr, "Wrong framerate in config %s\n", fmt);
return 0;
}
if (fps == 25) {
s->hd_video_mode |= SV_MODE_SMPTE274_25P;
}
else if (fps == 29) {
s->hd_video_mode |= SV_MODE_SMPTE274_29I;
}
else {
fprintf(stderr, "Wrong framerate in config %s\n", fmt);
return 0;
}
hd_size_x = 1920;
hd_size_y = 1080;
hd_color_spc = s->codec;
hd_size_x = 1920;
hd_size_y = 1080;
hd_color_spc = s->codec;
s = (struct vidcap_hdstation_state *)
malloc(sizeof(struct vidcap_hdstation_state));
if (s == NULL) {
debug_msg("Unable to allocate HDstation state\n");
return NULL;
}
s = (struct vidcap_hdstation_state *) malloc(sizeof(struct vidcap_hdstation_state));
if (s == NULL) {
debug_msg("Unable to allocate HDstation state\n");
return NULL;
}
s->sv = sv_open("");
if (s->sv == NULL) {
printf
("Unable to open grabber: sv_open() failed (no card present or driver not loaded?)\n");
free(s);
return NULL;
}
s->sv = sv_open("");
if (s->sv == NULL) {
printf("Unable to open grabber: sv_open() failed (no card present or driver not loaded?)\n");
free(s);
return NULL;
}
res = sv_videomode(s->sv, s->hd_video_mode | SV_MODE_AUDIO_NOAUDIO);
if (res != SV_OK) {
goto error;
}
res = sv_black(s->sv);
if (res != SV_OK) {
goto error;
}
res = sv_fifo_init(s->sv, &(s->fifo), 1, 1, 1, 0, 0);
if (res != SV_OK) {
goto error;
}
res = sv_fifo_start(s->sv, s->fifo);
if (res != SV_OK) {
goto error;
}
res = sv_videomode(s->sv, s->hd_video_mode | SV_MODE_AUDIO_NOAUDIO);
if (res != SV_OK) {
goto error;
}
res = sv_black(s->sv);
if (res != SV_OK) {
goto error;
}
res = sv_fifo_init(s->sv, &(s->fifo), 1, 1, 1, 0, 0);
if (res != SV_OK) {
goto error;
}
res = sv_fifo_start(s->sv, s->fifo);
if (res != SV_OK) {
goto error;
}
pthread_mutex_init(&(s->lock), NULL);
pthread_cond_init(&(s->boss_cv), NULL);
pthread_cond_init(&(s->worker_cv), NULL);
pthread_mutex_init(&(s->lock), NULL);
pthread_cond_init(&(s->boss_cv), NULL);
pthread_cond_init(&(s->worker_cv), NULL);
s->buffer_size = s->bpp * hd_size_x * hd_size_y;
s->rtp_buffer = NULL;
s->dma_buffer = NULL;
s->tmp_buffer = NULL;
s->boss_waiting = FALSE;
s->worker_waiting = FALSE;
s->work_to_do = FALSE;
s->bufs[0] = malloc(s->buffer_size);
s->bufs[1] = malloc(s->buffer_size);
s->bufs_index = 0;
s->buffer_size = s->bpp * hd_size_x * hd_size_y;
s->rtp_buffer = NULL;
s->dma_buffer = NULL;
s->tmp_buffer = NULL;
s->boss_waiting = FALSE;
s->worker_waiting = FALSE;
s->work_to_do = FALSE;
s->bufs[0] = malloc(s->buffer_size);
s->bufs[1] = malloc(s->buffer_size);
s->bufs_index = 0;
if (pthread_create
(&(s->thread_id), NULL, vidcap_hdstation_grab_thread, s) != 0) {
perror("Unable to create grabbing thread");
return NULL;
}
if (pthread_create(&(s->thread_id), NULL, vidcap_hdstation_grab_thread, s) != 0) {
perror("Unable to create grabbing thread");
return NULL;
}
debug_msg("HDstation capture device enabled\n");
return s;
error:
free(s);
printf("Chyba %s\n",sv_geterrortext(res));
debug_msg("Unable to open grabber: %s\n", sv_geterrortext(res));
return NULL;
debug_msg("HDstation capture device enabled\n");
return s;
error:
free(s);
printf("Chyba %s\n", sv_geterrortext(res));
debug_msg("Unable to open grabber: %s\n", sv_geterrortext(res));
return NULL;
}
void
vidcap_hdstation_done(void *state)
void vidcap_hdstation_done(void *state)
{
struct vidcap_hdstation_state *s = (struct vidcap_hdstation_state *) state;
struct vidcap_hdstation_state *s =
(struct vidcap_hdstation_state *)state;
sv_fifo_free(s->sv, s->fifo);
sv_close(s->sv);
free(s);
sv_fifo_free(s->sv, s->fifo);
sv_close(s->sv);
free(s);
}
struct video_frame *
vidcap_hdstation_grab(void *state)
struct video_frame *vidcap_hdstation_grab(void *state)
{
struct vidcap_hdstation_state *s = (struct vidcap_hdstation_state *) state;
struct video_frame *vf;
struct vidcap_hdstation_state *s =
(struct vidcap_hdstation_state *)state;
struct video_frame *vf;
pthread_mutex_lock(&(s->lock));
pthread_mutex_lock(&(s->lock));
/* Wait for the worker to finish... */
while (s->work_to_do) {
s->boss_waiting = TRUE;
pthread_cond_wait(&(s->boss_cv), &(s->lock));
s->boss_waiting = FALSE;
}
/* Wait for the worker to finish... */
while (s->work_to_do) {
s->boss_waiting = TRUE;
pthread_cond_wait(&(s->boss_cv), &(s->lock));
s->boss_waiting = FALSE;
}
/* ...and give it more to do... */
s->rtp_buffer = s->tmp_buffer;
s->work_to_do = TRUE;
/* ...and give it more to do... */
s->rtp_buffer = s->tmp_buffer;
s->work_to_do = TRUE;
/* ...and signal the worker... */
if (s->worker_waiting) {
pthread_cond_signal(&(s->worker_cv));
}
/* ...and signal the worker... */
if (s->worker_waiting) {
pthread_cond_signal(&(s->worker_cv));
}
pthread_mutex_unlock(&(s->lock));
pthread_mutex_unlock(&(s->lock));
if (s->rtp_buffer != NULL) {
vf = (struct video_frame *) malloc(sizeof(struct video_frame));
if (vf != NULL) {
vf->width = hd_size_x;
vf->height = hd_size_y;
vf->data = s->rtp_buffer;
vf->data_len = hd_size_x * hd_size_y * s->bpp;
}
return vf;
}
return NULL;
if (s->rtp_buffer != NULL) {
vf = (struct video_frame *)malloc(sizeof(struct video_frame));
if (vf != NULL) {
vf->width = hd_size_x;
vf->height = hd_size_y;
vf->data = s->rtp_buffer;
vf->data_len = hd_size_x * hd_size_y * s->bpp;
}
return vf;
}
return NULL;
}
#endif /* HAVE_HDSTATION */
#endif /* HAVE_HDSTATION */

View File

@@ -2,28 +2,28 @@
int main(int argc, char *argv[])
{
FILE *inf, *outf;
int c, i=0;
FILE *inf, *outf;
int c, i = 0;
if (argc != 3) {
printf("Usage: make_testcard <infile> <outfile>\n");
return 1;
}
if (argc != 3) {
printf("Usage: make_testcard <infile> <outfile>\n");
return 1;
}
outf = fopen(argv[2], "w");
fprintf(outf, "/* Automatically generated: DO NOT EDIT! */\n");
fprintf(outf, "unsigned char testcard_image[] = \"");
outf = fopen(argv[2], "w");
fprintf(outf, "/* Automatically generated: DO NOT EDIT! */\n");
fprintf(outf, "unsigned char testcard_image[] = \"");
inf = fopen(argv[1], "r");
while (!feof(inf)) {
c = fgetc(inf);
if (c != EOF) fprintf(outf, "\\x%02x", c);
}
fclose(inf);
inf = fopen(argv[1], "r");
while (!feof(inf)) {
c = fgetc(inf);
if (c != EOF)
fprintf(outf, "\\x%02x", c);
}
fclose(inf);
fprintf(outf, "\";\n");
fclose(outf);
fprintf(outf, "\";\n");
fclose(outf);
return 0;
return 0;
}

View File

@@ -56,42 +56,37 @@
#include "video_capture.h"
#include "video_capture/null.h"
static int capture_state = 0;
static int capture_state = 0;
void *
vidcap_null_init(char *fmt)
void *vidcap_null_init(char *fmt)
{
UNUSED(fmt);
capture_state = 0;
return &capture_state;
UNUSED(fmt);
capture_state = 0;
return &capture_state;
}
void
vidcap_null_done(void *state)
void vidcap_null_done(void *state)
{
assert(state == &capture_state);
assert(state == &capture_state);
}
struct video_frame *
vidcap_null_grab(void *state)
struct video_frame *vidcap_null_grab(void *state)
{
assert(state == &capture_state);
return NULL;
assert(state == &capture_state);
return NULL;
}
struct vidcap_type *
vidcap_null_probe(void)
struct vidcap_type *vidcap_null_probe(void)
{
struct vidcap_type *vt;
struct vidcap_type *vt;
vt = (struct vidcap_type *) malloc(sizeof(struct vidcap_type));
if (vt != NULL) {
vt->id = VIDCAP_NULL_ID;
vt->name = "null";
vt->description = "No video capture device";
vt->width = 0;
vt->height = 0;
}
return vt;
vt = (struct vidcap_type *)malloc(sizeof(struct vidcap_type));
if (vt != NULL) {
vt->id = VIDCAP_NULL_ID;
vt->name = "null";
vt->description = "No video capture device";
vt->width = 0;
vt->height = 0;
}
return vt;
}

View File

@@ -50,7 +50,7 @@
#include "config_win32.h"
#ifndef HAVE_MACOSX
#ifdef HAVE_QUAD /* From config.h */
#ifdef HAVE_QUAD /* From config.h */
#include "debug.h"
#include "video_types.h"
@@ -74,10 +74,10 @@
#define BUFLEN 256
extern int should_exit;
extern int should_exit;
const char device[] = "/dev/sdirx0";
const char fmt[] = "/sys/class/sdi/sdirx%i/%s";
const char device[] = "/dev/sdirx0";
const char fmt[] = "/sys/class/sdi/sdirx%i/%s";
int fd;
ssize_t ret, read_ret, bytes;
@@ -88,295 +88,287 @@ unsigned int frames, last_frames, timestamp, last_timestamp;
unsigned int val;
struct vidcap_quad_state {
char name[BUFLEN];
unsigned char* data;
unsigned long int bufsize;
char name[BUFLEN];
unsigned char *data;
unsigned long int bufsize;
};
struct vidcap_type *
vidcap_quad_probe(void)
struct vidcap_type *vidcap_quad_probe(void)
{
printf("vidcap_quad_probe\n");
printf("vidcap_quad_probe\n");
struct vidcap_type* vt;
struct vidcap_type *vt;
/* CHECK IF QUAD CAN WARK CORRECTLY */
/* CHECK IF QUAD CAN WARK CORRECTLY */
/* END OF CHECK IF QUAD CAN WARK CORRECTLY */
/* END OF CHECK IF QUAD CAN WARK CORRECTLY */
vt = (struct vidcap_type *) malloc(sizeof(struct vidcap_type));
if (vt != NULL) {
vt->id = VIDCAP_QUAD_ID;
vt->name = "quad";
vt->description = "HD-SDI Maste Quad/i PCIe card";
vt->width = hd_size_x;
vt->height = hd_size_y;
vt->colour_mode = YUV_422;
}
return vt;
vt = (struct vidcap_type *)malloc(sizeof(struct vidcap_type));
if (vt != NULL) {
vt->id = VIDCAP_QUAD_ID;
vt->name = "quad";
vt->description = "HD-SDI Maste Quad/i PCIe card";
vt->width = hd_size_x;
vt->height = hd_size_y;
vt->colour_mode = YUV_422;
}
return vt;
}
void *
vidcap_quad_init(int fps)
void *vidcap_quad_init(int fps)
{
printf("vidcap_quad_init\n");
printf("vidcap_quad_init\n");
struct vidcap_quad_state *s;
struct vidcap_quad_state *s;
struct stat buf;
int num;
char str[BUFLEN], *endptr;
struct stat buf;
int num;
char str[BUFLEN], *endptr;
s = (struct vidcap_quad_state *) malloc(sizeof(struct vidcap_quad_state));
if(s == NULL) {
printf("Unable to allocate Quad state\n");
return NULL;
}
s = (struct vidcap_quad_state *)
malloc(sizeof(struct vidcap_quad_state));
if (s == NULL) {
printf("Unable to allocate Quad state\n");
return NULL;
}
/* Get the sysfs info */
memset (&buf, 0, sizeof (buf));
if(stat (device, &buf) < 0) {
fprintf (stderr, "%s: ", device);
perror ("unable to get the file status");
goto NO_STAT;
}
if(!S_ISCHR (buf.st_mode)) {
fprintf (stderr, "%s: not a character device\n", device);
goto NO_STAT;
}
if(!(buf.st_rdev & 0x0080)) {
fprintf (stderr, "%s: not a receiver\n", device);
goto NO_STAT;
}
/* Get the sysfs info */
memset(&buf, 0, sizeof(buf));
if (stat(device, &buf) < 0) {
fprintf(stderr, "%s: ", device);
perror("unable to get the file status");
goto NO_STAT;
}
if (!S_ISCHR(buf.st_mode)) {
fprintf(stderr, "%s: not a character device\n", device);
goto NO_STAT;
}
if (!(buf.st_rdev & 0x0080)) {
fprintf(stderr, "%s: not a receiver\n", device);
goto NO_STAT;
}
num = buf.st_rdev & 0x007f;
snprintf (s->name, sizeof (s->name), fmt, num, "dev");
num = buf.st_rdev & 0x007f;
snprintf(s->name, sizeof(s->name), fmt, num, "dev");
memset (str, 0, sizeof (str));
if(util_read (s->name, str, sizeof (str)) < 0) {
fprintf (stderr, "%s: ", device);
perror ("unable to get the device number");
goto NO_STAT;
}
if(strtoul (str, &endptr, 0) != (buf.st_rdev >> 8)) {
fprintf (stderr, "%s: not a SMPTE 259M-C device\n", device);
goto NO_STAT;
}
if(*endptr != ':') {
fprintf (stderr, "%s: error reading %s\n", device, s->name);
goto NO_STAT;
}
memset(str, 0, sizeof(str));
if (util_read(s->name, str, sizeof(str)) < 0) {
fprintf(stderr, "%s: ", device);
perror("unable to get the device number");
goto NO_STAT;
}
if (strtoul(str, &endptr, 0) != (buf.st_rdev >> 8)) {
fprintf(stderr, "%s: not a SMPTE 259M-C device\n", device);
goto NO_STAT;
}
if (*endptr != ':') {
fprintf(stderr, "%s: error reading %s\n", device, s->name);
goto NO_STAT;
}
/* Open the file */
if((fd = open (device, O_RDONLY)) < 0) {
fprintf (stderr, "%s: ", device);
perror ("unable to open file for reading");
goto NO_STAT;
}
/* Open the file */
if ((fd = open(device, O_RDONLY)) < 0) {
fprintf(stderr, "%s: ", device);
perror("unable to open file for reading");
goto NO_STAT;
}
/* Get the buffer size */
snprintf (s->name, sizeof (s->name), fmt, num, "bufsize");
if(util_strtoul (s->name, &(s->bufsize)) < 0) {
fprintf (stderr, "%s: ", device);
perror ("unable to get the receiver buffer size");
goto NO_BUFS;
}
/* Get the buffer size */
snprintf(s->name, sizeof(s->name), fmt, num, "bufsize");
if (util_strtoul(s->name, &(s->bufsize)) < 0) {
fprintf(stderr, "%s: ", device);
perror("unable to get the receiver buffer size");
goto NO_BUFS;
}
/* Allocate some memory */
if((s->data = (unsigned char *)malloc (s->bufsize)) == NULL) {
fprintf (stderr, "%s: ", device);
fprintf (stderr, "unable to allocate memory\n");
goto NO_BUFS;
}
/* Allocate some memory */
if ((s->data = (unsigned char *)malloc(s->bufsize)) == NULL) {
fprintf(stderr, "%s: ", device);
fprintf(stderr, "unable to allocate memory\n");
goto NO_BUFS;
}
/* SET SOME VARIABLES*/
pfd.fd = fd;
pfd.events = POLLIN | POLLPRI;
last_frames = 0;
last_timestamp = 0;
/* SET SOME VARIABLES */
pfd.fd = fd;
pfd.events = POLLIN | POLLPRI;
last_frames = 0;
last_timestamp = 0;
s->data = NULL;
s->data = NULL;
if(gettimeofday (&tv, NULL) < 0) {
fprintf (stderr, "%s: ", device);
perror ("unable to get time");
return NULL;
}
lasttime = tv.tv_sec + (double)tv.tv_usec / 1000000;
if (gettimeofday(&tv, NULL) < 0) {
fprintf(stderr, "%s: ", device);
perror("unable to get time");
return NULL;
}
lasttime = tv.tv_sec + (double)tv.tv_usec / 1000000;
return s;
return s;
NO_STAT:
return NULL;
NO_BUFS:
close(fd);
return NULL;
NO_STAT:
return NULL;
NO_BUFS:
close(fd);
return NULL;
}
void
vidcap_quad_done(void *state)
void vidcap_quad_done(void *state)
{
struct vidcap_quad_state *s = (struct vidcap_quad_state *) state;
struct vidcap_quad_state *s = (struct vidcap_quad_state *)state;
assert(s != NULL);
assert(s != NULL);
if(s!= NULL) {
free(s->data);
close(fd);
}
if (s != NULL) {
free(s->data);
close(fd);
}
}
struct video_frame *
vidcap_quad_grab(void *state)
struct video_frame *vidcap_quad_grab(void *state)
{
printf("vidcap_quad_grab\n");
printf("vidcap_quad_grab\n");
struct vidcap_quad_state *s = (struct vidcap_quad_state *) state;
struct video_frame *vf;
struct vidcap_quad_state *s = (struct vidcap_quad_state *)state;
struct video_frame *vf;
/* Receive the data and check for errors */
if(poll (&pfd, 1, 1000) < 0) {
fprintf (stderr, "%s: ", device);
perror ("unable to poll device file");
goto NO_RUN;
}
/* Receive the data and check for errors */
if(pfd.revents & POLLIN) {
if ((read_ret = read (fd, s->data, s->bufsize)) < 0) {
fprintf (stderr, "%s: ", device);
perror ("unable to read from device file");
goto NO_RUN;
}
bytes = 0;
if (poll(&pfd, 1, 1000) < 0) {
fprintf(stderr, "%s: ", device);
perror("unable to poll device file");
goto NO_RUN;
}
/* I DON'T NEED TO WRITE DATA SOMEWHERE, I WILL RETURN THEM THROUGH THIS FUNCTION*/
/*
while (bytes < read_ret) {
if ((ret = write (STDOUT_FILENO, s->data + bytes, read_ret - bytes)) < 0) {
fprintf (stderr, "%s: ", device);
perror ("unable to write to output");
goto NO_RUN;
}
bytes += ret;
}
*/
}
if (pfd.revents & POLLIN) {
if ((read_ret = read(fd, s->data, s->bufsize)) < 0) {
fprintf(stderr, "%s: ", device);
perror("unable to read from device file");
goto NO_RUN;
}
bytes = 0;
if(pfd.revents & POLLPRI) {
if (ioctl (fd, SDI_IOC_RXGETEVENTS, &val) < 0) {
fprintf (stderr, "%s: ", device);
perror ("unable to get receiver event flags");
goto NO_RUN;
}
if (val & SDI_EVENT_RX_BUFFER) {
fprinttime (stderr, "");
fprintf (stderr,
"driver receive buffer queue "
"overrun detected\n");
}
if (val & SDI_EVENT_RX_FIFO) {
fprinttime (stderr, "");
fprintf (stderr,
"onboard receive FIFO "
"overrun detected\n");
}
if (val & SDI_EVENT_RX_CARRIER) {
fprinttime (stderr, "");
fprintf (stderr,
"carrier status "
"change detected\n");
}
}
/* I DON'T NEED TO WRITE DATA SOMEWHERE, I WILL RETURN THEM THROUGH THIS FUNCTION */
/*
while (bytes < read_ret) {
if ((ret = write (STDOUT_FILENO, s->data + bytes, read_ret - bytes)) < 0) {
fprintf (stderr, "%s: ", device);
perror ("unable to write to output");
goto NO_RUN;
}
bytes += ret;
}
*/
}
gettimeofday (&tv, NULL);
time_sec = tv.tv_sec + (double)tv.tv_usec / 1000000;
dt = time_sec - lasttime;
/* Only for HD-SDI, display timestamp and counter */
if (pfd.revents & POLLPRI) {
if (ioctl(fd, SDI_IOC_RXGETEVENTS, &val) < 0) {
fprintf(stderr, "%s: ", device);
perror("unable to get receiver event flags");
goto NO_RUN;
}
if (val & SDI_EVENT_RX_BUFFER) {
fprinttime(stderr, "");
fprintf(stderr,
"driver receive buffer queue "
"overrun detected\n");
}
if (val & SDI_EVENT_RX_FIFO) {
fprinttime(stderr, "");
fprintf(stderr,
"onboard receive FIFO " "overrun detected\n");
}
if (val & SDI_EVENT_RX_CARRIER) {
fprinttime(stderr, "");
fprintf(stderr, "carrier status " "change detected\n");
}
}
if(dt >= 5) {
if(ioctl (fd, SDI_IOC_RXGET27COUNT, &frames) < 0) {
fprintf (stderr, "%s: ", device);
perror ("unable to get "
"the counter");
free (s->data);
close (fd);
return NULL;
}
gettimeofday(&tv, NULL);
time_sec = tv.tv_sec + (double)tv.tv_usec / 1000000;
dt = time_sec - lasttime;
if(ioctl (fd, SDI_IOC_RXGETTIMESTAMP, &timestamp) < 0) {
fprintf (stderr, "%s: ", device);
perror ("unable to get "
"the timestamp");
free (s->data);
close (fd);
return NULL;
}
/* Only for HD-SDI, display timestamp and counter */
float fps = (frames - last_frames) / (timestamp - last_timestamp);
fprintf(stderr, "%d frames in %g seconds = %g FPS\n", (frames - last_frames), (timestamp - last_timestamp), fps);
if (dt >= 5) {
if (ioctl(fd, SDI_IOC_RXGET27COUNT, &frames) < 0) {
fprintf(stderr, "%s: ", device);
perror("unable to get " "the counter");
free(s->data);
close(fd);
return NULL;
}
last_frames = frames;
last_timestamp = timestamp;
if (ioctl(fd, SDI_IOC_RXGETTIMESTAMP, &timestamp) < 0) {
fprintf(stderr, "%s: ", device);
perror("unable to get " "the timestamp");
free(s->data);
close(fd);
return NULL;
}
if(ioctl(fd, SDI_IOC_RXGETCARRIER, &val) < 0){
fprintf (stderr, "%s: ", device);
perror ("unable to get the carrier status");
}else if (val) {
fprintf (stderr, "Carrier detected, ");
}else {
fprintf (stderr, "No carrier, ");
}
float fps =
(frames - last_frames) / (timestamp - last_timestamp);
fprintf(stderr, "%d frames in %g seconds = %g FPS\n",
(frames - last_frames), (timestamp - last_timestamp),
fps);
if(ioctl (fd, SDI_IOC_RXGETSTATUS, &val) < 0) {
fprintf (stderr, "%s: ", device);
perror ("unable to get the receiver status");
}else {
fprintf (stderr, "Receiver is ");
if (val) {
//printf ("passing data.\n");
fprintf (stderr, "passing data\n");
}else {
//printf ("blocking data.\n");
fprintf (stderr, "blocking data\n");
}
}
lasttime = time_sec;
}
last_frames = frames;
last_timestamp = timestamp;
if(s->data != NULL) {
vf = (struct video_frame *) malloc(sizeof(struct video_frame));
if (vf != NULL) {
vf->colour_mode = YUV_422;
vf->width = hd_size_x;
vf->height = hd_size_y;
vf->data = (char*) s->data;
vf->data_len = s->bufsize;
//vf->data_len = hd_size_x * hd_size_y * hd_color_bpp;
}
if (ioctl(fd, SDI_IOC_RXGETCARRIER, &val) < 0) {
fprintf(stderr, "%s: ", device);
perror("unable to get the carrier status");
} else if (val) {
fprintf(stderr, "Carrier detected, ");
} else {
fprintf(stderr, "No carrier, ");
}
// testing write of frames into the files
/*
char gn[128];
memset(gn, 0, 128);
sprintf(gn, "_frames/frame%04d.yuv", s->delegate->get_framecount());
FILE *g=fopen(gn, "w+");
fwrite(vf->data, 1, vf->data_len, g);
fclose(g);
*/
if (ioctl(fd, SDI_IOC_RXGETSTATUS, &val) < 0) {
fprintf(stderr, "%s: ", device);
perror("unable to get the receiver status");
} else {
fprintf(stderr, "Receiver is ");
if (val) {
//printf ("passing data.\n");
fprintf(stderr, "passing data\n");
} else {
//printf ("blocking data.\n");
fprintf(stderr, "blocking data\n");
}
}
return vf;
}
lasttime = time_sec;
}
return NULL;
if (s->data != NULL) {
vf = (struct video_frame *)malloc(sizeof(struct video_frame));
if (vf != NULL) {
vf->colour_mode = YUV_422;
vf->width = hd_size_x;
vf->height = hd_size_y;
vf->data = (char *)s->data;
vf->data_len = s->bufsize;
//vf->data_len = hd_size_x * hd_size_y * hd_color_bpp;
}
// testing write of frames into the files
/*
char gn[128];
memset(gn, 0, 128);
sprintf(gn, "_frames/frame%04d.yuv", s->delegate->get_framecount());
FILE *g=fopen(gn, "w+");
fwrite(vf->data, 1, vf->data_len, g);
fclose(g);
*/
NO_RUN:
return NULL;
return vf;
}
return NULL;
NO_RUN:
return NULL;
}
#endif /* HAVE_QUAD */
#endif /* HAVE_MACOSX */
#endif /* HAVE_QUAD */
#endif /* HAVE_MACOSX */

View File

@@ -71,20 +71,20 @@
#define MAGIC_QT_GRABBER VIDCAP_QUICKTIME_ID
struct qt_grabber_state {
uint32_t magic;
SeqGrabComponent grabber;
SGChannel video_channel;
Rect bounds;
GWorldPtr gworld;
ImageSequence seqID;
int sg_idle_enough;
int major;
int minor;
int width;
int height;
int codec;
struct codec_info_t *c_info;
unsigned gui:1;
uint32_t magic;
SeqGrabComponent grabber;
SGChannel video_channel;
Rect bounds;
GWorldPtr gworld;
ImageSequence seqID;
int sg_idle_enough;
int major;
int minor;
int width;
int height;
int codec;
struct codec_info_t *c_info;
unsigned gui:1;
};
int frames = 0;
@@ -121,420 +121,418 @@ struct timeval t, t0;
static pascal OSErr
qt_data_proc(SGChannel c, Ptr p, long len, long *offset, long chRefCon,
TimeValue time, short writeType, long refCon)
TimeValue time, short writeType, long refCon)
{
struct qt_grabber_state *s = (struct qt_grabber_state *)refCon;
struct qt_grabber_state *s = (struct qt_grabber_state *)refCon;
UNUSED(c);
UNUSED(offset);
UNUSED(chRefCon);
UNUSED(time);
UNUSED(writeType);
UNUSED(c);
UNUSED(offset);
UNUSED(chRefCon);
UNUSED(time);
UNUSED(writeType);
if (s == NULL) {
debug_msg("corrupt state\n");
return -1;
}
if (s == NULL) {
debug_msg("corrupt state\n");
return -1;
}
memcpy(GetPixBaseAddr(GetGWorldPixMap(s->gworld)), p, len);
s->sg_idle_enough = 1;
memcpy(GetPixBaseAddr(GetGWorldPixMap(s->gworld)), p, len);
s->sg_idle_enough = 1;
frames++;
gettimeofday(&t, NULL);
double seconds = tv_diff(t, t0);
if (seconds >= 5) {
float fps = frames / seconds;
fprintf(stderr, "%d frames in %g seconds = %g FPS\n", frames,
seconds, fps);
t0 = t;
frames = 0;
}
frames++;
gettimeofday(&t, NULL);
double seconds = tv_diff(t, t0);
if (seconds >= 5) {
float fps = frames / seconds;
fprintf(stderr, "%d frames in %g seconds = %g FPS\n", frames,
seconds, fps);
t0 = t;
frames = 0;
}
return 0;
return 0;
}
static Boolean
SeqGrabberModalFilterProc(DialogPtr theDialog, const EventRecord * theEvent,
short *itemHit, long refCon)
short *itemHit, long refCon)
{
UNUSED(theDialog);
UNUSED(itemHit);
UNUSED(theDialog);
UNUSED(itemHit);
// Ordinarily, if we had multiple windows we cared about, we'd handle
// updating them in here, but since we don't, we'll just clear out
// any update events meant for us
// Ordinarily, if we had multiple windows we cared about, we'd handle
// updating them in here, but since we don't, we'll just clear out
// any update events meant for us
Boolean handled = false;
Boolean handled = false;
if ((theEvent->what == updateEvt) &&
((WindowPtr) theEvent->message == (WindowPtr) refCon)) {
BeginUpdate((WindowPtr) refCon);
EndUpdate((WindowPtr) refCon);
handled = true;
}
return (handled);
if ((theEvent->what == updateEvt) &&
((WindowPtr) theEvent->message == (WindowPtr) refCon)) {
BeginUpdate((WindowPtr) refCon);
EndUpdate((WindowPtr) refCon);
handled = true;
}
return (handled);
}
// SGSettingsDialog with the "Compression" panel removed
static OSErr MinimalSGSettingsDialog(SeqGrabComponent seqGrab, SGChannel sgchanVideo,
WindowPtr gMonitor)
static OSErr MinimalSGSettingsDialog(SeqGrabComponent seqGrab,
SGChannel sgchanVideo, WindowPtr gMonitor)
{
OSErr err;
Component *panelListPtr = NULL;
UInt8 numberOfPanels = 0;
OSErr err;
Component *panelListPtr = NULL;
UInt8 numberOfPanels = 0;
ComponentDescription cd = { SeqGrabPanelType, VideoMediaType, 0, 0, 0 };
Component c = 0;
Component *cPtr = NULL;
ComponentDescription cd = { SeqGrabPanelType, VideoMediaType, 0, 0, 0 };
Component c = 0;
Component *cPtr = NULL;
numberOfPanels = CountComponents(&cd);
panelListPtr =
(Component *) NewPtr(sizeof(Component) * (numberOfPanels + 1));
numberOfPanels = CountComponents(&cd);
panelListPtr =
(Component *) NewPtr(sizeof(Component) * (numberOfPanels + 1));
cPtr = panelListPtr;
numberOfPanels = 0;
CFStringRef compressionCFSTR = CFSTR("Compression");
do {
ComponentDescription compInfo;
c = FindNextComponent(c, &cd);
if (c) {
Handle hName = NewHandle(0);
GetComponentInfo(c, &compInfo, hName, NULL, NULL);
CFStringRef nameCFSTR =
CFStringCreateWithPascalString(kCFAllocatorDefault,
(unsigned char
*)(*hName),
kCFStringEncodingASCII);
if (CFStringCompare
(nameCFSTR, compressionCFSTR,
kCFCompareCaseInsensitive) != kCFCompareEqualTo) {
*cPtr++ = c;
numberOfPanels++;
}
DisposeHandle(hName);
}
} while (c);
cPtr = panelListPtr;
numberOfPanels = 0;
CFStringRef compressionCFSTR = CFSTR("Compression");
do {
ComponentDescription compInfo;
c = FindNextComponent(c, &cd);
if (c) {
Handle hName = NewHandle(0);
GetComponentInfo(c, &compInfo, hName, NULL, NULL);
CFStringRef nameCFSTR =
CFStringCreateWithPascalString(kCFAllocatorDefault,
(unsigned char
*)(*hName),
kCFStringEncodingASCII);
if (CFStringCompare
(nameCFSTR, compressionCFSTR,
kCFCompareCaseInsensitive) != kCFCompareEqualTo) {
*cPtr++ = c;
numberOfPanels++;
}
DisposeHandle(hName);
}
} while (c);
if ((err =
SGSettingsDialog(seqGrab, sgchanVideo, numberOfPanels,
panelListPtr, seqGrabSettingsPreviewOnly,
(SGModalFilterUPP)
NewSGModalFilterUPP(SeqGrabberModalFilterProc),
(long)gMonitor))) {
return err;
}
if ((err =
SGSettingsDialog(seqGrab, sgchanVideo, numberOfPanels,
panelListPtr, seqGrabSettingsPreviewOnly,
(SGModalFilterUPP)
NewSGModalFilterUPP(SeqGrabberModalFilterProc),
(long)gMonitor))) {
return err;
}
}
void nprintf(char *str)
{
char tmp[((int)str[0]) + 1];
char tmp[((int)str[0]) + 1];
strncpy(tmp, &str[1], str[0]);
tmp[(int)str[0]] = 0;
fprintf(stdout, "%s", tmp);
strncpy(tmp, &str[1], str[0]);
tmp[(int)str[0]] = 0;
fprintf(stdout, "%s", tmp);
}
/* Initialize the QuickTime grabber */
static int qt_open_grabber(struct qt_grabber_state *s, char *fmt)
{
GrafPtr savedPort;
WindowPtr gMonitor;
//SGModalFilterUPP seqGrabModalFilterUPP;
GrafPtr savedPort;
WindowPtr gMonitor;
//SGModalFilterUPP seqGrabModalFilterUPP;
assert(s != NULL);
assert(s->magic == MAGIC_QT_GRABBER);
assert(s != NULL);
assert(s->magic == MAGIC_QT_GRABBER);
/****************************************************************************************/
/* Step 0: Initialise the QuickTime movie toolbox. */
InitCursor();
EnterMovies();
/****************************************************************************************/
/* Step 0: Initialise the QuickTime movie toolbox. */
InitCursor();
EnterMovies();
/****************************************************************************************/
/* Step 1: Create an off-screen graphics world object, into which we can capture video. */
/* Lock it into position, to prevent QuickTime from messing with it while capturing. */
OSType pixelFormat;
pixelFormat = FOUR_CHAR_CODE('BGRA');
/****************************************************************************************/
/* Step 2: Open and initialise the default sequence grabber. */
s->grabber = OpenDefaultComponent(SeqGrabComponentType, 0);
if (s->grabber == 0) {
debug_msg("Unable to open grabber\n");
return 0;
}
/****************************************************************************************/
/* Step 1: Create an off-screen graphics world object, into which we can capture video. */
/* Lock it into position, to prevent QuickTime from messing with it while capturing. */
OSType pixelFormat;
pixelFormat = FOUR_CHAR_CODE('BGRA');
/****************************************************************************************/
/* Step 2: Open and initialise the default sequence grabber. */
s->grabber = OpenDefaultComponent(SeqGrabComponentType, 0);
if (s->grabber == 0) {
debug_msg("Unable to open grabber\n");
return 0;
}
gMonitor = GetDialogWindow(GetNewDialog(1000, NULL, (WindowPtr) - 1L));
gMonitor = GetDialogWindow(GetNewDialog(1000, NULL, (WindowPtr) - 1L));
GetPort(&savedPort);
SetPort(gMonitor);
GetPort(&savedPort);
SetPort(gMonitor);
if (SGInitialize(s->grabber) != noErr) {
debug_msg("Unable to init grabber\n");
return 0;
}
if (SGInitialize(s->grabber) != noErr) {
debug_msg("Unable to init grabber\n");
return 0;
}
SGSetGWorld(s->grabber, GetDialogPort(gMonitor), NULL);
SGSetGWorld(s->grabber, GetDialogPort(gMonitor), NULL);
/****************************************************************************************/
/* Specify the destination data reference for a record operation tell it */
/* we're not making a movie if the flag seqGrabDontMakeMovie is used, */
/* the sequence grabber still calls your data function, but does not */
/* write any data to the movie file writeType will always be set to */
/* seqGrabWriteAppend */
if (SGSetDataRef(s->grabber, 0, 0, seqGrabDontMakeMovie) != noErr) {
CloseComponent(s->grabber);
debug_msg("Unable to set data ref\n");
return 0;
}
/****************************************************************************************/
/* Specify the destination data reference for a record operation tell it */
/* we're not making a movie if the flag seqGrabDontMakeMovie is used, */
/* the sequence grabber still calls your data function, but does not */
/* write any data to the movie file writeType will always be set to */
/* seqGrabWriteAppend */
if (SGSetDataRef(s->grabber, 0, 0, seqGrabDontMakeMovie) != noErr) {
CloseComponent(s->grabber);
debug_msg("Unable to set data ref\n");
return 0;
}
if (SGSetGWorld(s->grabber, NULL, NULL) != noErr) {
debug_msg("Unable to get gworld from grabber\n");
return 0;
}
if (SGSetGWorld(s->grabber, NULL, NULL) != noErr) {
debug_msg("Unable to get gworld from grabber\n");
return 0;
}
if (SGNewChannel(s->grabber, VideoMediaType, &s->video_channel) !=
noErr) {
debug_msg("Unable to open video channel\n");
return 0;
}
if (SGNewChannel(s->grabber, VideoMediaType, &s->video_channel) !=
noErr) {
debug_msg("Unable to open video channel\n");
return 0;
}
/* Print available devices */
int i;
int j;
SGDeviceInputList inputList;
SGDeviceList deviceList;
if (strcmp(fmt, "help") == 0) {
if (SGGetChannelDeviceList
(s->video_channel, sgDeviceListIncludeInputs,
&deviceList) == noErr) {
fprintf(stdout, "Available capture devices:\n");
for (i = 0; i < (*deviceList)->count; i++) {
SGDeviceName *deviceEntry =
&(*deviceList)->entry[i];
fprintf(stdout, " Device %d: ", i);
nprintf((char *)(deviceEntry->name));
if (deviceEntry->
flags & sgDeviceNameFlagDeviceUnavailable) {
fprintf(stdout,
" - ### NOT AVAILABLE ###");
}
if (i == (*deviceList)->selectedIndex) {
fprintf(stdout, " - ### ACTIVE ###");
}
fprintf(stdout, "\n");
short activeInputIndex = 0;
inputList = deviceEntry->inputs;
if (inputList && (*inputList)->count >= 1) {
SGGetChannelDeviceAndInputNames(s->
video_channel,
NULL,
NULL,
&activeInputIndex);
for (j = 0; j < (*inputList)->count;
j++) {
fprintf(stdout, "\t");
fprintf(stdout, "- %d. ", j);
nprintf((char
*)((&(*inputList)->
entry[j].name)));
if ((i ==
(*deviceList)->
selectedIndex)
&& (j == activeInputIndex))
fprintf(stdout,
" - ### ACTIVE ###");
fprintf(stdout, "\n");
}
}
}
SGDisposeDeviceList(s->grabber, deviceList);
CodecNameSpecListPtr list;
GetCodecNameList(&list, 1);
printf("Compression types:\n");
for (i = 0; i < list->count; i++) {
int fcc = list->list[i].cType;
printf("\t%d) ", i);
nprintf((char *)list->list[i].typeName);
printf(" - FCC (%c%c%c%c)",
fcc >> 24,
(fcc >> 16) & 0xff,
(fcc >> 8) & 0xff, (fcc) & 0xff);
printf(" - codec id %x",
(unsigned int)(list->list[i].codec));
printf(" - cType %x",
(unsigned int)list->list[i].cType);
printf("\n");
}
}
return 0;
}
/* Print available devices */
int i;
int j;
SGDeviceInputList inputList;
SGDeviceList deviceList;
if (strcmp(fmt, "help") == 0) {
if (SGGetChannelDeviceList
(s->video_channel, sgDeviceListIncludeInputs,
&deviceList) == noErr) {
fprintf(stdout, "Available capture devices:\n");
for (i = 0; i < (*deviceList)->count; i++) {
SGDeviceName *deviceEntry =
&(*deviceList)->entry[i];
fprintf(stdout, " Device %d: ", i);
nprintf((char *)(deviceEntry->name));
if (deviceEntry->flags &
sgDeviceNameFlagDeviceUnavailable) {
fprintf(stdout,
" - ### NOT AVAILABLE ###");
}
if (i == (*deviceList)->selectedIndex) {
fprintf(stdout, " - ### ACTIVE ###");
}
fprintf(stdout, "\n");
short activeInputIndex = 0;
inputList = deviceEntry->inputs;
if (inputList && (*inputList)->count >= 1) {
SGGetChannelDeviceAndInputNames
(s->video_channel, NULL, NULL,
&activeInputIndex);
for (j = 0; j < (*inputList)->count;
j++) {
fprintf(stdout, "\t");
fprintf(stdout, "- %d. ", j);
nprintf((char
*)((&
(*inputList)->entry
[j].name)));
if ((i ==
(*deviceList)->selectedIndex)
&& (j == activeInputIndex))
fprintf(stdout,
" - ### ACTIVE ###");
fprintf(stdout, "\n");
}
}
}
SGDisposeDeviceList(s->grabber, deviceList);
CodecNameSpecListPtr list;
GetCodecNameList(&list, 1);
printf("Compression types:\n");
for (i = 0; i < list->count; i++) {
int fcc = list->list[i].cType;
printf("\t%d) ", i);
nprintf((char *)list->list[i].typeName);
printf(" - FCC (%c%c%c%c)",
fcc >> 24,
(fcc >> 16) & 0xff,
(fcc >> 8) & 0xff, (fcc) & 0xff);
printf(" - codec id %x",
(unsigned int)(list->list[i].codec));
printf(" - cType %x",
(unsigned int)list->list[i].cType);
printf("\n");
}
}
return 0;
}
if (SGSetChannelUsage
(s->video_channel,
seqGrabRecord | seqGrabPreview | seqGrabAlwaysUseTimeBase |
seqGrabLowLatencyCapture) != noErr) {
debug_msg("Unable to set channel usage\n");
return 0;
}
if (SGSetChannelUsage
(s->video_channel,
seqGrabRecord | seqGrabPreview | seqGrabAlwaysUseTimeBase |
seqGrabLowLatencyCapture) != noErr) {
debug_msg("Unable to set channel usage\n");
return 0;
}
if (SGSetChannelPlayFlags(s->video_channel, channelPlayAllData) !=
noErr) {
debug_msg("Unable to set channel flags\n");
return 0;
}
if (SGSetChannelPlayFlags(s->video_channel, channelPlayAllData) !=
noErr) {
debug_msg("Unable to set channel flags\n");
return 0;
}
SGStartPreview(s->grabber);
SGStartPreview(s->grabber);
/* Select the device */
if (strcmp(fmt, "gui") == 0) { //Use gui to select input
MinimalSGSettingsDialog(s->grabber, s->video_channel, gMonitor);
} else { // Use input specified on cmd
if (SGGetChannelDeviceList
(s->video_channel, sgDeviceListIncludeInputs,
&deviceList) != noErr) {
debug_msg("Unable to get list of quicktime devices\n");
return 0;
}
/* Select the device */
if (strcmp(fmt, "gui") == 0) { //Use gui to select input
MinimalSGSettingsDialog(s->grabber, s->video_channel, gMonitor);
} else { // Use input specified on cmd
if (SGGetChannelDeviceList
(s->video_channel, sgDeviceListIncludeInputs,
&deviceList) != noErr) {
debug_msg("Unable to get list of quicktime devices\n");
return 0;
}
char *tmp;
char *tmp;
tmp = strtok(fmt, ":");
if (!tmp) {
fprintf(stderr, "Wrong config %s\n", fmt);
return 0;
}
s->major = atoi(tmp);
tmp = strtok(NULL, ":");
if (!tmp) {
fprintf(stderr, "Wrong config %s\n", fmt);
return 0;
}
s->minor = atoi(tmp);
tmp = strtok(NULL, ":");
if (!tmp) {
fprintf(stderr, "Wrong config %s\n", fmt);
return 0;
}
s->codec = atoi(tmp);
tmp = strtok(fmt, ":");
if (!tmp) {
fprintf(stderr, "Wrong config %s\n", fmt);
return 0;
}
s->major = atoi(tmp);
tmp = strtok(NULL, ":");
if (!tmp) {
fprintf(stderr, "Wrong config %s\n", fmt);
return 0;
}
s->minor = atoi(tmp);
tmp = strtok(NULL, ":");
if (!tmp) {
fprintf(stderr, "Wrong config %s\n", fmt);
return 0;
}
s->codec = atoi(tmp);
SGDeviceName *deviceEntry = &(*deviceList)->entry[s->major];
printf("Quicktime: Setting device: ");
nprintf((char *)deviceEntry->name);
printf("\n");
if (SGSetChannelDevice(s->video_channel, deviceEntry->name) !=
noErr) {
debug_msg("Setting up the selected device failed\n");
return 0;
}
SGDeviceName *deviceEntry = &(*deviceList)->entry[s->major];
printf("Quicktime: Setting device: ");
nprintf((char *)deviceEntry->name);
printf("\n");
if (SGSetChannelDevice(s->video_channel, deviceEntry->name) !=
noErr) {
debug_msg("Setting up the selected device failed\n");
return 0;
}
/* Select input */
inputList = deviceEntry->inputs;
printf("Quicktime: Setting input: ");
nprintf((char *)(&(*inputList)->entry[s->minor].name));
printf("\n");
if (SGSetChannelDeviceInput(s->video_channel, s->minor) !=
noErr) {
debug_msg
("Setting up input on selected device failed\n");
return 0;
}
}
/* Select input */
inputList = deviceEntry->inputs;
printf("Quicktime: Setting input: ");
nprintf((char *)(&(*inputList)->entry[s->minor].name));
printf("\n");
if (SGSetChannelDeviceInput(s->video_channel, s->minor) !=
noErr) {
debug_msg
("Setting up input on selected device failed\n");
return 0;
}
}
/* Set video size according to selected video format */
Rect gActiveVideoRect;
SGGetSrcVideoBounds(s->video_channel, &gActiveVideoRect);
/* Set video size according to selected video format */
Rect gActiveVideoRect;
SGGetSrcVideoBounds(s->video_channel, &gActiveVideoRect);
hd_size_x = s->bounds.right =
gActiveVideoRect.right - gActiveVideoRect.left;
hd_size_y = s->bounds.bottom =
gActiveVideoRect.bottom - gActiveVideoRect.top;
hd_size_x = s->bounds.right =
gActiveVideoRect.right - gActiveVideoRect.left;
hd_size_y = s->bounds.bottom =
gActiveVideoRect.bottom - gActiveVideoRect.top;
printf("Quicktime: Video size: %dx%d\n", s->bounds.right,
s->bounds.bottom);
printf("Quicktime: Video size: %dx%d\n", s->bounds.right,
s->bounds.bottom);
if (SGSetChannelBounds(s->video_channel, &(s->bounds)) != noErr) {
debug_msg("Unable to set channel bounds\n");
return 0;
}
if (SGSetChannelBounds(s->video_channel, &(s->bounds)) != noErr) {
debug_msg("Unable to set channel bounds\n");
return 0;
}
/* Set selected fmt->codec and get pixel format of that codec */
int pixfmt;
if (s->codec > 0) {
CodecNameSpecListPtr list;
GetCodecNameList(&list, 1);
pixfmt = list->list[s->codec].cType;
printf("Quicktime: SetCompression: %d\n",
(int)SGSetVideoCompressor(s->video_channel, 0,
list->list[s->codec].codec, 0,
0, 0));
} else {
int codec;
SGGetVideoCompressor(s->video_channel, NULL, &codec, NULL, NULL,
NULL);
CodecNameSpecListPtr list;
GetCodecNameList(&list, 1);
for (i = 0; i < list->count; i++) {
if ((unsigned)codec == list->list[i].codec) {
pixfmt = list->list[i].cType;
break;
}
}
}
/* Set selected fmt->codec and get pixel format of that codec */
int pixfmt;
if (s->codec > 0) {
CodecNameSpecListPtr list;
GetCodecNameList(&list, 1);
pixfmt = list->list[s->codec].cType;
printf("Quicktime: SetCompression: %d\n",
(int)SGSetVideoCompressor(s->video_channel, 0,
list->list[s->codec].codec, 0,
0, 0));
} else {
int codec;
SGGetVideoCompressor(s->video_channel, NULL, &codec, NULL, NULL,
NULL);
CodecNameSpecListPtr list;
GetCodecNameList(&list, 1);
for (i = 0; i < list->count; i++) {
if ((unsigned)codec == list->list[i].codec) {
pixfmt = list->list[i].cType;
break;
}
}
}
for (i = 0; codec_info[i].name != NULL; i++) {
if ((unsigned)pixfmt == codec_info[i].fcc) {
s->c_info = &codec_info[i];
}
}
for (i = 0; codec_info[i].name != NULL; i++) {
if ((unsigned)pixfmt == codec_info[i].fcc) {
s->c_info = &codec_info[i];
}
}
printf("Quicktime: Selected pixel format: %c%c%c%c\n",
pixfmt >> 24, (pixfmt >> 16) & 0xff, (pixfmt >> 8) & 0xff,
(pixfmt) & 0xff);
printf("Quicktime: Selected pixel format: %c%c%c%c\n",
pixfmt >> 24, (pixfmt >> 16) & 0xff, (pixfmt >> 8) & 0xff,
(pixfmt) & 0xff);
hd_color_spc = s->codec;
hd_color_spc = s->codec;
int h_align = s->c_info->h_align;
if (h_align) {
hd_size_x = ((hd_size_x + h_align - 1) / h_align) * h_align;
printf
("Quicktime: Pixel format 'v210' was selected -> Setting hd_size_x to %d\n",
hd_size_x);
}
int h_align = s->c_info->h_align;
if (h_align) {
hd_size_x = ((hd_size_x + h_align - 1) / h_align) * h_align;
printf
("Quicktime: Pixel format 'v210' was selected -> Setting hd_size_x to %d\n",
hd_size_x);
}
SetPort(savedPort);
SetPort(savedPort);
if (QTNewGWorld(&(s->gworld), pixelFormat, &(s->bounds), 0, NULL, 0) !=
noErr) {
debug_msg("Unable to create GWorld\n");
return 0;
}
if (QTNewGWorld(&(s->gworld), pixelFormat, &(s->bounds), 0, NULL, 0) !=
noErr) {
debug_msg("Unable to create GWorld\n");
return 0;
}
if (!LockPixels(GetPortPixMap(s->gworld))) {
debug_msg("Unable to lock pixels\n");
return 0;
}
if (!LockPixels(GetPortPixMap(s->gworld))) {
debug_msg("Unable to lock pixels\n");
return 0;
}
/*if (SGSetGWorld(s->grabber, s->gworld, GetMainDevice()) != noErr) {
debug_msg("Unable to set graphics world\n");
return 0;
} */
/*if (SGSetGWorld(s->grabber, s->gworld, GetMainDevice()) != noErr) {
debug_msg("Unable to set graphics world\n");
return 0;
} */
/****************************************************************************************/
/* Step ?: Set the data procedure, which processes the frames as they're captured. */
SGSetDataProc(s->grabber, NewSGDataUPP(qt_data_proc), (long)s);
/****************************************************************************************/
/* Step ?: Set the data procedure, which processes the frames as they're captured. */
SGSetDataProc(s->grabber, NewSGDataUPP(qt_data_proc), (long)s);
/****************************************************************************************/
/* Step ?: Start capturing video... */
if (SGPrepare(s->grabber, FALSE, TRUE) != noErr) {
debug_msg("Unable to prepare capture\n");
return 0;
}
/****************************************************************************************/
/* Step ?: Start capturing video... */
if (SGPrepare(s->grabber, FALSE, TRUE) != noErr) {
debug_msg("Unable to prepare capture\n");
return 0;
}
if (SGStartRecord(s->grabber) != noErr) {
debug_msg("Unable to start recording\n");
return 0;
}
if (SGStartRecord(s->grabber) != noErr) {
debug_msg("Unable to start recording\n");
return 0;
}
return 1;
return 1;
}
/*******************************************************************************
@@ -542,94 +540,94 @@ static int qt_open_grabber(struct qt_grabber_state *s, char *fmt)
******************************************************************************/
struct vidcap_type *vidcap_quicktime_probe(void)
{
struct vidcap_type *vt;
struct vidcap_type *vt;
vt = (struct vidcap_type *)malloc(sizeof(struct vidcap_type));
if (vt != NULL) {
vt->id = VIDCAP_QUICKTIME_ID;
vt->name = "quicktime";
vt->description = "QuickTime capture device";
vt->width = hd_size_x;
vt->height = hd_size_y;
}
vt = (struct vidcap_type *)malloc(sizeof(struct vidcap_type));
if (vt != NULL) {
vt->id = VIDCAP_QUICKTIME_ID;
vt->name = "quicktime";
vt->description = "QuickTime capture device";
vt->width = hd_size_x;
vt->height = hd_size_y;
}
return vt;
return vt;
}
/* Initialize the QuickTime grabbing system */
void *vidcap_quicktime_init(char *fmt)
{
struct qt_grabber_state *s;
struct qt_grabber_state *s;
s = (struct qt_grabber_state *)malloc(sizeof(struct qt_grabber_state));
if (s != NULL) {
s->magic = MAGIC_QT_GRABBER;
s->grabber = 0;
s->video_channel = 0;
s->seqID = 0;
s->bounds.top = 0;
s->bounds.left = 0;
s->bounds.bottom = hd_size_y;
s->bounds.right = hd_size_x;
s->sg_idle_enough = 0;
s = (struct qt_grabber_state *)malloc(sizeof(struct qt_grabber_state));
if (s != NULL) {
s->magic = MAGIC_QT_GRABBER;
s->grabber = 0;
s->video_channel = 0;
s->seqID = 0;
s->bounds.top = 0;
s->bounds.left = 0;
s->bounds.bottom = hd_size_y;
s->bounds.right = hd_size_x;
s->sg_idle_enough = 0;
if (qt_open_grabber(s, fmt) == 0) {
free(s);
return NULL;
}
}
if (qt_open_grabber(s, fmt) == 0) {
free(s);
return NULL;
}
}
return s;
return s;
}
/* Finalize the grabbing system */
void vidcap_quicktime_done(void *state)
{
struct qt_grabber_state *s = (struct qt_grabber_state *)state;
struct qt_grabber_state *s = (struct qt_grabber_state *)state;
assert(s != NULL);
assert(s != NULL);
if (s != NULL) {
assert(s->magic != MAGIC_QT_GRABBER);
SGStop(s->grabber);
UnlockPixels(GetPortPixMap(s->gworld));
CloseComponent(s->grabber);
DisposeGWorld(s->gworld);
ExitMovies();
free(s);
}
if (s != NULL) {
assert(s->magic != MAGIC_QT_GRABBER);
SGStop(s->grabber);
UnlockPixels(GetPortPixMap(s->gworld));
CloseComponent(s->grabber);
DisposeGWorld(s->gworld);
ExitMovies();
free(s);
}
}
/* Grab a frame */
struct video_frame *vidcap_quicktime_grab(void *state)
{
struct qt_grabber_state *s = (struct qt_grabber_state *)state;
struct video_frame *vf;
struct qt_grabber_state *s = (struct qt_grabber_state *)state;
struct video_frame *vf;
assert(s != NULL);
assert(s->magic == MAGIC_QT_GRABBER);
assert(s != NULL);
assert(s->magic == MAGIC_QT_GRABBER);
/* Run the QuickTime sequence grabber idle function, which provides */
/* processor time to out data proc running as a callback. */
/* Run the QuickTime sequence grabber idle function, which provides */
/* processor time to out data proc running as a callback. */
/* The while loop done in this way is also sort of nice bussy waiting */
/* and synchronizes capturing and sending. */
s->sg_idle_enough = 0;
while (!s->sg_idle_enough) {
if (SGIdle(s->grabber) != noErr) {
debug_msg("Error in SGIDle\n");
return NULL;
}
}
/* The while loop done in this way is also sort of nice bussy waiting */
/* and synchronizes capturing and sending. */
s->sg_idle_enough = 0;
while (!s->sg_idle_enough) {
if (SGIdle(s->grabber) != noErr) {
debug_msg("Error in SGIDle\n");
return NULL;
}
}
vf = malloc(sizeof(struct video_frame));
if (vf != NULL) {
vf->width = hd_size_x;
vf->height = hd_size_y;
vf->data = (char *)GetPixBaseAddr(GetGWorldPixMap(s->gworld));
vf->data_len = hd_size_x * hd_size_y * s->c_info->bpp;
}
return vf;
vf = malloc(sizeof(struct video_frame));
if (vf != NULL) {
vf->width = hd_size_x;
vf->height = hd_size_y;
vf->data = (char *)GetPixBaseAddr(GetGWorldPixMap(s->gworld));
vf->data_len = hd_size_x * hd_size_y * s->c_info->bpp;
}
return vf;
}
#endif /* HAVE_MACOSX */
#endif /* HAVE_MACOSX */

View File

@@ -68,65 +68,66 @@
#include <SDL/SDL.h>
void rgb2yuv422(unsigned char *in, unsigned int width, unsigned int height);
unsigned char * tov210(unsigned char *in, unsigned int width, unsigned int height, double bpp);
unsigned char *tov210(unsigned char *in, unsigned int width,
unsigned int height, double bpp);
void toR10k(unsigned char *in, unsigned int width, unsigned int height);
struct testcard_state {
struct timeval last_frame_time;
int fps;
int count;
unsigned int width;
unsigned int height;
int size;
char *frame;
int linesize;
int pan;
SDL_Surface *surface;
struct timeval t0;
struct timeval last_frame_time;
int fps;
int count;
unsigned int width;
unsigned int height;
int size;
char *frame;
int linesize;
int pan;
SDL_Surface *surface;
struct timeval t0;
};
const int rect_colors[] = {
0xff0000ff,
0xff00ff00,
0xffff0000,
0xff00ffff,
0xffffff00,
0xffff00ff };
0xff0000ff,
0xff00ff00,
0xffff0000,
0xff00ffff,
0xffffff00,
0xffff00ff
};
#define COL_NUM 6
void
rgb2yuv422(unsigned char *in, unsigned int width, unsigned int height)
void rgb2yuv422(unsigned char *in, unsigned int width, unsigned int height)
{
unsigned int i,j;
int r,g,b;
int y,u,v,y1,u1,v1;
unsigned int i, j;
int r, g, b;
int y, u, v, y1, u1, v1;
unsigned char *dst;
dst = in;
for(j = 0; j < height; j++) {
for(i = 0; i < width; i+=2) {
for (j = 0; j < height; j++) {
for (i = 0; i < width; i += 2) {
r = *(in++);
g = *(in++);
b = *(in++);
in++; /*skip alpha*/
in++; /*skip alpha */
y = r * 0.299 + g * 0.587 + b * 0.114;
u = b * 0.5 - r * 0.168736 - g * 0.331264;
v = r * 0.5 - g * 0.418688 -b * 0.081312;
v = r * 0.5 - g * 0.418688 - b * 0.081312;
//y -= 16;
if(y > 255)
if (y > 255)
y = 255;
if(y < 0)
if (y < 0)
y = 0;
if(u < -128)
if (u < -128)
u = -128;
if(u > 127)
if (u > 127)
u = 127;
if(v < -128)
if (v < -128)
v = -128;
if(v > 127)
if (v > 127)
v = 127;
u += 128;
v += 128;
@@ -134,58 +135,58 @@ rgb2yuv422(unsigned char *in, unsigned int width, unsigned int height)
r = *(in++);
g = *(in++);
b = *(in++);
in++; /*skip alpha*/
in++; /*skip alpha */
y1 = r * 0.299 + g * 0.587 + b * 0.114;
u1 = b * 0.5 - r * 0.168736 - g * 0.331264;
v1 = r * 0.5 - g * 0.418688 -b * 0.081312;
if(y1 > 255)
v1 = r * 0.5 - g * 0.418688 - b * 0.081312;
if (y1 > 255)
y1 = 255;
if(y1 < 0)
if (y1 < 0)
y1 = 0;
if(u1 < -128)
if (u1 < -128)
u1 = -128;
if(u1 > 127)
if (u1 > 127)
u1 = 127;
if(v1 < -128)
if (v1 < -128)
v1 = -128;
if(v1 > 127)
if (v1 > 127)
v1 = 127;
u1 += 128;
v1 += 128;
*(dst++) = (u + u1)/2;
*(dst++) = (u + u1) / 2;
*(dst++) = y;
*(dst++) = (v + v1)/2;
*(dst++) = (v + v1) / 2;
*(dst++) = y1;
}
}
}
unsigned char *
tov210(unsigned char *in, unsigned int width, unsigned int aligned_x, unsigned int height, double bpp)
unsigned char *tov210(unsigned char *in, unsigned int width,
unsigned int aligned_x, unsigned int height, double bpp)
{
struct {
unsigned a:10;
unsigned b:10;
unsigned c:10;
unsigned p1:2;
unsigned a:10;
unsigned b:10;
unsigned c:10;
unsigned p1:2;
} *p;
unsigned int i,j;
unsigned int i, j;
unsigned int linesize = aligned_x * bpp;
unsigned char *dst = (unsigned char*)malloc(aligned_x*height*bpp);
unsigned char *dst = (unsigned char *)malloc(aligned_x * height * bpp);
unsigned char *src;
unsigned char *ret = dst;
for(j=0; j < height; j++) {
p = (void*)dst;
for (j = 0; j < height; j++) {
p = (void *)dst;
dst += linesize;
src = in;
in += width*2;
for(i=0; i < width; i+=3) {
unsigned int u,y,v;
in += width * 2;
for (i = 0; i < width; i += 3) {
unsigned int u, y, v;
u = *(src++);
y = *(src++);
@@ -195,7 +196,7 @@ tov210(unsigned char *in, unsigned int width, unsigned int aligned_x, unsigned i
p->b = y << 2;
p->c = v << 2;
p->p1 = 0;
p++;
u = *(src++);
@@ -213,32 +214,31 @@ tov210(unsigned char *in, unsigned int width, unsigned int aligned_x, unsigned i
return ret;
}
void
toR10k(unsigned char *in, unsigned int width, unsigned int height)
void toR10k(unsigned char *in, unsigned int width, unsigned int height)
{
struct {
unsigned r:8;
unsigned r:8;
unsigned gh:6;
unsigned p1:2;
unsigned gh:6;
unsigned p1:2;
unsigned bh:4;
unsigned p2:2;
unsigned gl:2;
unsigned bh:4;
unsigned p2:2;
unsigned gl:2;
unsigned p3:2;
unsigned p4:2;
unsigned bl:4;
unsigned p3:2;
unsigned p4:2;
unsigned bl:4;
} *d;
unsigned int i,j;
d = (void*)in;
unsigned int i, j;
d = (void *)in;
for (j = 0; j < height; j++) {
for (i = 0; i < width; i++) {
unsigned int r, g, b;
for(j = 0; j < height; j++) {
for(i = 0; i < width; i++) {
unsigned int r,g,b;
r = *(in++);
g = *(in++);
b = *(in++);
@@ -256,24 +256,22 @@ toR10k(unsigned char *in, unsigned int width, unsigned int height)
d->p4 = 0;
d++;
}
}
}
}
void *
vidcap_testcard_init(char *fmt)
void *vidcap_testcard_init(char *fmt)
{
struct testcard_state *s;
char *filename;
FILE *in;
struct stat sb;
unsigned int i,j;
unsigned int rect_size=COL_NUM;
codec_t codec;
int aligned_x;
struct testcard_state *s;
char *filename;
FILE *in;
struct stat sb;
unsigned int i, j;
unsigned int rect_size = COL_NUM;
codec_t codec;
int aligned_x;
if(strcmp(fmt, "help")==0) {
if (strcmp(fmt, "help") == 0) {
printf("testcard options:\n");
printf("\twidth:height:fps:codec[:filename][:p}\n");
printf("\tp - pan with frame\n");
@@ -282,48 +280,48 @@ vidcap_testcard_init(char *fmt)
}
s = malloc(sizeof(struct testcard_state));
if(!s)
if (!s)
return NULL;
char *tmp;
tmp = strtok(fmt, ":");
if(!tmp) {
if (!tmp) {
fprintf(stderr, "Wrong format for testcard '%s'\n", fmt);
free(s);
return NULL;
}
s->width = atoi(tmp);
tmp = strtok(NULL, ":");
if(!tmp) {
if (!tmp) {
fprintf(stderr, "Wrong format for testcard '%s'\n", fmt);
free(s);
return NULL;
}
s->height = atoi(tmp);
tmp = strtok(NULL, ":");
if(!tmp) {
if (!tmp) {
free(s->frame);
free(s);
fprintf(stderr, "Wrong format for testcard '%s'\n", fmt);
return NULL;
}
s->fps = atoi(tmp);
s->fps = atoi(tmp);
tmp=strtok(NULL, ":");
if(!tmp) {
tmp = strtok(NULL, ":");
if (!tmp) {
free(s->frame);
free(s);
fprintf(stderr, "Wrong format for testcard '%s'\n", fmt);
return NULL;
}
int h_align=0;
double bpp=0;
int h_align = 0;
double bpp = 0;
for(i = 0; codec_info[i].name != NULL; i++) {
if(strcmp(tmp, codec_info[i].name) == 0) {
for (i = 0; codec_info[i].name != NULL; i++) {
if (strcmp(tmp, codec_info[i].name) == 0) {
h_align = codec_info[i].h_align;
bpp = codec_info[i].bpp;
codec = codec_info[i].codec;
@@ -331,22 +329,21 @@ vidcap_testcard_init(char *fmt)
}
}
aligned_x = s->width;
if(h_align) {
aligned_x = (aligned_x + h_align - 1)/h_align*h_align;
if (h_align) {
aligned_x = (aligned_x + h_align - 1) / h_align * h_align;
}
rect_size = (s->width + rect_size-1) / rect_size;
rect_size = (s->width + rect_size - 1) / rect_size;
s->linesize = aligned_x * bpp;
s->size = aligned_x*s->height*bpp;
s->size = aligned_x * s->height * bpp;
filename = strtok(NULL, ":");
if(filename && strcmp(filename, "p") != 0) {
if (filename && strcmp(filename, "p") != 0) {
s->frame = malloc(s->size);
if(stat(filename, &sb)) {
if (stat(filename, &sb)) {
perror("stat");
free(s);
return NULL;
@@ -354,17 +351,16 @@ vidcap_testcard_init(char *fmt)
in = fopen(filename, "r");
if(s->size < sb.st_size) {
if (s->size < sb.st_size) {
fprintf(stderr, "Error wrong file size for selected "
"resolution and codec. File size %d, "
"computed size %d\n",
(int)sb.st_size, s->size);
"resolution and codec. File size %d, "
"computed size %d\n", (int)sb.st_size, s->size);
free(s->frame);
free(s);
return NULL;
}
if(!in || fread(s->frame, sb.st_size, 1, in) == 0) {
if (!in || fread(s->frame, sb.st_size, 1, in) == 0) {
fprintf(stderr, "Cannot read file %s\n", filename);
free(s->frame);
free(s);
@@ -374,58 +370,64 @@ vidcap_testcard_init(char *fmt)
fclose(in);
} else {
SDL_Rect r;
int col_num=0;
s->surface = SDL_CreateRGBSurface(SDL_SWSURFACE, aligned_x, s->height,
32, 0xff, 0xff00, 0xff0000, 0xff000000);
if(filename && filename[0] == 'p') {
int col_num = 0;
s->surface =
SDL_CreateRGBSurface(SDL_SWSURFACE, aligned_x, s->height,
32, 0xff, 0xff00, 0xff0000,
0xff000000);
if (filename && filename[0] == 'p') {
s->pan = 48;
}
for(j=0; j < s->height; j+=rect_size) {
int grey=0xff010101;
if(j==rect_size*2) {
r.w= s->width;
r.h = rect_size/4;
for (j = 0; j < s->height; j += rect_size) {
int grey = 0xff010101;
if (j == rect_size * 2) {
r.w = s->width;
r.h = rect_size / 4;
r.x = 0;
r.y = j;
SDL_FillRect(s->surface, &r, 0xffffffff);
r.y = j+rect_size*3/4;
r.y = j + rect_size * 3 / 4;
SDL_FillRect(s->surface, &r, 0);
}
for(i=0; i < s->width; i+=rect_size) {
for (i = 0; i < s->width; i += rect_size) {
r.w = rect_size;
r.h = rect_size;
r.x = i;
r.y = j;
printf("Fill rect at %d,%d\n", r.x, r.y );
if(j!=rect_size*2) {
SDL_FillRect(s->surface, &r, rect_colors[col_num]);
col_num = (col_num+1)%COL_NUM;
printf("Fill rect at %d,%d\n", r.x, r.y);
if (j != rect_size * 2) {
SDL_FillRect(s->surface, &r,
rect_colors[col_num]);
col_num = (col_num + 1) % COL_NUM;
} else {
r.h = rect_size/2;
r.y += rect_size/4;
SDL_FillRect(s->surface, &r, grey);
grey += 0x00010101*(255/COL_NUM);
r.h = rect_size / 2;
r.y += rect_size / 4;
SDL_FillRect(s->surface, &r, grey);
grey += 0x00010101 * (255 / COL_NUM);
}
}
}
s->frame = s->surface->pixels;
if(codec == UYVY || codec == v210 || codec == Vuy2) {
rgb2yuv422((unsigned char*)s->frame, s->width, s->height);
}
if(codec == v210) {
s->frame = (char*)tov210((unsigned char*)s->frame, s->width, aligned_x, s->height, bpp);
s->frame = s->surface->pixels;
if (codec == UYVY || codec == v210 || codec == Vuy2) {
rgb2yuv422((unsigned char *)s->frame, s->width,
s->height);
}
if(codec == R10k) {
toR10k((unsigned char*)s->frame, s->width, s->height);
if (codec == v210) {
s->frame =
(char *)tov210((unsigned char *)s->frame, s->width,
aligned_x, s->height, bpp);
}
if (codec == R10k) {
toR10k((unsigned char *)s->frame, s->width, s->height);
}
}
tmp = strtok(NULL, ":");
if(tmp) {
if(tmp[0] == 'p') {
if (tmp) {
if (tmp[0] == 'p') {
s->pan = 48;
}
}
@@ -438,80 +440,83 @@ vidcap_testcard_init(char *fmt)
return s;
}
void
vidcap_testcard_done(void *state)
void vidcap_testcard_done(void *state)
{
struct testcard_state *s = state;
if(s->frame != s->surface->pixels)
if (s->frame != s->surface->pixels)
free(s->frame);
if(s->surface)
if (s->surface)
SDL_FreeSurface(s->surface);
free(s);
}
struct video_frame *
vidcap_testcard_grab(void *arg)
struct video_frame *vidcap_testcard_grab(void *arg)
{
struct timeval curr_time;
struct testcard_state *state;
struct video_frame *vf;
struct timeval curr_time;
struct testcard_state *state;
struct video_frame *vf;
state = (struct testcard_state *) arg;
state = (struct testcard_state *)arg;
gettimeofday(&curr_time, NULL);
if (tv_diff(curr_time, state->last_frame_time) > 1.0/(double)state->fps) {
if (tv_diff(curr_time, state->last_frame_time) >
1.0 / (double)state->fps) {
state->last_frame_time = curr_time;
state->count++;
double seconds = tv_diff(curr_time, state->t0);
double seconds = tv_diff(curr_time, state->t0);
if (seconds >= 5) {
float fps = state->count / seconds;
fprintf(stderr, "%d frames in %g seconds = %g FPS\n", state->count, seconds, fps);
float fps = state->count / seconds;
fprintf(stderr, "%d frames in %g seconds = %g FPS\n",
state->count, seconds, fps);
state->t0 = curr_time;
state->count = 0;
}
vf = (struct video_frame *) malloc(sizeof(struct video_frame));
vf = (struct video_frame *)malloc(sizeof(struct video_frame));
if (vf != NULL) {
char line[state->linesize*2+state->pan];
unsigned int i;
vf->width = state->width;
vf->height = state->height;
vf->data = state->frame;
vf->data_len = state->size;
memcpy(line, state->frame, state->linesize*2+state->pan);
for(i=0; i < hd_size_y-3; i++) {
memcpy(state->frame+i*state->linesize,
state->frame+(i+2)*state->linesize+state->pan, state->linesize);
char line[state->linesize * 2 + state->pan];
unsigned int i;
vf->width = state->width;
vf->height = state->height;
vf->data = state->frame;
vf->data_len = state->size;
memcpy(line, state->frame,
state->linesize * 2 + state->pan);
for (i = 0; i < hd_size_y - 3; i++) {
memcpy(state->frame + i * state->linesize,
state->frame + (i +
2) * state->linesize +
state->pan, state->linesize);
}
memcpy(state->frame+i*state->linesize,
state->frame+(i+2)*state->linesize+state->pan, state->linesize-state->pan);
memcpy(state->frame+(hd_size_y-2)*state->linesize-state->pan,
line, state->linesize*2+state->pan);
memcpy(state->frame + i * state->linesize,
state->frame + (i + 2) * state->linesize +
state->pan, state->linesize - state->pan);
memcpy(state->frame +
(hd_size_y - 2) * state->linesize - state->pan,
line, state->linesize * 2 + state->pan);
/*if(!(state->count % 2)) {
unsigned int *p = state->frame;
for(i=0; i < state->linesize*hd_size_y/4; i++) {
*p = *p ^ 0x00ffffffL;
p++;
}
}*/
unsigned int *p = state->frame;
for(i=0; i < state->linesize*hd_size_y/4; i++) {
*p = *p ^ 0x00ffffffL;
p++;
}
} */
}
return vf;
}
return NULL;
}
struct vidcap_type *
vidcap_testcard_probe(void)
struct vidcap_type *vidcap_testcard_probe(void)
{
struct vidcap_type *vt;
struct vidcap_type *vt;
vt = (struct vidcap_type *) malloc(sizeof(struct vidcap_type));
vt = (struct vidcap_type *)malloc(sizeof(struct vidcap_type));
if (vt != NULL) {
vt->id = VIDCAP_TESTCARD_ID;
vt->name = "testcard";
vt->id = VIDCAP_TESTCARD_ID;
vt->name = "testcard";
vt->description = "Video testcard";
}
return vt;
}

View File

@@ -60,13 +60,12 @@ const struct codec_info_t codec_info[] = {
{Vuy2, "2vuy", '2vuy', 0, 2, 0},
{DVS8, "DVS8", 0, 0, 2, 0},
{R10k, "R10k", 1378955371, 0, 4, 1},
{v210, "v210", 1983000880, 48, 8.0/3.0, 0},
{DVS10, "DVS10", 0, 48, 8.0/3.0, 0},
{0, NULL, 0, 0, 0.0, 0}};
{v210, "v210", 1983000880, 48, 8.0 / 3.0, 0},
{DVS10, "DVS10", 0, 48, 8.0 / 3.0, 0},
{0, NULL, 0, 0, 0.0, 0}
};
void
show_codec_help(void)
void show_codec_help(void)
{
printf("\tSupported codecs:\n");
printf("\t\t8bits\n");
@@ -80,123 +79,119 @@ show_codec_help(void)
printf("\t\t\t'DVS10' - Centaurus 10bit YUV 4:2:2\n");
}
double
get_bpp(codec_t codec)
double get_bpp(codec_t codec)
{
int i=0;
int i = 0;
while(codec_info[i].name != NULL) {
if(codec == codec_info[i].codec)
return codec_info[i].bpp;
i++;
}
return 0;
while (codec_info[i].name != NULL) {
if (codec == codec_info[i].codec)
return codec_info[i].bpp;
i++;
}
return 0;
}
int
vc_getsrc_linesize(unsigned int width, codec_t codec)
int vc_getsrc_linesize(unsigned int width, codec_t codec)
{
if(codec_info[codec].h_align) {
width = ((width + codec_info[codec].h_align - 1) / codec_info[codec].h_align) * codec_info[codec].h_align;
if (codec_info[codec].h_align) {
width =
((width + codec_info[codec].h_align -
1) / codec_info[codec].h_align) *
codec_info[codec].h_align;
}
return width * codec_info[codec].bpp;
}
/* linear blend deinterlace */
void
vc_deinterlace(unsigned char *src, long src_linesize, int lines)
void vc_deinterlace(unsigned char *src, long src_linesize, int lines)
{
int i,j;
int i, j;
long pitch = src_linesize;
register long pitch2 = pitch*2;
register long pitch2 = pitch * 2;
unsigned char *bline1, *bline2, *bline3;
register unsigned char *line1, *line2, *line3;
bline1 = src;
bline2 = src + pitch;
bline3 = src + 3*pitch;
for(i=0; i < src_linesize; i+=16) {
/* preload first two lines */
asm volatile(
"movdqa (%0), %%xmm0\n"
"movdqa (%1), %%xmm1\n"
:
: "r" ((unsigned long *)bline1),
"r" ((unsigned long *)bline2));
line1 = bline2;
line2 = bline2 + pitch;
line3 = bline3;
for(j=0; j < lines-4; j+=2) {
asm volatile(
"movdqa (%1), %%xmm2\n"
"pavgb %%xmm2, %%xmm0\n"
"pavgb %%xmm1, %%xmm0\n"
"movdqa (%2), %%xmm1\n"
"movdqa %%xmm0, (%0)\n"
"pavgb %%xmm1, %%xmm0\n"
"pavgb %%xmm2, %%xmm0\n"
"movdqa %%xmm0, (%1)\n"
:
:"r" ((unsigned long *)line1),
"r" ((unsigned long *)line2),
"r" ((unsigned long *)line3)
);
line1 += pitch2;
line2 += pitch2;
line3 += pitch2;
bline3 = src + 3 * pitch;
for (i = 0; i < src_linesize; i += 16) {
/* preload first two lines */
asm volatile ("movdqa (%0), %%xmm0\n"
"movdqa (%1), %%xmm1\n"::"r" ((unsigned long *)
bline1),
"r"((unsigned long *)bline2));
line1 = bline2;
line2 = bline2 + pitch;
line3 = bline3;
for (j = 0; j < lines - 4; j += 2) {
asm volatile ("movdqa (%1), %%xmm2\n"
"pavgb %%xmm2, %%xmm0\n"
"pavgb %%xmm1, %%xmm0\n"
"movdqa (%2), %%xmm1\n"
"movdqa %%xmm0, (%0)\n"
"pavgb %%xmm1, %%xmm0\n"
"pavgb %%xmm2, %%xmm0\n"
"movdqa %%xmm0, (%1)\n"::"r" ((unsigned
long *)
line1),
"r"((unsigned long *)line2),
"r"((unsigned long *)line3)
);
line1 += pitch2;
line2 += pitch2;
line3 += pitch2;
}
bline1 += 16;
bline2 += 16;
bline3 += 16;
}
bline1 += 16;
bline2 += 16;
bline3 += 16;
}
}
void
vc_copylinev210(unsigned char *dst, unsigned char *src, int dst_len)
void vc_copylinev210(unsigned char *dst, unsigned char *src, int dst_len)
{
struct {
unsigned a:10;
unsigned b:10;
unsigned c:10;
unsigned p1:2;
unsigned a:10;
unsigned b:10;
unsigned c:10;
unsigned p1:2;
} *s;
register uint32_t *d;
register uint32_t tmp;
d = (uint32_t *)dst;
s = (void*)src;
d = (uint32_t *) dst;
s = (void *)src;
while(dst_len >= 12) {
while (dst_len >= 12) {
tmp = (s->a >> 2) | (s->b >> 2) << 8 | (((s)->c >> 2) << 16);
s++;
*(d++) = tmp | ((s->a >> 2) << 24);
tmp = (s->b >> 2) | (((s)->c >> 2) << 8);
s++;
*(d++) = tmp | ((s->a >> 2) << 16) | ((s->b >> 2)<<24);
*(d++) = tmp | ((s->a >> 2) << 16) | ((s->b >> 2) << 24);
tmp = (s->c >> 2);
s++;
*(d++) = tmp | ((s->a >> 2) << 8) | ((s->b >> 2) << 16) | ((s->c >> 2) << 24);
*(d++) =
tmp | ((s->a >> 2) << 8) | ((s->b >> 2) << 16) |
((s->c >> 2) << 24);
s++;
dst_len -= 12;
}
if(dst_len >= 4) {
tmp = (s->a >> 2) | (s->b >> 2) << 8 | (((s)->c >> 2) << 16);
s++;
*(d++) = tmp | ((s->a >> 2) << 24);
if (dst_len >= 4) {
tmp = (s->a >> 2) | (s->b >> 2) << 8 | (((s)->c >> 2) << 16);
s++;
*(d++) = tmp | ((s->a >> 2) << 24);
}
if(dst_len >= 8) {
tmp = (s->b >> 2) | (((s)->c >> 2) << 8);
s++;
*(d++) = tmp | ((s->a >> 2) << 16) | ((s->b >> 2)<<24);
if (dst_len >= 8) {
tmp = (s->b >> 2) | (((s)->c >> 2) << 8);
s++;
*(d++) = tmp | ((s->a >> 2) << 16) | ((s->b >> 2) << 24);
}
}
void
vc_copyliner10k(unsigned char *dst, unsigned char *src, int len, int rshift, int gshift, int bshift)
vc_copyliner10k(unsigned char *dst, unsigned char *src, int len, int rshift,
int gshift, int bshift)
{
struct {
unsigned r:8;
@@ -215,20 +210,36 @@ vc_copyliner10k(unsigned char *dst, unsigned char *src, int len, int rshift, int
register uint32_t *d;
register uint32_t tmp;
d = (uint32_t *)dst;
s = (void*)src;
d = (uint32_t *) dst;
s = (void *)src;
while(len > 0) {
tmp = (s->r << rshift) | (((s->gh << 2) | s->gl) << gshift) | (((s->bh << 4) | s->bl) << bshift);
while (len > 0) {
tmp =
(s->
r << rshift) | (((s->gh << 2) | s->
gl) << gshift) | (((s->bh << 4) | s->
bl) << bshift);
s++;
*(d++) = tmp;
tmp = (s->r << rshift) | (((s->gh << 2) | s->gl) << gshift) | (((s->bh << 4) | s->bl) << bshift);
tmp =
(s->
r << rshift) | (((s->gh << 2) | s->
gl) << gshift) | (((s->bh << 4) | s->
bl) << bshift);
s++;
*(d++) = tmp;
tmp = (s->r << rshift) | (((s->gh << 2) | s->gl) << gshift) | (((s->bh << 4) | s->bl) << bshift);
tmp =
(s->
r << rshift) | (((s->gh << 2) | s->
gl) << gshift) | (((s->bh << 4) | s->
bl) << bshift);
s++;
*(d++) = tmp;
tmp = (s->r << rshift) | (((s->gh << 2) | s->gl) << gshift) | (((s->bh << 4) | s->bl) << bshift);
tmp =
(s->
r << rshift) | (((s->gh << 2) | s->
gl) << gshift) | (((s->bh << 4) | s->
bl) << bshift);
s++;
*(d++) = tmp;
len -= 16;
@@ -236,17 +247,18 @@ vc_copyliner10k(unsigned char *dst, unsigned char *src, int len, int rshift, int
}
void
vc_copylineRGBA(unsigned char *dst, unsigned char *src, int len, int rshift, int gshift, int bshift)
vc_copylineRGBA(unsigned char *dst, unsigned char *src, int len, int rshift,
int gshift, int bshift)
{
register uint32_t *d=(uint32_t*)dst;
register uint32_t *s=(uint32_t*)src;
register uint32_t *d = (uint32_t *) dst;
register uint32_t *s = (uint32_t *) src;
register uint32_t tmp;
if(rshift == 0 && gshift == 8 && bshift == 16) {
if (rshift == 0 && gshift == 8 && bshift == 16) {
memcpy(dst, src, len);
} else {
while(len > 0) {
register unsigned int r,g,b;
while (len > 0) {
register unsigned int r, g, b;
tmp = *(s++);
r = tmp & 0xff;
g = (tmp >> 8) & 0xff;
@@ -280,78 +292,74 @@ vc_copylineRGBA(unsigned char *dst, unsigned char *src, int len, int rshift, int
#if !(HAVE_MACOSX || HAVE_32B_LINUX)
void
vc_copylineDVS10(unsigned char *dst, unsigned char *src, int src_len)
void vc_copylineDVS10(unsigned char *dst, unsigned char *src, int src_len)
{
register unsigned char *_d=dst,*_s=src;
register unsigned char *_d = dst, *_s = src;
while(len > 0) {
while (len > 0) {
asm ("movd %0, %%xmm4\n": : "r" (0xffffff));
asm("movd %0, %%xmm4\n": :"r"(0xffffff));
asm volatile ("movdqa (%0), %%xmm0\n"
"movdqa 16(%0), %%xmm5\n"
"movdqa %%xmm0, %%xmm1\n"
"movdqa %%xmm0, %%xmm2\n"
"movdqa %%xmm0, %%xmm3\n"
"pand %%xmm4, %%xmm0\n"
"movdqa %%xmm5, %%xmm6\n"
"movdqa %%xmm5, %%xmm7\n"
"movdqa %%xmm5, %%xmm8\n"
"pand %%xmm4, %%xmm5\n"
"pslldq $4, %%xmm4\n"
"pand %%xmm4, %%xmm1\n"
"pand %%xmm4, %%xmm6\n"
"pslldq $4, %%xmm4\n"
"psrldq $1, %%xmm1\n"
"psrldq $1, %%xmm6\n"
"pand %%xmm4, %%xmm2\n"
"pand %%xmm4, %%xmm7\n"
"pslldq $4, %%xmm4\n"
"psrldq $2, %%xmm2\n"
"psrldq $2, %%xmm7\n"
"pand %%xmm4, %%xmm3\n"
"pand %%xmm4, %%xmm8\n"
"por %%xmm1, %%xmm0\n"
"psrldq $3, %%xmm3\n"
"psrldq $3, %%xmm8\n"
"por %%xmm2, %%xmm0\n"
"por %%xmm6, %%xmm5\n"
"por %%xmm3, %%xmm0\n"
"por %%xmm7, %%xmm5\n"
"movdq2q %%xmm0, %%mm0\n"
"por %%xmm8, %%xmm5\n"
"movdqa %%xmm5, %%xmm1\n"
"pslldq $12, %%xmm5\n"
"psrldq $4, %%xmm1\n"
"por %%xmm5, %%xmm0\n"
"psrldq $8, %%xmm0\n"
"movq %%mm0, (%1)\n"
"movdq2q %%xmm0, %%mm1\n"
"movdq2q %%xmm1, %%mm2\n"
"movq %%mm1, 8(%1)\n"
"movq %%mm2, 16(%1)\n"
:
: "r" (_s), "r" (_d));
_s += 32;
_d += 24;
src_len -= 32;
}
asm volatile ("movdqa (%0), %%xmm0\n"
"movdqa 16(%0), %%xmm5\n"
"movdqa %%xmm0, %%xmm1\n"
"movdqa %%xmm0, %%xmm2\n"
"movdqa %%xmm0, %%xmm3\n"
"pand %%xmm4, %%xmm0\n"
"movdqa %%xmm5, %%xmm6\n"
"movdqa %%xmm5, %%xmm7\n"
"movdqa %%xmm5, %%xmm8\n"
"pand %%xmm4, %%xmm5\n"
"pslldq $4, %%xmm4\n"
"pand %%xmm4, %%xmm1\n"
"pand %%xmm4, %%xmm6\n"
"pslldq $4, %%xmm4\n"
"psrldq $1, %%xmm1\n"
"psrldq $1, %%xmm6\n"
"pand %%xmm4, %%xmm2\n"
"pand %%xmm4, %%xmm7\n"
"pslldq $4, %%xmm4\n"
"psrldq $2, %%xmm2\n"
"psrldq $2, %%xmm7\n"
"pand %%xmm4, %%xmm3\n"
"pand %%xmm4, %%xmm8\n"
"por %%xmm1, %%xmm0\n"
"psrldq $3, %%xmm3\n"
"psrldq $3, %%xmm8\n"
"por %%xmm2, %%xmm0\n"
"por %%xmm6, %%xmm5\n"
"por %%xmm3, %%xmm0\n"
"por %%xmm7, %%xmm5\n"
"movdq2q %%xmm0, %%mm0\n"
"por %%xmm8, %%xmm5\n"
"movdqa %%xmm5, %%xmm1\n"
"pslldq $12, %%xmm5\n"
"psrldq $4, %%xmm1\n"
"por %%xmm5, %%xmm0\n"
"psrldq $8, %%xmm0\n"
"movq %%mm0, (%1)\n"
"movdq2q %%xmm0, %%mm1\n"
"movdq2q %%xmm1, %%mm2\n"
"movq %%mm1, 8(%1)\n"
"movq %%mm2, 16(%1)\n"::"r" (_s), "r"(_d));
_s += 32;
_d += 24;
src_len -= 32;
}
}
#else
void
vc_copylineDVS10(unsigned char *dst, unsigned char *src, int src_len)
void vc_copylineDVS10(unsigned char *dst, unsigned char *src, int src_len)
{
register uint64_t *d, *s;
register uint64_t a1,a2,a3,a4;
register uint64_t a1, a2, a3, a4;
d = (uint64_t *)dst;
s = (uint64_t *)src;
d = (uint64_t *) dst;
s = (uint64_t *) src;
while(src_len > 0) {
while (src_len > 0) {
a1 = *(s++);
a2 = *(s++);
a3 = *(s++);
@@ -363,11 +371,11 @@ vc_copylineDVS10(unsigned char *dst, unsigned char *src, int src_len)
a4 = (a4 & 0xffffff) | ((a4 >> 8) & 0xffffff000000LL);
*(d++) = a1 | (a2 << 48); /* 0xa2|a2|a1|a1|a1|a1|a1|a1 */
*(d++) = (a2 >> 16)|(a3 << 32); /* 0xa3|a3|a3|a3|a2|a2|a2|a2 */
*(d++) = (a3 >> 32)|(a4 << 16); /* 0xa4|a4|a4|a4|a4|a4|a3|a3 */
*(d++) = (a2 >> 16) | (a3 << 32); /* 0xa3|a3|a3|a3|a2|a2|a2|a2 */
*(d++) = (a3 >> 32) | (a4 << 16); /* 0xa4|a4|a4|a4|a4|a4|a3|a3 */
src_len -= 16;
}
}
#endif /* !(HAVE_MACOSX || HAVE_32B_LINUX) */
#endif /* !(HAVE_MACOSX || HAVE_32B_LINUX) */

View File

@@ -54,9 +54,9 @@
#include <assert.h>
#ifdef HAVE_MACOSX
#include <malloc/malloc.h>
#else /* HAVE_MACOSX */
#else /* HAVE_MACOSX */
#include <malloc.h>
#endif /* HAVE_MACOSX */
#endif /* HAVE_MACOSX */
#include <string.h>
#include <unistd.h>
#include "video_types.h"
@@ -65,7 +65,7 @@
#ifndef HAVE_MACOSX
#define uint64_t unsigned long
#endif /* HAVE_MACOSX */
#endif /* HAVE_MACOSX */
/* NOTE: These threads busy wait, so at *most* set this to one less than the
* total number of cores on your system (Also 3 threads will work)! Also, if
@@ -85,140 +85,141 @@
*/
struct video_compress {
unsigned char *buffer[NUM_THREADS];
unsigned char *output_data;
unsigned char *out;
pthread_mutex_t lock;
int thread_count,len[NUM_THREADS],go[NUM_THREADS];
pthread_t thread_ids[NUM_THREADS];
unsigned char *buffer[NUM_THREADS];
unsigned char *output_data;
unsigned char *out;
pthread_mutex_t lock;
int thread_count, len[NUM_THREADS], go[NUM_THREADS];
pthread_t thread_ids[NUM_THREADS];
};
inline void compress_copyline64(unsigned char *dst, unsigned char *src, int len);
inline void compress_copyline64(unsigned char *dst, unsigned char *src,
int len);
inline void compress_copyline128(unsigned char *d, unsigned char *s, int len);
void compress_deinterlace(unsigned char *buffer);
void compress_data(void *args, struct video_frame * tx);
void compress_data(void *args, struct video_frame *tx);
struct video_compress * initialize_video_compression(void)
struct video_compress *initialize_video_compression(void)
{
/* This function does the following:
* 1. Allocate memory for buffers
* 2. Spawn compressor threads
*/
int x;
struct video_compress *compress;
/* This function does the following:
* 1. Allocate memory for buffers
* 2. Spawn compressor threads
*/
int x;
struct video_compress *compress;
compress=calloc(1,sizeof(struct video_compress));
for(x=0;x<NUM_THREADS;x++) {
compress->buffer[x]=(unsigned char*)malloc(1920*1080*4/NUM_THREADS);
}
compress = calloc(1, sizeof(struct video_compress));
for (x = 0; x < NUM_THREADS; x++) {
compress->buffer[x] =
(unsigned char *)malloc(1920 * 1080 * 4 / NUM_THREADS);
}
#ifdef HAVE_MACOSX
compress->output_data=(unsigned char*)malloc(1920*1080*4);
compress->out=(unsigned char*)malloc(1920*1080*4);
#else
/*
* memalign doesn't exist on Mac OS. malloc always returns 16
* bytes aligned memory
*
compress->output_data = (unsigned char *)malloc(1920 * 1080 * 4);
compress->out = (unsigned char *)malloc(1920 * 1080 * 4);
#else
/*
* memalign doesn't exist on Mac OS. malloc always returns 16
* bytes aligned memory
*
* see: http://www.mythtv.org/pipermail/mythtv-dev/2006-January/044309.html
*/
compress->output_data=(unsigned char*)memalign(16,1920*1080*4);
compress->out=(unsigned char*)memalign(16,1920*1080*4);
#endif /* HAVE_MACOSX */
memset(compress->output_data,0,1920*1080*4);
memset(compress->out,0,1920*1080*4/8);
compress->thread_count=0;
if(pthread_mutex_init(&(compress->lock),NULL)){
perror("Error initializing mutex!");
exit(x);
}
*/
compress->output_data = (unsigned char *)memalign(16, 1920 * 1080 * 4);
compress->out = (unsigned char *)memalign(16, 1920 * 1080 * 4);
#endif /* HAVE_MACOSX */
memset(compress->output_data, 0, 1920 * 1080 * 4);
memset(compress->out, 0, 1920 * 1080 * 4 / 8);
compress->thread_count = 0;
if (pthread_mutex_init(&(compress->lock), NULL)) {
perror("Error initializing mutex!");
exit(x);
}
pthread_mutex_lock(&(compress->lock));
pthread_mutex_lock(&(compress->lock));
for(x=0;x<NUM_THREADS;x++){
if(pthread_create(&(compress->thread_ids[x]), NULL, (void *)compress_thread, (void *)compress)) {
perror("Unable to create compressor thread!");
exit(x);
}
for (x = 0; x < NUM_THREADS; x++) {
if (pthread_create
(&(compress->thread_ids[x]), NULL, (void *)compress_thread,
(void *)compress)) {
perror("Unable to create compressor thread!");
exit(x);
}
compress->go[x]=0;
compress->len[x]=0;
}
pthread_mutex_unlock(&(compress->lock));
return compress;
compress->go[x] = 0;
compress->len[x] = 0;
}
pthread_mutex_unlock(&(compress->lock));
return compress;
}
#if !(HAVE_MACOSX || HAVE_32B_LINUX)
inline void compress_copyline128(unsigned char *d, unsigned char *s, int len)
{
register unsigned char *_d=d,*_s=s;
register unsigned char *_d = d, *_s = s;
while(--len >= 0) {
while (--len >= 0) {
asm ("movd %0, %%xmm4\n": : "r" (0xffffff));
asm("movd %0, %%xmm4\n": :"r"(0xffffff));
asm volatile ("movdqa (%0), %%xmm0\n"
"movdqa 16(%0), %%xmm5\n"
"movdqa %%xmm0, %%xmm1\n"
"movdqa %%xmm0, %%xmm2\n"
"movdqa %%xmm0, %%xmm3\n"
"pand %%xmm4, %%xmm0\n"
"movdqa %%xmm5, %%xmm6\n"
"movdqa %%xmm5, %%xmm7\n"
"movdqa %%xmm5, %%xmm8\n"
"pand %%xmm4, %%xmm5\n"
"pslldq $4, %%xmm4\n"
"pand %%xmm4, %%xmm1\n"
"pand %%xmm4, %%xmm6\n"
"pslldq $4, %%xmm4\n"
"psrldq $1, %%xmm1\n"
"psrldq $1, %%xmm6\n"
"pand %%xmm4, %%xmm2\n"
"pand %%xmm4, %%xmm7\n"
"pslldq $4, %%xmm4\n"
"psrldq $2, %%xmm2\n"
"psrldq $2, %%xmm7\n"
"pand %%xmm4, %%xmm3\n"
"pand %%xmm4, %%xmm8\n"
"por %%xmm1, %%xmm0\n"
"psrldq $3, %%xmm3\n"
"psrldq $3, %%xmm8\n"
"por %%xmm2, %%xmm0\n"
"por %%xmm6, %%xmm5\n"
"por %%xmm3, %%xmm0\n"
"por %%xmm7, %%xmm5\n"
"movdq2q %%xmm0, %%mm0\n"
"por %%xmm8, %%xmm5\n"
"movdqa %%xmm5, %%xmm1\n"
"pslldq $12, %%xmm5\n"
"psrldq $4, %%xmm1\n"
"por %%xmm5, %%xmm0\n"
"psrldq $8, %%xmm0\n"
"movq %%mm0, (%1)\n"
"movdq2q %%xmm0, %%mm1\n"
"movdq2q %%xmm1, %%mm2\n"
"movq %%mm1, 8(%1)\n"
"movq %%mm2, 16(%1)\n"
:
: "r" (_s), "r" (_d));
"movdqa 16(%0), %%xmm5\n"
"movdqa %%xmm0, %%xmm1\n"
"movdqa %%xmm0, %%xmm2\n"
"movdqa %%xmm0, %%xmm3\n"
"pand %%xmm4, %%xmm0\n"
"movdqa %%xmm5, %%xmm6\n"
"movdqa %%xmm5, %%xmm7\n"
"movdqa %%xmm5, %%xmm8\n"
"pand %%xmm4, %%xmm5\n"
"pslldq $4, %%xmm4\n"
"pand %%xmm4, %%xmm1\n"
"pand %%xmm4, %%xmm6\n"
"pslldq $4, %%xmm4\n"
"psrldq $1, %%xmm1\n"
"psrldq $1, %%xmm6\n"
"pand %%xmm4, %%xmm2\n"
"pand %%xmm4, %%xmm7\n"
"pslldq $4, %%xmm4\n"
"psrldq $2, %%xmm2\n"
"psrldq $2, %%xmm7\n"
"pand %%xmm4, %%xmm3\n"
"pand %%xmm4, %%xmm8\n"
"por %%xmm1, %%xmm0\n"
"psrldq $3, %%xmm3\n"
"psrldq $3, %%xmm8\n"
"por %%xmm2, %%xmm0\n"
"por %%xmm6, %%xmm5\n"
"por %%xmm3, %%xmm0\n"
"por %%xmm7, %%xmm5\n"
"movdq2q %%xmm0, %%mm0\n"
"por %%xmm8, %%xmm5\n"
"movdqa %%xmm5, %%xmm1\n"
"pslldq $12, %%xmm5\n"
"psrldq $4, %%xmm1\n"
"por %%xmm5, %%xmm0\n"
"psrldq $8, %%xmm0\n"
"movq %%mm0, (%1)\n"
"movdq2q %%xmm0, %%mm1\n"
"movdq2q %%xmm1, %%mm2\n"
"movq %%mm1, 8(%1)\n"
"movq %%mm2, 16(%1)\n"::"r" (_s), "r"(_d));
_s += 32;
_d += 24;
}
}
#endif /* !(HAVE_MACOSX || HAVE_32B_LINUX) */
#endif /* !(HAVE_MACOSX || HAVE_32B_LINUX) */
inline void compress_copyline64(unsigned char *dst, unsigned char *src, int len)
{
register uint64_t *d, *s;
register uint64_t a1,a2,a3,a4;
register uint64_t a1, a2, a3, a4;
d = (uint64_t *)dst;
s = (uint64_t *)src;
d = (uint64_t *) dst;
s = (uint64_t *) src;
while(len-- > 0) {
while (len-- > 0) {
a1 = *(s++);
a2 = *(s++);
a3 = *(s++);
@@ -230,50 +231,46 @@ inline void compress_copyline64(unsigned char *dst, unsigned char *src, int len)
a4 = (a4 & 0xffffff) | ((a4 >> 8) & 0xffffff000000);
*(d++) = a1 | (a2 << 48); /* 0xa2|a2|a1|a1|a1|a1|a1|a1 */
*(d++) = (a2 >> 16)|(a3 << 32); /* 0xa3|a3|a3|a3|a2|a2|a2|a2 */
*(d++) = (a3 >> 32)|(a4 << 16); /* 0xa4|a4|a4|a4|a4|a4|a3|a3 */
*(d++) = (a2 >> 16) | (a3 << 32); /* 0xa3|a3|a3|a3|a2|a2|a2|a2 */
*(d++) = (a3 >> 32) | (a4 << 16); /* 0xa4|a4|a4|a4|a4|a4|a3|a3 */
}
}
/* linear blend deinterlace */
void compress_deinterlace(unsigned char *buffer)
{
int i,j;
long pitch = 1920*2;
register long pitch2 = pitch*2;
int i, j;
long pitch = 1920 * 2;
register long pitch2 = pitch * 2;
unsigned char *bline1, *bline2, *bline3;
register unsigned char *line1, *line2, *line3;
bline1 = buffer;
bline2 = buffer + pitch;
bline3 = buffer + 3*pitch;
for(i=0; i < 1920*2; i+=16) {
bline3 = buffer + 3 * pitch;
for (i = 0; i < 1920 * 2; i += 16) {
/* preload first two lines */
asm volatile(
"movdqa (%0), %%xmm0\n"
"movdqa (%1), %%xmm1\n"
:
: "r" ((unsigned long *)bline1),
"r" ((unsigned long *)bline2));
asm volatile ("movdqa (%0), %%xmm0\n"
"movdqa (%1), %%xmm1\n"::"r" ((unsigned long *)
bline1),
"r"((unsigned long *)bline2));
line1 = bline2;
line2 = bline2 + pitch;
line3 = bline3;
for(j=0; j < 1076; j+=2) {
asm volatile(
"movdqa (%1), %%xmm2\n"
"pavgb %%xmm2, %%xmm0\n"
"pavgb %%xmm1, %%xmm0\n"
"movdqa (%2), %%xmm1\n"
"movdqa %%xmm0, (%0)\n"
"pavgb %%xmm1, %%xmm0\n"
"pavgb %%xmm2, %%xmm0\n"
"movdqa %%xmm0, (%1)\n"
:
:"r" ((unsigned long *)line1),
"r" ((unsigned long *)line2),
"r" ((unsigned long *)line3)
);
for (j = 0; j < 1076; j += 2) {
asm volatile ("movdqa (%1), %%xmm2\n"
"pavgb %%xmm2, %%xmm0\n"
"pavgb %%xmm1, %%xmm0\n"
"movdqa (%2), %%xmm1\n"
"movdqa %%xmm0, (%0)\n"
"pavgb %%xmm1, %%xmm0\n"
"pavgb %%xmm2, %%xmm0\n"
"movdqa %%xmm0, (%1)\n"::"r" ((unsigned
long *)
line1),
"r"((unsigned long *)line2),
"r"((unsigned long *)line3)
);
line1 += pitch2;
line2 += pitch2;
line3 += pitch2;
@@ -284,116 +281,123 @@ void compress_deinterlace(unsigned char *buffer)
}
}
void compress_data(void *args, struct video_frame * tx)
void compress_data(void *args, struct video_frame *tx)
{
/* This thread will be called from main.c and handle the compress_threads */
struct video_compress * compress= (struct video_compress *)args;
int x,total=0;
int i;
unsigned char *line1,*line2;
/* This thread will be called from main.c and handle the compress_threads */
struct video_compress *compress = (struct video_compress *)args;
int x, total = 0;
int i;
unsigned char *line1, *line2;
line1=(unsigned char *)tx->data;
line2=compress->output_data;
/* First 10->8 bit conversion */
if (bitdepth == 10) {
for(x=0;x<HD_HEIGHT;x+=2) {
line1 = (unsigned char *)tx->data;
line2 = compress->output_data;
/* First 10->8 bit conversion */
if (bitdepth == 10) {
for (x = 0; x < HD_HEIGHT; x += 2) {
#if (HAVE_MACOSX || HAVE_32B_LINUX)
compress_copyline64(line2, line1, 5120/32);
compress_copyline64(line2+3840, line1+5120*540, 5120/32);
#else /* (HAVE_MACOSX || HAVE_32B_LINUX) */
compress_copyline128(line2, line1, 5120/32);
compress_copyline128(line2+3840, line1+5120*540, 5120/32);
#endif /* (HAVE_MACOSX || HAVE_32B_LINUX) */
line1 += 5120;
line2 += 2*3840;
}
} else {
if (progressive == 1) {
memcpy(line2, line1, hd_size_x*hd_size_y*hd_color_bpp);
} else {
for(i=0; i<1080; i+=2) {
memcpy(line2, line1, hd_size_x*hd_color_bpp);
memcpy(line2+hd_size_x*hd_color_bpp, line1+hd_size_x*hd_color_bpp*540, hd_size_x*hd_color_bpp);
line1 += hd_size_x*hd_color_bpp;
line2 += 2*hd_size_x*hd_color_bpp;
}
}
}
compress_copyline64(line2, line1, 5120 / 32);
compress_copyline64(line2 + 3840, line1 + 5120 * 540,
5120 / 32);
compress_deinterlace(compress->output_data);
#else /* (HAVE_MACOSX || HAVE_32B_LINUX) */
compress_copyline128(line2, line1, 5120 / 32);
compress_copyline128(line2 + 3840, line1 + 5120 * 540,
5120 / 32);
#endif /* (HAVE_MACOSX || HAVE_32B_LINUX) */
line1 += 5120;
line2 += 2 * 3840;
}
} else {
if (progressive == 1) {
memcpy(line2, line1,
hd_size_x * hd_size_y * hd_color_bpp);
} else {
for (i = 0; i < 1080; i += 2) {
memcpy(line2, line1, hd_size_x * hd_color_bpp);
memcpy(line2 + hd_size_x * hd_color_bpp,
line1 + hd_size_x * hd_color_bpp * 540,
hd_size_x * hd_color_bpp);
line1 += hd_size_x * hd_color_bpp;
line2 += 2 * hd_size_x * hd_color_bpp;
}
}
}
for(x=0;x<NUM_THREADS;x++) {
compress->go[x]=1;
}
compress_deinterlace(compress->output_data);
while(total!=1036800){
//This is just getting silly...
total=0;
for(x=0;x<NUM_THREADS;x++) {
total+=compress->len[x];
}
}
for (x = 0; x < NUM_THREADS; x++) {
compress->go[x] = 1;
}
tx->data=(char *)compress->out;
tx->colour_mode=DXT_1080;
tx->data_len=total;
while (total != 1036800) {
//This is just getting silly...
total = 0;
for (x = 0; x < NUM_THREADS; x++) {
total += compress->len[x];
}
}
tx->data = (char *)compress->out;
tx->colour_mode = DXT_1080;
tx->data_len = total;
}
static void compress_thread(void *args)
{
struct video_compress * compress= (struct video_compress *)args;
int myId,myEnd,myStart,range,x;
unsigned char *retv, *input;
struct video_compress *compress = (struct video_compress *)args;
int myId, myEnd, myStart, range, x;
unsigned char *retv, *input;
pthread_mutex_lock(&(compress->lock));
myId=compress->thread_count;
compress->thread_count++;
pthread_mutex_unlock(&(compress->lock));
range=1920*1080/NUM_THREADS;
myStart=myId*range;
myEnd=(myId+1)*range;
fprintf(stderr, "Thread %d online, handling elements %d - %d\n",myId,myStart,myEnd-1);
pthread_mutex_lock(&(compress->lock));
myId = compress->thread_count;
compress->thread_count++;
pthread_mutex_unlock(&(compress->lock));
range = 1920 * 1080 / NUM_THREADS;
myStart = myId * range;
myEnd = (myId + 1) * range;
fprintf(stderr, "Thread %d online, handling elements %d - %d\n", myId,
myStart, myEnd - 1);
while (1) {
while (compress->go[myId] == 0) {
//Busywait
}
retv = compress->buffer[myId];
input =
(compress->output_data) +
(myId * 1920 * 1080 * 2 / NUM_THREADS);
/* Repack the data to YUV 4:4:4 Format */
for (x = 0; x < range; x += 2) {
retv[4 * x] = input[2 * x + 1]; //Y1
retv[4 * x + 1] = input[2 * x]; //U1
retv[4 * x + 2] = input[2 * x + 2]; //V1
retv[4 * x + 3] = 255; //Alpha
while(1) {
while(compress->go[myId]==0) {
//Busywait
}
retv=compress->buffer[myId];
input=(compress->output_data)+(myId*1920*1080*2/NUM_THREADS);
/* Repack the data to YUV 4:4:4 Format */
for(x=0;x<range;x+=2) {
retv[4*x]=input[2*x+1]; //Y1
retv[4*x+1]=input[2*x]; //U1
retv[4*x+2]=input[2*x+2]; //V1
retv[4*x+3]=255; //Alpha
retv[4 * x + 4] = input[2 * x + 3]; //Y2
retv[4 * x + 5] = input[2 * x]; //U1
retv[4 * x + 6] = input[2 * x + 2]; //V1
retv[4 * x + 7] = 255; //Alpha
}
compress->len[myId] =
DirectDXT1(retv,
(compress->out) + myId * 1036800 / (NUM_THREADS),
1920, 1080 / NUM_THREADS);
compress->go[myId] = 0;
retv[4*x+4]=input[2*x+3]; //Y2
retv[4*x+5]=input[2*x]; //U1
retv[4*x+6]=input[2*x+2]; //V1
retv[4*x+7]=255; //Alpha
}
compress->len[myId]=DirectDXT1(retv,(compress->out)+myId*1036800/(NUM_THREADS),1920,1080/NUM_THREADS);
compress->go[myId]=0;
}
}
}
void compress_exit(void *args)
{
struct video_compress * compress= (struct video_compress *)args;
int x;
struct video_compress *compress = (struct video_compress *)args;
int x;
for(x=0;x<compress->thread_count;x++){
pthread_kill(compress->thread_ids[x],SIGKILL);
}
for (x = 0; x < compress->thread_count; x++) {
pthread_kill(compress->thread_ids[x], SIGKILL);
}
free(compress->buffer[0]);
free(compress->buffer[1]);
free(compress->buffer[2]);
free(compress->buffer[3]);
free(compress->buffer[0]);
free(compress->buffer[1]);
free(compress->buffer[2]);
free(compress->buffer[3]);
}

View File

@@ -73,167 +73,162 @@
*/
typedef struct {
display_id_t id;
display_type_t *(*func_probe)(void);
void *(*func_init)(char *fmt);
void (*func_done)(void *state);
char *(*func_getf)(void *state);
int (*func_putf)(void *state, char *frame);
display_colour_t (*func_colour)(void *state);
display_id_t id;
display_type_t *(*func_probe) (void);
void *(*func_init) (char *fmt);
void (*func_done) (void *state);
char *(*func_getf) (void *state);
int (*func_putf) (void *state, char *frame);
display_colour_t(*func_colour) (void *state);
} display_table_t;
static display_table_t display_device_table[] = {
#ifndef X_DISPLAY_MISSING
{
0,
display_xv_probe,
display_xv_init,
display_xv_done,
display_xv_getf,
display_xv_putf,
display_xv_colour,
},
{
0,
display_x11_probe,
display_x11_init,
display_x11_done,
display_x11_getf,
display_x11_putf,
display_x11_colour,
},
{
0,
display_xv_probe,
display_xv_init,
display_xv_done,
display_xv_getf,
display_xv_putf,
display_xv_colour,
},
{
0,
display_x11_probe,
display_x11_init,
display_x11_done,
display_x11_getf,
display_x11_putf,
display_x11_colour,
},
#ifdef HAVE_SDL
{
0,
display_sdl_probe,
display_sdl_init,
display_sdl_done,
display_sdl_getf,
display_sdl_putf,
display_sdl_colour,
},
{
0,
display_sdl_probe,
display_sdl_init,
display_sdl_done,
display_sdl_getf,
display_sdl_putf,
display_sdl_colour,
},
#ifdef HAVE_GL
{
0,
display_gl_probe,
display_gl_init,
display_gl_done,
display_gl_getf,
display_gl_putf,
display_gl_colour,
},
{
0,
display_gl_probe,
display_gl_init,
display_gl_done,
display_gl_getf,
display_gl_putf,
display_gl_colour,
},
#ifdef HAVE_SAGE
{
0,
display_sage_probe,
display_sage_init,
display_sage_done,
display_sage_getf,
display_sage_putf,
display_sage_colour,
},
#endif /* HAVE_SAGE */
{
0,
display_sage_probe,
display_sage_init,
display_sage_done,
display_sage_getf,
display_sage_putf,
display_sage_colour,
},
#endif /* HAVE_SAGE */
#ifdef HAVE_FASTDXT
{
0,
display_dxt_probe,
display_dxt_init,
display_dxt_done,
display_dxt_getf,
display_dxt_putf,
display_dxt_colour,
},
#endif /* HAVE_FASTDXT */
#endif /* HAVE_GL */
#endif /* HAVE_SDL */
#endif /* X_DISPLAY_MISSING */
{
0,
display_dxt_probe,
display_dxt_init,
display_dxt_done,
display_dxt_getf,
display_dxt_putf,
display_dxt_colour,
},
#endif /* HAVE_FASTDXT */
#endif /* HAVE_GL */
#endif /* HAVE_SDL */
#endif /* X_DISPLAY_MISSING */
#ifdef HAVE_HDSTATION
{
0,
display_hdstation_probe,
display_hdstation_init,
display_hdstation_done,
display_hdstation_getf,
display_hdstation_putf,
display_hdstation_colour,
},
#endif /* HAVE_HDSTATION */
{
0,
display_hdstation_probe,
display_hdstation_init,
display_hdstation_done,
display_hdstation_getf,
display_hdstation_putf,
display_hdstation_colour,
},
#endif /* HAVE_HDSTATION */
#ifdef HAVE_MACOSX
{
0,
display_quicktime_probe,
display_quicktime_init,
display_quicktime_done,
display_quicktime_getf,
display_quicktime_putf,
display_quicktime_colour,
},
#endif /* HAVE_MACOSX */
{
0,
display_null_probe,
display_null_init,
display_null_done,
display_null_getf,
display_null_putf,
display_null_colour,
}
{
0,
display_quicktime_probe,
display_quicktime_init,
display_quicktime_done,
display_quicktime_getf,
display_quicktime_putf,
display_quicktime_colour,
},
#endif /* HAVE_MACOSX */
{
0,
display_null_probe,
display_null_init,
display_null_done,
display_null_getf,
display_null_putf,
display_null_colour,
}
};
#define DISPLAY_DEVICE_TABLE_SIZE (sizeof(display_device_table) / sizeof(display_table_t))
static display_type_t *available_devices[DISPLAY_DEVICE_TABLE_SIZE];
static int available_device_count = 0;
static display_type_t *available_devices[DISPLAY_DEVICE_TABLE_SIZE];
static int available_device_count = 0;
int
display_init_devices(void)
int display_init_devices(void)
{
unsigned int i;
display_type_t *dt;
unsigned int i;
display_type_t *dt;
assert(available_device_count == 0);
assert(available_device_count == 0);
for (i = 0; i < DISPLAY_DEVICE_TABLE_SIZE; i++) {
dt = display_device_table[i].func_probe();
if (dt != NULL) {
display_device_table[i].id = dt->id;
available_devices[available_device_count++] = dt;
}
}
return 0;
for (i = 0; i < DISPLAY_DEVICE_TABLE_SIZE; i++) {
dt = display_device_table[i].func_probe();
if (dt != NULL) {
display_device_table[i].id = dt->id;
available_devices[available_device_count++] = dt;
}
}
return 0;
}
void
display_free_devices(void)
void display_free_devices(void)
{
int i;
int i;
for (i = 0; i < available_device_count; i++) {
free(available_devices[i]);
available_devices[i] = NULL;
}
available_device_count = 0;
for (i = 0; i < available_device_count; i++) {
free(available_devices[i]);
available_devices[i] = NULL;
}
available_device_count = 0;
}
int
display_get_device_count(void)
int display_get_device_count(void)
{
return available_device_count;
return available_device_count;
}
display_type_t *
display_get_device_details(int index)
display_type_t *display_get_device_details(int index)
{
assert(index < available_device_count);
assert(available_devices[index] != NULL);
assert(index < available_device_count);
assert(available_devices[index] != NULL);
return available_devices[index];
return available_devices[index];
}
display_id_t
display_get_null_device_id(void)
display_id_t display_get_null_device_id(void)
{
return DISPLAY_NULL_ID;
return DISPLAY_NULL_ID;
}
/*
@@ -243,59 +238,55 @@ display_get_null_device_id(void)
#define DISPLAY_MAGIC 0x01ba7ef1
struct display {
uint32_t magic;
int index;
void *state;
uint32_t magic;
int index;
void *state;
};
struct display *
display_init(display_id_t id, char *fmt)
struct display *display_init(display_id_t id, char *fmt)
{
unsigned int i;
unsigned int i;
for (i = 0; i < DISPLAY_DEVICE_TABLE_SIZE; i++) {
if (display_device_table[i].id == id) {
struct display *d = (struct display *) malloc(sizeof(struct display));
d->magic = DISPLAY_MAGIC;
d->state = display_device_table[i].func_init(fmt);
d->index = i;
if (d->state == NULL) {
debug_msg("Unable to start display 0x%08lx\n", id);
free(d);
return NULL;
}
return d;
}
}
debug_msg("Unknown display id: 0x%08x\n", id);
return NULL;
for (i = 0; i < DISPLAY_DEVICE_TABLE_SIZE; i++) {
if (display_device_table[i].id == id) {
struct display *d =
(struct display *)malloc(sizeof(struct display));
d->magic = DISPLAY_MAGIC;
d->state = display_device_table[i].func_init(fmt);
d->index = i;
if (d->state == NULL) {
debug_msg("Unable to start display 0x%08lx\n",
id);
free(d);
return NULL;
}
return d;
}
}
debug_msg("Unknown display id: 0x%08x\n", id);
return NULL;
}
void
display_done(struct display *d)
void display_done(struct display *d)
{
assert(d->magic == DISPLAY_MAGIC);
display_device_table[d->index].func_done(d->state);
assert(d->magic == DISPLAY_MAGIC);
display_device_table[d->index].func_done(d->state);
}
struct video_frame*
display_get_frame(struct display *d)
struct video_frame *display_get_frame(struct display *d)
{
assert(d->magic == DISPLAY_MAGIC);
return display_device_table[d->index].func_getf(d->state);
assert(d->magic == DISPLAY_MAGIC);
return display_device_table[d->index].func_getf(d->state);
}
void
display_put_frame(struct display *d, char *frame)
void display_put_frame(struct display *d, char *frame)
{
assert(d->magic == DISPLAY_MAGIC);
display_device_table[d->index].func_putf(d->state, frame);
assert(d->magic == DISPLAY_MAGIC);
display_device_table[d->index].func_putf(d->state, frame);
}
display_colour_t
display_get_colour_mode(struct display *d)
display_colour_t display_get_colour_mode(struct display *d)
{
assert(d->magic == DISPLAY_MAGIC);
return display_device_table[d->index].func_colour(d->state);
assert(d->magic == DISPLAY_MAGIC);
return display_device_table[d->index].func_colour(d->state);
}

View File

@@ -54,11 +54,11 @@
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <OpenGL/glext.h>
#else /* HAVE_MACOSX */
#else /* HAVE_MACOSX */
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#endif /* HAVE_MACOSX */
#endif /* HAVE_MACOSX */
#include <SDL/SDL.h>
#include "compat/platform_semaphore.h"
#include <signal.h>
@@ -74,7 +74,6 @@
#include "video_display/dxt.h"
// #define glGetProcAddress(n) glXGetProcAddressARB((GLubyte *) n)
#define degree_to_radian(x) ( M_PI * x / 180.0f )
#define radian_to_degree(x) ( x * (180.0f / M_PI) )
@@ -83,476 +82,501 @@
#define MAGIC_DXT DISPLAY_DXT_ID
#define SIZE 1036800
struct state_sdl {
Display *display;
unsigned int x_res_x;
unsigned int x_res_y;
Display *display;
unsigned int x_res_x;
unsigned int x_res_y;
int vw_depth;
SDL_Overlay *vw_image;
GLubyte *buffers[2];
GLubyte *outbuffer;
GLubyte *y, *u, *v; //Guess what this might be...
GLhandleARB VSHandle,FSHandle,PHandle;
int image_display, image_network;
GLuint texture[4];
int vw_depth;
SDL_Overlay *vw_image;
GLubyte *buffers[2];
GLubyte *outbuffer;
GLubyte *y, *u, *v; //Guess what this might be...
GLhandleARB VSHandle, FSHandle, PHandle;
int image_display, image_network;
GLuint texture[4];
/* Thread related information follows... */
pthread_t thread_id;
sem_t semaphore;
pthread_t thread_id;
sem_t semaphore;
/* For debugging... */
uint32_t magic;
uint32_t magic;
SDL_Surface *sdl_screen;
SDL_Rect rect;
SDL_Surface *sdl_screen;
SDL_Rect rect;
char *FProgram,*VProgram;
char *FProgram, *VProgram;
};
/* Prototyping */
static void * display_thread_dxt(void *arg);
static void *display_thread_dxt(void *arg);
void dxt_resize_window(int width, int height);
void dxt_bind_texture(void *args);
void dxt_draw();
void * display_dxt_init(void);
void *display_dxt_init(void);
void dxt_arb_init(void *arg);
void glsl_dxt_init(void *arg);
void dxt_loadShader(void *arg, char *filename);
void dxt_draw();
#ifdef DEBUG
void dxt_check_error()
{
GLenum msg;
int flag=0;
msg=glGetError();
while(msg!=GL_NO_ERROR) {
flag=1;
switch(msg){
case GL_INVALID_ENUM:
fprintf(stderr, "GL_INVALID_ENUM\n");
break;
case GL_INVALID_VALUE:
fprintf(stderr, "GL_INVALID_VALUE\n");
break;
case GL_INVALID_OPERATION:
fprintf(stderr, "GL_INVALID_OPERATION\n");
break;
case GL_STACK_OVERFLOW:
fprintf(stderr, "GL_STACK_OVERFLOW\n");
break;
case GL_STACK_UNDERFLOW:
fprintf(stderr, "GL_STACK_UNDERFLOW\n");
break;
case GL_OUT_OF_MEMORY:
fprintf(stderr, "GL_OUT_OF_MEMORY\n");
break;
default:
fprintf(stderr, "wft mate? Unknown GL ERROR: %p\n",msg);
break;
}
msg=glGetError();
}
if(flag)
exit(1);
GLenum msg;
int flag = 0;
msg = glGetError();
while (msg != GL_NO_ERROR) {
flag = 1;
switch (msg) {
case GL_INVALID_ENUM:
fprintf(stderr, "GL_INVALID_ENUM\n");
break;
case GL_INVALID_VALUE:
fprintf(stderr, "GL_INVALID_VALUE\n");
break;
case GL_INVALID_OPERATION:
fprintf(stderr, "GL_INVALID_OPERATION\n");
break;
case GL_STACK_OVERFLOW:
fprintf(stderr, "GL_STACK_OVERFLOW\n");
break;
case GL_STACK_UNDERFLOW:
fprintf(stderr, "GL_STACK_UNDERFLOW\n");
break;
case GL_OUT_OF_MEMORY:
fprintf(stderr, "GL_OUT_OF_MEMORY\n");
break;
default:
fprintf(stderr, "wft mate? Unknown GL ERROR: %p\n",
msg);
break;
}
msg = glGetError();
}
if (flag)
exit(1);
}
#endif /* DEBUG */
#endif /* DEBUG */
void * display_dxt_init(void)
void *display_dxt_init(void)
{
struct state_sdl *s;
struct state_sdl *s;
int ret;
int itemp;
unsigned int utemp;
Window wtemp;
int ret;
int itemp;
unsigned int utemp;
Window wtemp;
s = (struct state_sdl *) calloc(1,sizeof(struct state_sdl));
s->magic = MAGIC_DXT;
s = (struct state_sdl *)calloc(1, sizeof(struct state_sdl));
s->magic = MAGIC_DXT;
if (!(s->display = XOpenDisplay(NULL))) {
printf("Unable to open display DXT: XOpenDisplay.\n");
return NULL;
}
if (!(s->display = XOpenDisplay(NULL))) {
printf("Unable to open display DXT: XOpenDisplay.\n");
return NULL;
}
/* Get XWindows resolution */
ret = XGetGeometry(s->display, DefaultRootWindow(s->display), &wtemp, &itemp, &itemp, &(s->x_res_x), &(s->x_res_y), &utemp, &utemp);
s->rect.w = HD_WIDTH;
s->rect.h =HD_HEIGHT;
if ((s->x_res_x - HD_WIDTH) > 0) {
s->rect.x = (s->x_res_x - HD_WIDTH) / 2;
} else {
s->rect.x = 0;
}
if ((s->x_res_y - HD_HEIGHT) > 0) {
s->rect.y = (s->x_res_y - HD_HEIGHT) / 2;
} else {
s->rect.y = 0;
}
/* Get XWindows resolution */
ret =
XGetGeometry(s->display, DefaultRootWindow(s->display), &wtemp,
&itemp, &itemp, &(s->x_res_x), &(s->x_res_y), &utemp,
&utemp);
s->buffers[0]=malloc(HD_WIDTH*HD_HEIGHT*3);
s->buffers[1]=malloc(HD_WIDTH*HD_HEIGHT*3);
s->outbuffer=malloc(HD_WIDTH*HD_HEIGHT*4);
s->image_network=0;
s->image_display=1;
s->rect.w = HD_WIDTH;
s->rect.h = HD_HEIGHT;
if ((s->x_res_x - HD_WIDTH) > 0) {
s->rect.x = (s->x_res_x - HD_WIDTH) / 2;
} else {
s->rect.x = 0;
}
if ((s->x_res_y - HD_HEIGHT) > 0) {
s->rect.y = (s->x_res_y - HD_HEIGHT) / 2;
} else {
s->rect.y = 0;
}
asm("emms\n");
s->buffers[0] = malloc(HD_WIDTH * HD_HEIGHT * 3);
s->buffers[1] = malloc(HD_WIDTH * HD_HEIGHT * 3);
s->outbuffer = malloc(HD_WIDTH * HD_HEIGHT * 4);
s->image_network = 0;
s->image_display = 1;
platform_sem_init(&s->semaphore, 0, 0);
if (pthread_create(&(s->thread_id), NULL, display_thread_dxt, (void *) s) != 0) {
perror("Unable to create display thread\n");
return NULL;
}
asm("emms\n");
return (void*)s;
platform_sem_init(&s->semaphore, 0, 0);
if (pthread_create(&(s->thread_id), NULL, display_thread_dxt, (void *)s)
!= 0) {
perror("Unable to create display thread\n");
return NULL;
}
return (void *)s;
}
void dxt_loadShader(void *arg, char *filename)
{
struct state_sdl *s = (struct state_sdl *) arg;
struct stat file;
s = (struct state_sdl *) calloc(1,sizeof(struct state_sdl));
struct state_sdl *s = (struct state_sdl *)arg;
struct stat file;
s = (struct state_sdl *)calloc(1, sizeof(struct state_sdl));
stat(filename,&file);
s->FProgram=calloc(file.st_size+1,sizeof(char));
FILE *fh;
fh=fopen(filename, "r");
if(!fh){
perror(filename);
exit(113);
}
fread(s->FProgram,sizeof(char),file.st_size,fh);
fclose(fh);
stat(filename, &file);
s->FProgram = calloc(file.st_size + 1, sizeof(char));
FILE *fh;
fh = fopen(filename, "r");
if (!fh) {
perror(filename);
exit(113);
}
fread(s->FProgram, sizeof(char), file.st_size, fh);
fclose(fh);
}
void dxt_arb_init(void *arg)
{
struct state_sdl *s = (struct state_sdl *) arg;
char *log;
/* Set up program objects. */
s->PHandle=glCreateProgramObjectARB();
s->FSHandle=glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
s->VSHandle=glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
struct state_sdl *s = (struct state_sdl *)arg;
char *log;
/* Set up program objects. */
s->PHandle = glCreateProgramObjectARB();
s->FSHandle = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
s->VSHandle = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
/* Compile Shader */
assert(s->FProgram!=NULL);
glShaderSourceARB(s->FSHandle,1,(const GLcharARB**)&(s->FProgram),NULL);
glCompileShaderARB(s->FSHandle);
glShaderSourceARB(s->VSHandle,1,(const GLcharARB**)&(s->VProgram),NULL);
glCompileShaderARB(s->VSHandle);
/* Compile Shader */
assert(s->FProgram != NULL);
glShaderSourceARB(s->FSHandle, 1, (const GLcharARB **)&(s->FProgram),
NULL);
glCompileShaderARB(s->FSHandle);
glShaderSourceARB(s->VSHandle, 1, (const GLcharARB **)&(s->VProgram),
NULL);
glCompileShaderARB(s->VSHandle);
/* Print compile log */
log=calloc(32768,sizeof(char));
glGetInfoLogARB(s->FSHandle,32768,NULL,log);
printf("Compile Log: %s\n", log);
free(log);
log=calloc(32768,sizeof(char));
glGetInfoLogARB(s->VSHandle,32768,NULL,log);
printf("Compile Log: %s\n", log);
free(log);
/* Print compile log */
log = calloc(32768, sizeof(char));
glGetInfoLogARB(s->FSHandle, 32768, NULL, log);
printf("Compile Log: %s\n", log);
free(log);
log = calloc(32768, sizeof(char));
glGetInfoLogARB(s->VSHandle, 32768, NULL, log);
printf("Compile Log: %s\n", log);
free(log);
/* Attach and link our program */
glAttachObjectARB(s->PHandle,s->FSHandle);
glAttachObjectARB(s->PHandle,s->VSHandle);
glLinkProgramARB(s->PHandle);
/* Attach and link our program */
glAttachObjectARB(s->PHandle, s->FSHandle);
glAttachObjectARB(s->PHandle, s->VSHandle);
glLinkProgramARB(s->PHandle);
/* Print link log. */
log=calloc(32768,sizeof(char));
glGetInfoLogARB(s->PHandle,32768,NULL,log);
printf("Link Log: %s\n", log);
free(log);
/* Print link log. */
log = calloc(32768, sizeof(char));
glGetInfoLogARB(s->PHandle, 32768, NULL, log);
printf("Link Log: %s\n", log);
free(log);
/* Finally, use the program. */
glUseProgramObjectARB(s->PHandle);
/* Finally, use the program. */
glUseProgramObjectARB(s->PHandle);
}
void glsl_dxt_init(void *arg)
{
//TODO: Add log
struct state_sdl *s = (struct state_sdl *) arg;
//TODO: Add log
struct state_sdl *s = (struct state_sdl *)arg;
s->PHandle=glCreateProgram();
s->FSHandle=glCreateShader(GL_FRAGMENT_SHADER);
s->PHandle = glCreateProgram();
s->FSHandle = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(s->FSHandle,1,(const GLcharARB**)&(s->FProgram),NULL);
glCompileShader(s->FSHandle);
glShaderSource(s->FSHandle, 1, (const GLcharARB **)&(s->FProgram),
NULL);
glCompileShader(s->FSHandle);
glAttachShader(s->PHandle,s->FSHandle);
glAttachShader(s->PHandle, s->FSHandle);
glLinkProgram(s->PHandle);
glUseProgram(s->PHandle);
glLinkProgram(s->PHandle);
glUseProgram(s->PHandle);
}
void dxt_resize_window(int width, int height)
{
/* Height / width ration */
GLfloat ratio;
GLint y = 0;
/* Height / width ration */
GLfloat ratio;
GLint y = 0;
/* Protect against a divide by zero */
if ( height == 0 )
height = 1;
/* Protect against a divide by zero */
if (height == 0)
height = 1;
if ((height > HD_HEIGHT) && (width >= HD_WIDTH)) {
y = (height - HD_HEIGHT) / 2;
height = HD_HEIGHT;
}
ratio =
(GLfloat) width / (GLfloat) (((float)(width * HD_HEIGHT)) /
((float)HD_WIDTH));
if ((height > HD_HEIGHT) && (width >= HD_WIDTH)) {
y = (height - HD_HEIGHT) / 2;
height = HD_HEIGHT;
}
ratio = ( GLfloat )width / ( GLfloat )(((float)(width * HD_HEIGHT))/((float)HD_WIDTH));
glViewport(0, y, (GLint) width, (GLint) height);
glViewport( 0, y, ( GLint )width, (GLint)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode( GL_PROJECTION );
glLoadIdentity( );
glScalef(1,
(((float)(width * HD_HEIGHT)) / ((float)HD_WIDTH)) /
((float)height), 1);
gluPerspective(45.0f, ratio, 0.1f, 100.0f);
glScalef(1, (((float)(width * HD_HEIGHT))/((float)HD_WIDTH))/((float)height), 1);
gluPerspective(45.0f, ratio, 0.1f, 100.0f);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void dxt_bind_texture(void *arg)
{
struct state_sdl *s = (struct state_sdl *) arg;
static int i=0;
struct state_sdl *s = (struct state_sdl *)arg;
static int i = 0;
//TODO: does OpenGL use different stuff here?
glActiveTexture(GL_TEXTURE0);
i=glGetUniformLocationARB(s->PHandle,"yuvtex");
glUniform1iARB(i,0);
glBindTexture(GL_TEXTURE_2D,0);
glCompressedTexImage2D(GL_TEXTURE_2D, 0,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,1920,1080, 0,(1920*1080/16)*8, s->buffers[s->image_display]);
//TODO: does OpenGL use different stuff here?
glActiveTexture(GL_TEXTURE0);
i = glGetUniformLocationARB(s->PHandle, "yuvtex");
glUniform1iARB(i, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glCompressedTexImage2D(GL_TEXTURE_2D, 0,
GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 1920, 1080, 0,
(1920 * 1080 / 16) * 8,
s->buffers[s->image_display]);
}
}
void dxt_draw()
{
glLoadIdentity( );
glTranslatef( 0.0f, 0.0f, -1.35f );
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -1.35f);
glBegin(GL_QUADS);
/* Front Face */
/* Bottom Left Of The Texture and Quad */
glTexCoord2f( 0.0f, 1.0f ); glVertex2f( -1.0f, -0.5625f);
/* Bottom Right Of The Texture and Quad */
glTexCoord2f( 1.0f, 1.0f ); glVertex2f( 1.0f, -0.5625f);
/* Top Right Of The Texture and Quad */
glTexCoord2f( 1.0f, 0.0f ); glVertex2f( 1.0f, 0.5625f);
/* Top Left Of The Texture and Quad */
glTexCoord2f( 0.0f, 0.0f ); glVertex2f( -1.0f, 0.5625f);
glEnd( );
glBegin(GL_QUADS);
/* Front Face */
/* Bottom Left Of The Texture and Quad */
glTexCoord2f(0.0f, 1.0f);
glVertex2f(-1.0f, -0.5625f);
/* Bottom Right Of The Texture and Quad */
glTexCoord2f(1.0f, 1.0f);
glVertex2f(1.0f, -0.5625f);
/* Top Right Of The Texture and Quad */
glTexCoord2f(1.0f, 0.0f);
glVertex2f(1.0f, 0.5625f);
/* Top Left Of The Texture and Quad */
glTexCoord2f(0.0f, 0.0f);
glVertex2f(-1.0f, 0.5625f);
glEnd();
SDL_GL_SwapBuffers( );
SDL_GL_SwapBuffers();
}
static void * display_thread_dxt(void *arg)
static void *display_thread_dxt(void *arg)
{
struct state_sdl *s = (struct state_sdl *) arg;
struct state_sdl *s = (struct state_sdl *)arg;
#ifndef HAVE_MACOSX
int i;
#endif /* HAVE_MACOSX */
const SDL_VideoInfo *videoInfo;
int videoFlags;
/* FPS */
static GLint T0 = 0;
static GLint Frames = 0;
int i;
#endif /* HAVE_MACOSX */
const SDL_VideoInfo *videoInfo;
int videoFlags;
/* FPS */
static GLint T0 = 0;
static GLint Frames = 0;
#ifdef HAVE_MACOSX
/* Startup function to call when running Cocoa code from a Carbon application. Whatever the fuck that means. */
/* Avoids uncaught exception (1002) when creating CGSWindow */
NSApplicationLoad();
/* Startup function to call when running Cocoa code from a Carbon application. Whatever the fuck that means. */
/* Avoids uncaught exception (1002) when creating CGSWindow */
NSApplicationLoad();
#endif
/* initialize SDL */
if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
fprintf( stderr, "Video initialization failed: %s\n",SDL_GetError());
exit(1);
}
/* initialize SDL */
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "Video initialization failed: %s\n",
SDL_GetError());
exit(1);
}
/* Fetch the video info */
videoInfo = SDL_GetVideoInfo( );
/* Fetch the video info */
videoInfo = SDL_GetVideoInfo();
if ( !videoInfo ) {
fprintf( stderr, "Video query failed: %s\n",SDL_GetError());
exit(1);
}
if (!videoInfo) {
fprintf(stderr, "Video query failed: %s\n", SDL_GetError());
exit(1);
}
/* the flags to pass to SDL_SetVideoMode */
videoFlags = SDL_OPENGL; /* Enable OpenGL in SDL */
videoFlags |= SDL_GL_DOUBLEBUFFER; /* Enable double buffering */
videoFlags |= SDL_HWPALETTE; /* Store the palette in hardware */
videoFlags |= SDL_FULLSCREEN; /* Fullscreen */
/* the flags to pass to SDL_SetVideoMode */
videoFlags = SDL_OPENGL; /* Enable OpenGL in SDL */
videoFlags |= SDL_GL_DOUBLEBUFFER; /* Enable double buffering */
videoFlags |= SDL_HWPALETTE; /* Store the palette in hardware */
videoFlags |= SDL_FULLSCREEN; /* Fullscreen */
/* This checks to see if surfaces can be stored in memory */
if ( videoInfo->hw_available )
videoFlags |= SDL_HWSURFACE;
else
videoFlags |= SDL_SWSURFACE;
/* This checks to see if surfaces can be stored in memory */
if (videoInfo->hw_available)
videoFlags |= SDL_HWSURFACE;
else
videoFlags |= SDL_SWSURFACE;
/* This checks if hardware blits can be done */
if ( videoInfo->blit_hw )
videoFlags |= SDL_HWACCEL;
/* This checks if hardware blits can be done */
if (videoInfo->blit_hw)
videoFlags |= SDL_HWACCEL;
/* Sets up OpenGL double buffering */
/* Sets up OpenGL double buffering */
// SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
// SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
// SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
// SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
#ifdef HAVE_SDL_1210
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
#endif /* HAVE_SDL_1210 */
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
#endif /* HAVE_SDL_1210 */
/* get a SDL surface */
s->sdl_screen = SDL_SetVideoMode(s->x_res_x, s->x_res_y, 32, videoFlags);
if(!s->sdl_screen){
fprintf(stderr,"Error setting video mode %dx%d!\n", s->x_res_x, s->x_res_y);
exit(128);
}
/* get a SDL surface */
s->sdl_screen =
SDL_SetVideoMode(s->x_res_x, s->x_res_y, 32, videoFlags);
if (!s->sdl_screen) {
fprintf(stderr, "Error setting video mode %dx%d!\n", s->x_res_x,
s->x_res_y);
exit(128);
}
SDL_WM_SetCaption("Ultragrid - Form Of DXT!", "Ultragrid");
SDL_WM_SetCaption("Ultragrid - Form Of DXT!", "Ultragrid");
SDL_ShowCursor(SDL_DISABLE);
SDL_ShowCursor(SDL_DISABLE);
/* OpenGL Setup */
glEnable( GL_TEXTURE_2D );
glGenTextures(1, s->texture);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
//glClearColor( 0, 1, 0, 0 );
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
dxt_resize_window(s->x_res_x, s->x_res_y);
glewInit();
if(glewIsSupported("GL_VERSION_2_0")){
fprintf(stderr, "OpenGL 2.0 is supported...\n");
}
/* Load shader */
//TODO: Need a less breaky way to do this...
struct stat file;
char *filename=strdup("../src/video_display/dxt.frag");
if (stat(filename,&file) != 0) {
filename=strdup("/usr/share/uv-0.3.1/dxt.frag");
if (stat(filename,&file) != 0) {
filename=strdup("/usr/local/share/uv-0.3.1/dxt.frag");
if (stat(filename,&file) != 0) {
fprintf(stderr, "dxt.frag not found. Giving up!\n");
exit(113);
}
}
}
s->FProgram=calloc(file.st_size+1,sizeof(char));
glEnable(GL_TEXTURE_2D);
glGenTextures(1, s->texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//glClearColor( 0, 1, 0, 0 );
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
dxt_resize_window(s->x_res_x, s->x_res_y);
glewInit();
if (glewIsSupported("GL_VERSION_2_0")) {
fprintf(stderr, "OpenGL 2.0 is supported...\n");
}
/* Load shader */
//TODO: Need a less breaky way to do this...
struct stat file;
char *filename = strdup("../src/video_display/dxt.frag");
if (stat(filename, &file) != 0) {
filename = strdup("/usr/share/uv-0.3.1/dxt.frag");
if (stat(filename, &file) != 0) {
filename = strdup("/usr/local/share/uv-0.3.1/dxt.frag");
if (stat(filename, &file) != 0) {
fprintf(stderr,
"dxt.frag not found. Giving up!\n");
exit(113);
}
}
}
s->FProgram = calloc(file.st_size + 1, sizeof(char));
FILE *fh;
fh=fopen(filename, "r");
if(!fh){
fh = fopen(filename, "r");
if (!fh) {
perror(filename);
exit(113);
}
fread(s->FProgram,sizeof(char),file.st_size,fh);
fread(s->FProgram, sizeof(char), file.st_size, fh);
fclose(fh);
char *filename2=strdup("../src/video_display/dxt.vert");
if (stat(filename2,&file) != 0) {
filename2=strdup("/usr/share/uv-0.3.1/dxt.vert");
if (stat(filename2,&file) != 0) {
filename2=strdup("/usr/local/share/uv-0.3.1/dxt.vert");
if (stat(filename2,&file) != 0) {
fprintf(stderr, "dxt.vert not found. Giving up!\n");
exit(113);
}
}
}
s->VProgram=calloc(file.st_size+1,sizeof(char));
fh=fopen(filename2, "r");
if(!fh){
char *filename2 = strdup("../src/video_display/dxt.vert");
if (stat(filename2, &file) != 0) {
filename2 = strdup("/usr/share/uv-0.3.1/dxt.vert");
if (stat(filename2, &file) != 0) {
filename2 =
strdup("/usr/local/share/uv-0.3.1/dxt.vert");
if (stat(filename2, &file) != 0) {
fprintf(stderr,
"dxt.vert not found. Giving up!\n");
exit(113);
}
}
}
s->VProgram = calloc(file.st_size + 1, sizeof(char));
fh = fopen(filename2, "r");
if (!fh) {
perror(filename2);
exit(113);
}
fread(s->VProgram,sizeof(char),file.st_size,fh);
fread(s->VProgram, sizeof(char), file.st_size, fh);
fclose(fh);
/* Check to see if OpenGL 2.0 is supported, if not use ARB (if supported) */
glewInit();
if(glewIsSupported("GL_VERSION_2_0")){
fprintf(stderr, "OpenGL 2.0 is supported...\n");
/* Check to see if OpenGL 2.0 is supported, if not use ARB (if supported) */
glewInit();
if (glewIsSupported("GL_VERSION_2_0")) {
fprintf(stderr, "OpenGL 2.0 is supported...\n");
//TODO: Re-enable dxt_init!
//glsl_dxt_init(s);
dxt_arb_init(s);
}else if(GLEW_ARB_fragment_shader){
fprintf(stderr, "OpenGL 2.0 not supported, using ARB extension...\n");
dxt_arb_init(s);
}else{
fprintf(stderr, "ERROR: Neither OpenGL 2.0 nor ARB_fragment_shader are supported, try updating your drivers...\n");
exit(65);
}
dxt_arb_init(s);
} else if (GLEW_ARB_fragment_shader) {
fprintf(stderr,
"OpenGL 2.0 not supported, using ARB extension...\n");
dxt_arb_init(s);
} else {
fprintf(stderr,
"ERROR: Neither OpenGL 2.0 nor ARB_fragment_shader are supported, try updating your drivers...\n");
exit(65);
}
/* Check to see if we have data yet, if not, just chillax */
/* TODO: we need some solution (TM) for sem_getvalue on MacOS X */
/* Check to see if we have data yet, if not, just chillax */
/* TODO: we need some solution (TM) for sem_getvalue on MacOS X */
#ifndef HAVE_MACOSX
sem_getvalue(&s->semaphore,&i);
while(i<1) {
display_dxt_handle_events(s);
usleep(1000);
sem_getvalue(&s->semaphore,&i);
}
#endif /* HAVE_MACOSX */
sem_getvalue(&s->semaphore, &i);
while (i < 1) {
display_dxt_handle_events(s);
usleep(1000);
sem_getvalue(&s->semaphore, &i);
}
#endif /* HAVE_MACOSX */
while(1) {
display_dxt_handle_events(s);
platform_sem_wait(&s->semaphore);
while (1) {
display_dxt_handle_events(s);
platform_sem_wait(&s->semaphore);
dxt_bind_texture(s);
dxt_draw(s);
dxt_bind_texture(s);
dxt_draw(s);
/* FPS Data, this is pretty ghetto though.... */
Frames++;
{
GLint t = SDL_GetTicks();
if (t - T0 >= 5000) {
GLfloat seconds = (t - T0) / 1000.0;
GLfloat fps = Frames / seconds;
fprintf(stderr, "%d frames in %g seconds = %g FPS\n", (int)Frames, seconds, fps);
T0 = t;
Frames = 0;
GLfloat seconds = (t - T0) / 1000.0;
GLfloat fps = Frames / seconds;
fprintf(stderr,
"%d frames in %g seconds = %g FPS\n",
(int)Frames, seconds, fps);
T0 = t;
Frames = 0;
}
}
}
return NULL;
}
return NULL;
}
display_type_t *display_dxt_probe(void)
{
display_type_t *dt;
display_format_t *dformat;
display_type_t *dt;
display_format_t *dformat;
dformat = malloc(4 * sizeof(display_format_t));
dformat[0].size = DS_176x144;
dformat[0].size = DS_176x144;
dformat[0].colour_mode = DC_YUV;
dformat[0].num_images = 1;
dformat[1].size = DS_352x288;
dformat[0].num_images = 1;
dformat[1].size = DS_352x288;
dformat[1].colour_mode = DC_YUV;
dformat[1].num_images = 1;
dformat[2].size = DS_702x576;
dformat[1].num_images = 1;
dformat[2].size = DS_702x576;
dformat[2].colour_mode = DC_YUV;
dformat[2].num_images = 1;
dformat[3].size = DS_1280x720;
dformat[2].num_images = 1;
dformat[3].size = DS_1280x720;
dformat[3].colour_mode = DC_YUV;
dformat[3].num_images = 1;
dformat[3].num_images = 1;
dt = malloc(sizeof(display_type_t));
if (dt != NULL) {
dt->id = DISPLAY_DXT_ID;
dt->name = "dxt";
dt->id = DISPLAY_DXT_ID;
dt->name = "dxt";
dt->description = "OpenGL With DXT Compression";
dt->formats = dformat;
dt->formats = dformat;
dt->num_formats = 4;
}
return dt;
@@ -560,7 +584,7 @@ display_type_t *display_dxt_probe(void)
void display_dxt_done(void *state)
{
struct state_sdl *s = (struct state_sdl *) state;
struct state_sdl *s = (struct state_sdl *)state;
assert(s->magic == MAGIC_DXT);
@@ -568,10 +592,10 @@ void display_dxt_done(void *state)
SDL_Quit();
}
char* display_dxt_getf(void *state)
char *display_dxt_getf(void *state)
{
struct state_sdl *s = (struct state_sdl *) state;
struct state_sdl *s = (struct state_sdl *)state;
assert(s->magic == MAGIC_DXT);
return (char *)s->buffers[s->image_network];
}
@@ -579,7 +603,7 @@ char* display_dxt_getf(void *state)
int display_dxt_putf(void *state, char *frame)
{
int tmp;
struct state_sdl *s = (struct state_sdl *) state;
struct state_sdl *s = (struct state_sdl *)state;
assert(s->magic == MAGIC_DXT);
UNUSED(frame);
@@ -592,35 +616,36 @@ int display_dxt_putf(void *state, char *frame)
/* ...and signal the worker */
platform_sem_post(&s->semaphore);
sem_getvalue(&s->semaphore, &tmp);
if(tmp > 1)
if (tmp > 1)
printf("frame drop!\n");
return 0;
}
display_colour_t display_dxt_colour(void *state)
{
struct state_sdl *s = (struct state_sdl *) state;
struct state_sdl *s = (struct state_sdl *)state;
assert(s->magic == MAGIC_DXT);
return DC_YUV;
}
int display_dxt_handle_events(void *state)
{
SDL_Event sdl_event;
SDL_Event sdl_event;
UNUSED(state);
UNUSED(state);
while (SDL_PollEvent(&sdl_event)) {
switch (sdl_event.type) {
case SDL_KEYDOWN:
case SDL_KEYUP:
if (!strcmp(SDL_GetKeyName(sdl_event.key.keysym.sym), "q")) {
kill(0, SIGINT);
}
break;
case SDL_KEYDOWN:
case SDL_KEYUP:
if (!strcmp
(SDL_GetKeyName(sdl_event.key.keysym.sym), "q")) {
kill(0, SIGINT);
}
break;
default:
break;
default:
break;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -57,7 +57,7 @@
#include "config_win32.h"
#include "host.h"
#ifdef HAVE_HDSTATION /* From config.h */
#ifdef HAVE_HDSTATION /* From config.h */
#include "debug.h"
#include "video_display.h"
@@ -65,288 +65,285 @@
#include "video_codec.h"
#include "tv.h"
#include "dvs_clib.h" /* From the DVS SDK */
#include "dvs_fifo.h" /* From the DVS SDK */
#include "dvs_clib.h" /* From the DVS SDK */
#include "dvs_fifo.h" /* From the DVS SDK */
#define HDSP_MAGIC 0x12345678
struct state_hdsp {
pthread_t thread_id;
sv_handle *sv;
sv_fifo *fifo;
char *frame_buffer;
int frame_size;
sv_fifo_buffer *fifo_buffer;
sv_fifo_buffer *display_buffer;
sv_fifo_buffer *tmp_buffer;
pthread_mutex_t lock;
pthread_cond_t boss_cv;
pthread_cond_t worker_cv;
int work_to_do;
int boss_waiting;
int worker_waiting;
uint32_t magic;
char *bufs[2];
int bufs_index;
codec_t codec;
int hd_video_mode;
double bpp;
pthread_t thread_id;
sv_handle *sv;
sv_fifo *fifo;
char *frame_buffer;
int frame_size;
sv_fifo_buffer *fifo_buffer;
sv_fifo_buffer *display_buffer;
sv_fifo_buffer *tmp_buffer;
pthread_mutex_t lock;
pthread_cond_t boss_cv;
pthread_cond_t worker_cv;
int work_to_do;
int boss_waiting;
int worker_waiting;
uint32_t magic;
char *bufs[2];
int bufs_index;
codec_t codec;
int hd_video_mode;
double bpp;
};
static void*
display_thread_hd(void *arg)
static void *display_thread_hd(void *arg)
{
struct state_hdsp *s = (struct state_hdsp *) arg;
int res;
struct state_hdsp *s = (struct state_hdsp *)arg;
int res;
while (1) {
pthread_mutex_lock(&s->lock);
while (1) {
pthread_mutex_lock(&s->lock);
while (s->work_to_do == FALSE) {
s->worker_waiting = TRUE;
pthread_cond_wait(&s->worker_cv, &s->lock);
s->worker_waiting = FALSE;
}
while (s->work_to_do == FALSE) {
s->worker_waiting = TRUE;
pthread_cond_wait(&s->worker_cv, &s->lock);
s->worker_waiting = FALSE;
}
s->display_buffer = s->tmp_buffer;
s->work_to_do = FALSE;
s->display_buffer = s->tmp_buffer;
s->work_to_do = FALSE;
if (s->boss_waiting) {
pthread_cond_signal(&s->boss_cv);
}
pthread_mutex_unlock(&s->lock);
if (s->boss_waiting) {
pthread_cond_signal(&s->boss_cv);
}
pthread_mutex_unlock(&s->lock);
res = sv_fifo_putbuffer(s->sv, s->fifo, s->display_buffer, NULL);
if (res != SV_OK) {
debug_msg("Error %s\n", sv_geterrortext(res));
return NULL;
}
}
return NULL;
}
char *
display_hdstation_getf(void *state)
{
struct state_hdsp *s = (struct state_hdsp *) state;
int res;
assert(s->magic == HDSP_MAGIC);
/* Prepare the new RTP buffer... */
res = sv_fifo_getbuffer(s->sv, s->fifo, &s->fifo_buffer, NULL, SV_FIFO_FLAG_VIDEOONLY | SV_FIFO_FLAG_FLUSH);
if (res != SV_OK) {
debug_msg("Error %s\n", sv_geterrortext(res));
return NULL;
}
s->bufs_index = (s->bufs_index + 1) % 2;
s->frame_buffer = s->bufs[s->bufs_index];
s->frame_size = hd_size_x * hd_size_y * s->bpp;
s->fifo_buffer->dma.addr = s->frame_buffer;
s->fifo_buffer->dma.size = s->frame_size;
return s->frame_buffer;
}
int
display_hdstation_putf(void *state, char *frame)
{
struct state_hdsp *s = (struct state_hdsp *) state;
UNUSED(frame);
assert(s->magic == HDSP_MAGIC);
pthread_mutex_lock(&s->lock);
/* Wait for the worker to finish... */
while (s->work_to_do) {
s->boss_waiting = TRUE;
pthread_cond_wait(&s->boss_cv, &s->lock);
s->boss_waiting = FALSE;
}
/* ...and give it more to do... */
s->tmp_buffer = s->fifo_buffer;
s->fifo_buffer = NULL;
s->work_to_do = TRUE;
/* ...and signal the worker */
if (s->worker_waiting) {
pthread_cond_signal(&s->worker_cv);
}
pthread_mutex_unlock(&s->lock);
return TRUE;
}
void *
display_hdstation_init(char *fmt)
{
struct state_hdsp *s;
int fps;
int i;
int res;
if (fmt != NULL) {
if (strcmp(fmt, "help") == 0) {
printf("hdstation options:\n");
printf("\tfps:codec\n");
return 0;
}
char *tmp;
tmp = strtok(fmt, ":");
if (!tmp) {
fprintf(stderr, "Wrong config %s\n", fmt);
return 0;
}
fps = atoi(tmp);
tmp = strtok(NULL, ":");
if (!tmp) {
fprintf(stderr, "Wrong config %s\n", fmt);
return 0;
}
s->codec = 0xffffffff;
for(i = 0; codec_info[i].name != NULL; i++) {
if(strcmp(tmp, codec_info[i].name) == 0) {
s->codec = codec_info[i].codec;
s->bpp = codec_info[i].bpp;
res =
sv_fifo_putbuffer(s->sv, s->fifo, s->display_buffer, NULL);
if (res != SV_OK) {
debug_msg("Error %s\n", sv_geterrortext(res));
return NULL;
}
}
if(s->codec == 0xffffffff) {
fprintf(stderr, "hdstation: unknown codec: %s\n", tmp);
free(s);
free(tmp);
return 0;
}
}
s->hd_video_mode=SV_MODE_COLOR_YUV422 | SV_MODE_ACTIVE_STREAMER;
if (s->codec == DVS10) {
s->hd_video_mode |= SV_MODE_NBIT_10BDVS;
}
if (fps == 25) {
s->hd_video_mode |= SV_MODE_SMPTE274_25P;
}
else if (fps == 29) {
s->hd_video_mode |= SV_MODE_SMPTE274_29I;
}
else {
fprintf(stderr, "Wrong framerate in config %s\n", fmt);
return 0;
}
/* Start the display thread... */
s = (struct state_hdsp *) malloc(sizeof(struct state_hdsp));
s->magic = HDSP_MAGIC;
s->frame_size = 0;
s->frame_buffer = 0;
s->sv = sv_open("");
if (s->sv == NULL) {
debug_msg("Cannot open HDTV display device\n");
return NULL;
}
res = sv_videomode(s->sv, s->hd_video_mode | SV_MODE_AUDIO_NOAUDIO);
if (res != SV_OK) {
debug_msg("Cannot set videomode %s\n", sv_geterrortext(res));
return NULL;
}
res = sv_sync_output(s->sv, SV_SYNCOUT_BILEVEL);
if (res != SV_OK) {
debug_msg("Cannot enable sync-on-green %s\n", sv_geterrortext(res));
return NULL;
}
res = sv_fifo_init(s->sv, &s->fifo, 0, 1, 1, 0, 0);
if (res != SV_OK) {
debug_msg("Cannot initialize video display FIFO %s\n", sv_geterrortext(res));
return NULL;
}
res = sv_fifo_start(s->sv, s->fifo);
if (res != SV_OK) {
debug_msg("Cannot start video display FIFO %s\n", sv_geterrortext(res));
return NULL;
}
pthread_mutex_init(&s->lock, NULL);
pthread_cond_init(&s->boss_cv, NULL);
pthread_cond_init(&s->worker_cv, NULL);
s->work_to_do = FALSE;
s->boss_waiting = FALSE;
s->worker_waiting = FALSE;
s->display_buffer = NULL;
s->bufs[0] = malloc(hd_size_x * hd_size_y * s->bpp);
s->bufs[1] = malloc(hd_size_x * hd_size_y * s->bpp);
s->bufs_index = 0;
memset(s->bufs[0], 0, hd_size_x * hd_size_y * s->bpp);
memset(s->bufs[1], 0, hd_size_x * hd_size_y * s->bpp);
if (pthread_create(&(s->thread_id), NULL, display_thread_hd, (void *) s) != 0) {
perror("Unable to create display thread\n");
return NULL;
}
return (void *) s;
return NULL;
}
void
display_hdstation_done(void *state)
char *display_hdstation_getf(void *state)
{
struct state_hdsp *s = (struct state_hdsp *) state;
struct state_hdsp *s = (struct state_hdsp *)state;
int res;
sv_fifo_free(s->sv, s->fifo);
sv_close(s->sv);
free(s);
assert(s->magic == HDSP_MAGIC);
/* Prepare the new RTP buffer... */
res =
sv_fifo_getbuffer(s->sv, s->fifo, &s->fifo_buffer, NULL,
SV_FIFO_FLAG_VIDEOONLY | SV_FIFO_FLAG_FLUSH);
if (res != SV_OK) {
debug_msg("Error %s\n", sv_geterrortext(res));
return NULL;
}
s->bufs_index = (s->bufs_index + 1) % 2;
s->frame_buffer = s->bufs[s->bufs_index];
s->frame_size = hd_size_x * hd_size_y * s->bpp;
s->fifo_buffer->dma.addr = s->frame_buffer;
s->fifo_buffer->dma.size = s->frame_size;
return s->frame_buffer;
}
display_colour_t
display_hdstation_colour(void *state)
int display_hdstation_putf(void *state, char *frame)
{
struct state_hdsp *s = (struct state_hdsp *) state;
struct state_hdsp *s = (struct state_hdsp *)state;
assert(s->magic == HDSP_MAGIC);
UNUSED(frame);
return DC_YUV;
assert(s->magic == HDSP_MAGIC);
pthread_mutex_lock(&s->lock);
/* Wait for the worker to finish... */
while (s->work_to_do) {
s->boss_waiting = TRUE;
pthread_cond_wait(&s->boss_cv, &s->lock);
s->boss_waiting = FALSE;
}
/* ...and give it more to do... */
s->tmp_buffer = s->fifo_buffer;
s->fifo_buffer = NULL;
s->work_to_do = TRUE;
/* ...and signal the worker */
if (s->worker_waiting) {
pthread_cond_signal(&s->worker_cv);
}
pthread_mutex_unlock(&s->lock);
return TRUE;
}
display_type_t *
display_hdstation_probe(void)
void *display_hdstation_init(char *fmt)
{
display_type_t *dtype;
display_format_t *dformat;
sv_handle *sv;
/* Probe the hardware... */
sv = sv_open("");
if (sv == NULL) {
debug_msg("Cannot probe HDTV display device\n");
return NULL;
}
sv_close(sv);
struct state_hdsp *s;
int fps;
int i;
int res;
dformat = malloc(sizeof(display_format_t));
if (dformat == NULL) {
return NULL;
}
dformat->size = DS_1920x1080;
dformat->colour_mode = DC_YUV;
dformat->num_images = 1;
if (fmt != NULL) {
if (strcmp(fmt, "help") == 0) {
printf("hdstation options:\n");
printf("\tfps:codec\n");
dtype = malloc(sizeof(display_type_t));
if (dtype != NULL) {
dtype->id = DISPLAY_HDSTATION_ID;
dtype->name = "hdtv";
dtype->description = "DVS HDstation (1080i/60 YUV 4:2:2)";
dtype->formats = dformat;
dtype->num_formats = 1;
}
return dtype;
return 0;
}
char *tmp;
tmp = strtok(fmt, ":");
if (!tmp) {
fprintf(stderr, "Wrong config %s\n", fmt);
return 0;
}
fps = atoi(tmp);
tmp = strtok(NULL, ":");
if (!tmp) {
fprintf(stderr, "Wrong config %s\n", fmt);
return 0;
}
s->codec = 0xffffffff;
for (i = 0; codec_info[i].name != NULL; i++) {
if (strcmp(tmp, codec_info[i].name) == 0) {
s->codec = codec_info[i].codec;
s->bpp = codec_info[i].bpp;
}
}
if (s->codec == 0xffffffff) {
fprintf(stderr, "hdstation: unknown codec: %s\n", tmp);
free(s);
free(tmp);
return 0;
}
}
s->hd_video_mode = SV_MODE_COLOR_YUV422 | SV_MODE_ACTIVE_STREAMER;
if (s->codec == DVS10) {
s->hd_video_mode |= SV_MODE_NBIT_10BDVS;
}
if (fps == 25) {
s->hd_video_mode |= SV_MODE_SMPTE274_25P;
} else if (fps == 29) {
s->hd_video_mode |= SV_MODE_SMPTE274_29I;
} else {
fprintf(stderr, "Wrong framerate in config %s\n", fmt);
return 0;
}
/* Start the display thread... */
s = (struct state_hdsp *)malloc(sizeof(struct state_hdsp));
s->magic = HDSP_MAGIC;
s->frame_size = 0;
s->frame_buffer = 0;
s->sv = sv_open("");
if (s->sv == NULL) {
debug_msg("Cannot open HDTV display device\n");
return NULL;
}
res = sv_videomode(s->sv, s->hd_video_mode | SV_MODE_AUDIO_NOAUDIO);
if (res != SV_OK) {
debug_msg("Cannot set videomode %s\n", sv_geterrortext(res));
return NULL;
}
res = sv_sync_output(s->sv, SV_SYNCOUT_BILEVEL);
if (res != SV_OK) {
debug_msg("Cannot enable sync-on-green %s\n",
sv_geterrortext(res));
return NULL;
}
res = sv_fifo_init(s->sv, &s->fifo, 0, 1, 1, 0, 0);
if (res != SV_OK) {
debug_msg("Cannot initialize video display FIFO %s\n",
sv_geterrortext(res));
return NULL;
}
res = sv_fifo_start(s->sv, s->fifo);
if (res != SV_OK) {
debug_msg("Cannot start video display FIFO %s\n",
sv_geterrortext(res));
return NULL;
}
pthread_mutex_init(&s->lock, NULL);
pthread_cond_init(&s->boss_cv, NULL);
pthread_cond_init(&s->worker_cv, NULL);
s->work_to_do = FALSE;
s->boss_waiting = FALSE;
s->worker_waiting = FALSE;
s->display_buffer = NULL;
s->bufs[0] = malloc(hd_size_x * hd_size_y * s->bpp);
s->bufs[1] = malloc(hd_size_x * hd_size_y * s->bpp);
s->bufs_index = 0;
memset(s->bufs[0], 0, hd_size_x * hd_size_y * s->bpp);
memset(s->bufs[1], 0, hd_size_x * hd_size_y * s->bpp);
if (pthread_create(&(s->thread_id), NULL, display_thread_hd, (void *)s)
!= 0) {
perror("Unable to create display thread\n");
return NULL;
}
return (void *)s;
}
#endif /* HAVE_HDSTATION */
void display_hdstation_done(void *state)
{
struct state_hdsp *s = (struct state_hdsp *)state;
sv_fifo_free(s->sv, s->fifo);
sv_close(s->sv);
free(s);
}
display_colour_t display_hdstation_colour(void *state)
{
struct state_hdsp *s = (struct state_hdsp *)state;
assert(s->magic == HDSP_MAGIC);
return DC_YUV;
}
display_type_t *display_hdstation_probe(void)
{
display_type_t *dtype;
display_format_t *dformat;
sv_handle *sv;
/* Probe the hardware... */
sv = sv_open("");
if (sv == NULL) {
debug_msg("Cannot probe HDTV display device\n");
return NULL;
}
sv_close(sv);
dformat = malloc(sizeof(display_format_t));
if (dformat == NULL) {
return NULL;
}
dformat->size = DS_1920x1080;
dformat->colour_mode = DC_YUV;
dformat->num_images = 1;
dtype = malloc(sizeof(display_type_t));
if (dtype != NULL) {
dtype->id = DISPLAY_HDSTATION_ID;
dtype->name = "hdtv";
dtype->description = "DVS HDstation (1080i/60 YUV 4:2:2)";
dtype->formats = dformat;
dtype->num_formats = 1;
}
return dtype;
}
#endif /* HAVE_HDSTATION */

View File

@@ -53,76 +53,69 @@
#define MAGIC_NULL 0x17bad83f
struct state_null {
uint32_t magic;
uint32_t magic;
};
void *
display_null_init(void)
void *display_null_init(void)
{
struct state_null *s;
struct state_null *s;
s = (struct state_null *) malloc(sizeof(struct state_null));
if (s != NULL) {
s->magic = MAGIC_NULL;
}
return s;
s = (struct state_null *)malloc(sizeof(struct state_null));
if (s != NULL) {
s->magic = MAGIC_NULL;
}
return s;
}
void
display_null_done(void *state)
void display_null_done(void *state)
{
struct state_null *s = (struct state_null *) state;
assert(s->magic == MAGIC_NULL);
free(s);
struct state_null *s = (struct state_null *)state;
assert(s->magic == MAGIC_NULL);
free(s);
}
char *
display_null_getf(void *state)
char *display_null_getf(void *state)
{
struct state_null *s = (struct state_null *) state;
assert(s->magic == MAGIC_NULL);
return NULL;
struct state_null *s = (struct state_null *)state;
assert(s->magic == MAGIC_NULL);
return NULL;
}
int
display_null_putf(void *state, char *frame)
int display_null_putf(void *state, char *frame)
{
struct state_null *s = (struct state_null *) state;
assert(s->magic == MAGIC_NULL);
UNUSED(frame);
return 0;
struct state_null *s = (struct state_null *)state;
assert(s->magic == MAGIC_NULL);
UNUSED(frame);
return 0;
}
display_colour_t
display_null_colour(void *state)
display_colour_t display_null_colour(void *state)
{
struct state_null *s = (struct state_null *) state;
assert(s->magic == MAGIC_NULL);
return DC_NONE;
struct state_null *s = (struct state_null *)state;
assert(s->magic == MAGIC_NULL);
return DC_NONE;
}
display_type_t *
display_null_probe(void)
display_type_t *display_null_probe(void)
{
display_type_t *dt;
display_format_t *df;
display_type_t *dt;
display_format_t *df;
df = malloc(sizeof(display_format_t));
if (df == NULL) {
return NULL;
}
df->size = DS_NONE;
df->colour_mode = DC_NONE;
df->num_images = 0;
df = malloc(sizeof(display_format_t));
if (df == NULL) {
return NULL;
}
df->size = DS_NONE;
df->colour_mode = DC_NONE;
df->num_images = 0;
dt = malloc(sizeof(display_type_t));
if (dt != NULL) {
dt->id = DISPLAY_NULL_ID;
dt->name = "none";
dt->description = "No display device";
dt->formats = df;
dt->num_formats = 1;
}
return dt;
dt = malloc(sizeof(display_type_t));
if (dt != NULL) {
dt->id = DISPLAY_NULL_ID;
dt->name = "none";
dt->description = "No display device";
dt->formats = df;
dt->num_formats = 1;
}
return dt;
}

View File

@@ -68,503 +68,534 @@
#define MAGIC_QT_DISPLAY DISPLAY_QUICKTIME_ID
struct state_quicktime {
ComponentInstance videoDisplayComponentInstance;
// Component videoDisplayComponent;
GWorldPtr gworld;
ImageSequence seqID;
ComponentInstance videoDisplayComponentInstance;
// Component videoDisplayComponent;
GWorldPtr gworld;
ImageSequence seqID;
char *buffers[2];
char *outBuffer;
int image_display, image_network;
char *buffers[2];
char *outBuffer;
int image_display, image_network;
int device;
int mode;
char *codec;
const struct codec_info_t *cinfo;
int width;
int height;
int device;
int mode;
char *codec;
const struct codec_info_t *cinfo;
int width;
int height;
/* Thread related information follows... */
pthread_t thread_id;
sem_t semaphore;
pthread_t thread_id;
sem_t semaphore;
uint32_t magic;
uint32_t magic;
};
/* Prototyping */
char * four_char_decode(int format);
char *four_char_decode(int format);
void nprintf(char *str);
char * four_char_decode(int format)
char *four_char_decode(int format)
{
static char fbuf0[32];
static char fbuf1[32];
static int count = 0;
char *fbuf;
static char fbuf0[32];
static char fbuf1[32];
static int count = 0;
char *fbuf;
if (count & 1)
fbuf = fbuf1;
else
fbuf = fbuf0;
count++;
if (count & 1)
fbuf = fbuf1;
else
fbuf = fbuf0;
count++;
if ((unsigned)format < 64)
sprintf(fbuf, "%d", format);
else {
fbuf[0] = (char)(format >> 24);
fbuf[1] = (char)(format >> 16);
fbuf[2] = (char)(format >> 8);
fbuf[3] = (char)(format >> 0);
}
return fbuf;
}
static void*
display_thread_quicktime(void *arg)
{
struct state_quicktime *s = (struct state_quicktime *) arg;
ImageDescriptionHandle imageDesc;
CodecFlags ignore;
int ret;
char *line1, *line2;
int frames = 0;
struct timeval t, t0;
imageDesc = (ImageDescriptionHandle)NewHandle(sizeof(ImageDescription));
platform_sem_wait(&s->semaphore);
(**(ImageDescriptionHandle)imageDesc).idSize = sizeof(ImageDescription);
(**(ImageDescriptionHandle)imageDesc).cType = s->cinfo->fcc;
(**(ImageDescriptionHandle)imageDesc).dataSize = hd_size_x * hd_size_y * s->cinfo->bpp; // dataSize is specified in bytes and is specified as height*width*bytes_per_luma_instant. v210 sets bytes_per_luma_instant to 8/3. See http://developer.apple.com/quicktime/icefloe/dispatch019.html#v210
//(**(ImageDescriptionHandle)imageDesc).cType = '2Vuy'; // QuickTime specifies '2vuy' codec, however Kona3 reports it as '2Vuy'
//(**(ImageDescriptionHandle)imageDesc).hRes = 72; // not used actually. Set to 72. See http://developer.apple.com/quicktime/icefloe/dispatch019.html#imagedesc
//(**(ImageDescriptionHandle)imageDesc).vRes = 72; // not used actually. Set to 72. See http://developer.apple.com/quicktime/icefloe/dispatch019.html#imagedesc
(**(ImageDescriptionHandle)imageDesc).width = s->width; // Beware: must be a multiple of horiz_align_pixels which is 2 for 2Vuy and 48 for v210. hd_size_x=1920 is a multiple of both. TODO: needs further investigation for 2K!
(**(ImageDescriptionHandle)imageDesc).height = s->height;
//(**(ImageDescriptionHandle)imageDesc).frameCount = 0;
//(**(ImageDescriptionHandle)imageDesc).depth = 24; // Given by the cType. See http://developer.apple.com/quicktime/icefloe/dispatch019.html
//(**(ImageDescriptionHandle)imageDesc).clutID = -1; // We dont use any custom color table
ret = DecompressSequenceBeginS(&(s->seqID),
imageDesc,
s->buffers[s->image_display],
hd_size_x * hd_size_y * s->cinfo->bpp, // Size of the buffer, not size of the actual frame data inside
s->gworld,
NULL,
NULL,
NULL,
srcCopy,
NULL,
(CodecFlags)NULL,
codecNormalQuality,
bestSpeedCodec);
if (ret != noErr) {
fprintf(stderr, "Failed DecompressSequenceBeginS\n");
}
DisposeHandle((Handle)imageDesc);
//ICMFrameTimeRecord frameTime = {{0}};
//TimeBase timeBase;
//timeBase = NewTimeBase();
//SetTimeBaseRate(timeBase, 0);
/* TODO frametime probably not needed */
//memset(&frameTime, 0, sizeof(ICMFrameTimeRecord));
//frameTime.recordSize = sizeof(frameTime);
//frameTime.scale = 1000; // Units per second
//frameTime.base = timeBase; // Specifying a timeBase means that DecompressSequenceFrameWhen must run asynchronously
//frameTime.duration = 30; // Duration of one frame specified accordingly to the scale specified above
//frameTime.frameNumber = 0; // We don't know the frame number
//frameTime.flags = icmFrameTimeDecodeImmediately;
while (1) {
platform_sem_wait(&s->semaphore);
line1 = s->buffers[s->image_display];
line2 = s->outBuffer;
memcpy(line2, line1, hd_size_x*hd_size_y*s->cinfo->bpp);
/* TODO: Running DecompressSequenceFrameWhen asynchronously in this way introduces a possible race condition! */
ret = DecompressSequenceFrameWhen(s->seqID,
s->outBuffer,
hd_size_x * hd_size_y * s->cinfo->bpp, // Size of the buffer, not size of the actual frame data inside
0,
&ignore,
-1, // If you set asyncCompletionProc to -1, the operation is performed asynchronously but the decompressor does not call the completion function.
NULL);
//&frameTime);
if (ret != noErr) {
fprintf(stderr, "Failed DecompressSequenceFrameWhen: %d\n", ret);
}
frames++;
gettimeofday(&t, NULL);
double seconds = tv_diff(t, t0);
if (seconds >= 5) {
float fps = frames / seconds;
fprintf(stderr, "%d frames in %g seconds = %g FPS\n", frames, seconds, fps);
t0 = t;
frames = 0;
}
}
return NULL;
}
char *
display_quicktime_getf(void *state)
{
struct state_quicktime *s = (struct state_quicktime *) state;
assert(s->magic == MAGIC_QT_DISPLAY);
return (char *)s->buffers[s->image_network];
}
int
display_quicktime_putf(void *state, char *frame)
{
int tmp;
struct state_quicktime *s = (struct state_quicktime *) state;
UNUSED(frame);
assert(s->magic == MAGIC_QT_DISPLAY);
/* ...and give it more to do... */
tmp = s->image_display;
s->image_display = s->image_network;
s->image_network = tmp;
/* ...and signal the worker */
platform_sem_post(&s->semaphore);
return 0;
}
static void
print_modes(int fullhelp)
{
ComponentDescription cd;
Component c = 0;
cd.componentType = QTVideoOutputComponentType;
cd.componentSubType = 0;
cd.componentManufacturer = 0;
cd.componentFlags = 0;
cd.componentFlagsMask = kQTVideoOutputDontDisplayToUser;
//fprintf(stdout, "Number of Quicktime Vido Display components %d\n", CountComponents (&cd));
fprintf(stdout, "Available playback devices:\n");
/* Print relevant video output components */
while ((c = FindNextComponent(c, &cd))) {
Handle componentNameHandle = NewHandle(0);
GetComponentInfo(c, &cd, componentNameHandle, NULL, NULL);
HLock(componentNameHandle);
char *cName = *componentNameHandle;
fprintf(stdout, " Device %d: ", (int)c);
nprintf(cName);
fprintf(stdout, "\n");
HUnlock(componentNameHandle);
DisposeHandle(componentNameHandle);
/* Get display modes of selected video output component */
QTAtomContainer modeListAtomContainer = NULL;
ComponentInstance videoDisplayComponentInstance;
videoDisplayComponentInstance = OpenComponent(c);
int ret = QTVideoOutputGetDisplayModeList(videoDisplayComponentInstance, &modeListAtomContainer);
if (ret != noErr || modeListAtomContainer == NULL) {
fprintf(stdout, "\tNo output modes available\n");
CloseComponent(videoDisplayComponentInstance);
continue;
if ((unsigned)format < 64)
sprintf(fbuf, "%d", format);
else {
fbuf[0] = (char)(format >> 24);
fbuf[1] = (char)(format >> 16);
fbuf[2] = (char)(format >> 8);
fbuf[3] = (char)(format >> 0);
}
return fbuf;
}
int i = 1;
QTAtom atomDisplay = 0, nextAtomDisplay = 0;
QTAtomType type;
QTAtomID id;
static void *display_thread_quicktime(void *arg)
{
struct state_quicktime *s = (struct state_quicktime *)arg;
/* Print modes of current display component */
while (i < QTCountChildrenOfType(modeListAtomContainer, kParentAtomIsContainer, kQTVODisplayModeItem)) {
ImageDescriptionHandle imageDesc;
CodecFlags ignore;
int ret;
ret = QTNextChildAnyType(modeListAtomContainer, kParentAtomIsContainer, atomDisplay, &nextAtomDisplay);
// Make sure its a display atom
ret = QTGetAtomTypeAndID(modeListAtomContainer, nextAtomDisplay, &type, &id);
if (type != kQTVODisplayModeItem) continue;
char *line1, *line2;
atomDisplay = nextAtomDisplay;
int frames = 0;
struct timeval t, t0;
QTAtom atom;
long dataSize, *dataPtr;
imageDesc =
(ImageDescriptionHandle) NewHandle(sizeof(ImageDescription));
/* Print component ID */
fprintf(stdout, "\t - %ld: ", id);
platform_sem_wait(&s->semaphore);
/* Print component name */
atom = QTFindChildByID(modeListAtomContainer, atomDisplay, kQTVOName, 1, NULL);
ret = QTGetAtomDataPtr(modeListAtomContainer, atom, &dataSize, (Ptr*)&dataPtr);
fprintf(stdout, " %s; ", (char *)dataPtr);
(**(ImageDescriptionHandle) imageDesc).idSize =
sizeof(ImageDescription);
(**(ImageDescriptionHandle) imageDesc).cType = s->cinfo->fcc;
(**(ImageDescriptionHandle) imageDesc).dataSize = hd_size_x * hd_size_y * s->cinfo->bpp; // dataSize is specified in bytes and is specified as height*width*bytes_per_luma_instant. v210 sets bytes_per_luma_instant to 8/3. See http://developer.apple.com/quicktime/icefloe/dispatch019.html#v210
//(**(ImageDescriptionHandle)imageDesc).cType = '2Vuy'; // QuickTime specifies '2vuy' codec, however Kona3 reports it as '2Vuy'
//(**(ImageDescriptionHandle)imageDesc).hRes = 72; // not used actually. Set to 72. See http://developer.apple.com/quicktime/icefloe/dispatch019.html#imagedesc
//(**(ImageDescriptionHandle)imageDesc).vRes = 72; // not used actually. Set to 72. See http://developer.apple.com/quicktime/icefloe/dispatch019.html#imagedesc
(**(ImageDescriptionHandle) imageDesc).width = s->width; // Beware: must be a multiple of horiz_align_pixels which is 2 for 2Vuy and 48 for v210. hd_size_x=1920 is a multiple of both. TODO: needs further investigation for 2K!
(**(ImageDescriptionHandle) imageDesc).height = s->height;
//(**(ImageDescriptionHandle)imageDesc).frameCount = 0;
//(**(ImageDescriptionHandle)imageDesc).depth = 24; // Given by the cType. See http://developer.apple.com/quicktime/icefloe/dispatch019.html
//(**(ImageDescriptionHandle)imageDesc).clutID = -1; // We dont use any custom color table
//if (strcmp((char *)dataPtr, mode) == 0) {
// displayMode = id;
//}
ret = DecompressSequenceBeginS(&(s->seqID), imageDesc, s->buffers[s->image_display], hd_size_x * hd_size_y * s->cinfo->bpp, // Size of the buffer, not size of the actual frame data inside
s->gworld,
NULL,
NULL,
NULL,
srcCopy,
NULL,
(CodecFlags) NULL,
codecNormalQuality, bestSpeedCodec);
if (ret != noErr) {
fprintf(stderr, "Failed DecompressSequenceBeginS\n");
}
DisposeHandle((Handle) imageDesc);
/* Print component other info */
atom = QTFindChildByID(modeListAtomContainer, atomDisplay, kQTVODimensions, 1, NULL);
ret = QTGetAtomDataPtr(modeListAtomContainer, atom, &dataSize, (Ptr *)&dataPtr);
fprintf(stdout, "%dx%d px\n", (int)EndianS32_BtoN(dataPtr[0]), (int)EndianS32_BtoN(dataPtr[1]));
//ICMFrameTimeRecord frameTime = {{0}};
//TimeBase timeBase;
/* Do not print codecs */
if (!fullhelp) {
i++;
continue;
}
//timeBase = NewTimeBase();
//SetTimeBaseRate(timeBase, 0);
/* Print supported pixel formats */
fprintf(stdout, "\t\t - Codec: ");
QTAtom decompressorsAtom;
int j = 1;
int codecsPerLine = 0;
while ((decompressorsAtom = QTFindChildByIndex(modeListAtomContainer, atomDisplay, kQTVODecompressors, j, NULL)) != 0) {
atom = QTFindChildByID(modeListAtomContainer, decompressorsAtom, kQTVODecompressorType, 1, NULL);
ret = QTGetAtomDataPtr(modeListAtomContainer, atom, &dataSize, (Ptr *)&dataPtr);
if (!(codecsPerLine % 9)) {
fprintf(stdout, "\n \t\t\t");
fprintf(stdout, "%s", (char *)dataPtr);
} else {
fprintf(stdout, ", %s", (char *)dataPtr);
/* TODO frametime probably not needed */
//memset(&frameTime, 0, sizeof(ICMFrameTimeRecord));
//frameTime.recordSize = sizeof(frameTime);
//frameTime.scale = 1000; // Units per second
//frameTime.base = timeBase; // Specifying a timeBase means that DecompressSequenceFrameWhen must run asynchronously
//frameTime.duration = 30; // Duration of one frame specified accordingly to the scale specified above
//frameTime.frameNumber = 0; // We don't know the frame number
//frameTime.flags = icmFrameTimeDecodeImmediately;
while (1) {
platform_sem_wait(&s->semaphore);
line1 = s->buffers[s->image_display];
line2 = s->outBuffer;
memcpy(line2, line1, hd_size_x * hd_size_y * s->cinfo->bpp);
/* TODO: Running DecompressSequenceFrameWhen asynchronously in this way introduces a possible race condition! */
ret = DecompressSequenceFrameWhen(s->seqID, s->outBuffer, hd_size_x * hd_size_y * s->cinfo->bpp, // Size of the buffer, not size of the actual frame data inside
0, &ignore, -1, // If you set asyncCompletionProc to -1, the operation is performed asynchronously but the decompressor does not call the completion function.
NULL);
//&frameTime);
if (ret != noErr) {
fprintf(stderr,
"Failed DecompressSequenceFrameWhen: %d\n",
ret);
}
codecsPerLine++;
//atom = QTFindChildByID(modeListAtomContainer, decompressorsAtom, kQTVODecompressorComponent, 1, NULL);
//ret = QTGetAtomDataPtr(modeListAtomContainer, atom, &dataSize, (Ptr *)&dataPtr);
//fprintf(stdout, "%s\n", (char *)dataPtr);
j++;
}
fprintf(stdout, "\n\n");
i++;
CloseComponent(videoDisplayComponentInstance);
}
fprintf(stdout, "\n");
cd.componentType = QTVideoOutputComponentType;
cd.componentSubType = 0;
cd.componentManufacturer = 0;
cd.componentFlags = 0;
cd.componentFlagsMask = kQTVideoOutputDontDisplayToUser;
}
}
static void
show_help(int full)
{
printf("Quicktime output options:\n");
printf("\tdevice:mode:codec | help | fullhelp\n");
print_modes(full);
}
void *
display_quicktime_init(char *fmt)
{
struct state_quicktime *s;
int ret;
int i;
/* Parse fmt input */
s = (struct state_quicktime *) malloc(sizeof(struct state_quicktime));
s->magic = MAGIC_QT_DISPLAY;
if(fmt!=NULL) {
if(strcmp(fmt, "help") == 0) {
show_help(0);
free(s);
return NULL;
frames++;
gettimeofday(&t, NULL);
double seconds = tv_diff(t, t0);
if (seconds >= 5) {
float fps = frames / seconds;
fprintf(stderr, "%d frames in %g seconds = %g FPS\n",
frames, seconds, fps);
t0 = t;
frames = 0;
}
}
if(strcmp(fmt, "fullhelp") == 0) {
show_help(1);
free(s);
return NULL;
}
char *tmp = strdup(fmt);
char *tok;
tok = strtok(tmp, ":");
if(tok == NULL) {
show_help(0);
free(s);
free(tmp);
return NULL;
}
s->device = atol(tok);
tok = strtok(NULL, ":");
if(tok == NULL) {
show_help(0);
free(s);
free(tmp);
return NULL;
}
s->mode = atol(tok);
tok = strtok(NULL, ":");
if(tok == NULL) {
show_help(0);
free(s);
free(tmp);
return NULL;
}
s->codec = strdup(tok);
}
for(i = 0; codec_info[i].name != NULL; i++) {
if(strcmp(s->codec, codec_info[i].name) == 0) {
s->cinfo = &codec_info[i];
}
}
s->videoDisplayComponentInstance = 0;
s->seqID = 0;
/* Open device */
s->videoDisplayComponentInstance = OpenComponent((Component)s->device);
InitCursor();
EnterMovies();
/* Set the display mode */
ret = QTVideoOutputSetDisplayMode(s->videoDisplayComponentInstance, s->mode);
if (ret != noErr) {
fprintf(stderr, "Failed to set video output display mode.\n");
return NULL;
}
/* We don't want to use the video output component instance echo port*/
ret = QTVideoOutputSetEchoPort(s->videoDisplayComponentInstance, nil);
if (ret != noErr) {
fprintf(stderr, "Failed to set video output echo port.\n");
return NULL;
}
/* Register Ultragrid with instande of the video outpiut */
ret = QTVideoOutputSetClientName(s->videoDisplayComponentInstance, (ConstStr255Param)"Ultragrid");
if (ret != noErr) {
fprintf(stderr, "Failed to register Ultragrid with selected video output instance.\n");
return NULL;
}
/* Call QTVideoOutputBegin to gain exclusive access to the video output */
ret = QTVideoOutputBegin(s->videoDisplayComponentInstance);
if (ret != noErr) {
fprintf(stderr, "Failed to get exclusive access to selected video output instance.\n");
return NULL;
}
/* Get a pointer to the gworld used by video output component */
ret = QTVideoOutputGetGWorld(s->videoDisplayComponentInstance, &s->gworld);
if (ret != noErr) {
fprintf(stderr, "Failed to get selected video output instance GWorld.\n");
return NULL;
}
ImageDescriptionHandle gWorldImgDesc = NULL;
PixMapHandle gWorldPixmap = (PixMapHandle)GetGWorldPixMap(s->gworld);
/* Determine width and height */
ret = MakeImageDescriptionForPixMap(gWorldPixmap, &gWorldImgDesc);
if (ret != noErr) {
fprintf(stderr, "Failed to determine width and height.\n");
return NULL;
}
hd_size_x = s->width = (**gWorldImgDesc).width;
hd_size_y = s->height = (**gWorldImgDesc).height;
if (s->cinfo->h_align) {
hd_size_x = ((hd_size_x + s->cinfo->h_align -1) / s->cinfo->h_align) * s->cinfo->h_align;
}
fprintf(stdout, "Selected mode: %d(%d)x%d, %fbpp\n", s->width, hd_size_x, hd_size_y, s->cinfo->bpp);
platform_sem_init(&s->semaphore, 0, 0);
s->buffers[0] = malloc(hd_size_x*hd_size_y*s->cinfo->bpp);
s->buffers[1] = malloc(hd_size_x*hd_size_y*s->cinfo->bpp);
s->image_network = 0;
s->image_display = 1;
s->outBuffer = malloc(hd_size_x*hd_size_y*s->cinfo->bpp);
if (pthread_create(&(s->thread_id), NULL, display_thread_quicktime, (void *) s) != 0) {
perror("Unable to create display thread\n");
return NULL;
}
return (void *) s;
}
void
display_quicktime_done(void *state)
char *display_quicktime_getf(void *state)
{
struct state_quicktime *s = (struct state_quicktime *) state;
int ret;
assert(s->magic == MAGIC_QT_DISPLAY);
ret = QTVideoOutputEnd(s->videoDisplayComponentInstance);
if (ret != noErr) {
fprintf(stderr, "Failed to release the video output component.\n");
}
ret = CloseComponent(s->videoDisplayComponentInstance);
if (ret != noErr) {
fprintf(stderr, "Failed to close the video output component.\n");
}
DisposeGWorld(s->gworld);
struct state_quicktime *s = (struct state_quicktime *)state;
assert(s->magic == MAGIC_QT_DISPLAY);
return (char *)s->buffers[s->image_network];
}
display_colour_t
display_quicktime_colour(void *state)
int display_quicktime_putf(void *state, char *frame)
{
struct state_quicktime *s = (struct state_quicktime *) state;
assert(s->magic == MAGIC_QT_DISPLAY);
return DC_YUV;
int tmp;
struct state_quicktime *s = (struct state_quicktime *)state;
UNUSED(frame);
assert(s->magic == MAGIC_QT_DISPLAY);
/* ...and give it more to do... */
tmp = s->image_display;
s->image_display = s->image_network;
s->image_network = tmp;
/* ...and signal the worker */
platform_sem_post(&s->semaphore);
return 0;
}
display_type_t *
display_quicktime_probe(void)
static void print_modes(int fullhelp)
{
display_type_t *dtype;
display_format_t *dformat;
ComponentDescription cd;
Component c = 0;
dformat = malloc(sizeof(display_format_t));
if (dformat == NULL) {
return NULL;
}
dformat->size = DS_1920x1080;
dformat->colour_mode = DC_YUV;
dformat->num_images = 1;
cd.componentType = QTVideoOutputComponentType;
cd.componentSubType = 0;
cd.componentManufacturer = 0;
cd.componentFlags = 0;
cd.componentFlagsMask = kQTVideoOutputDontDisplayToUser;
dtype = malloc(sizeof(display_type_t));
if (dtype != NULL) {
dtype->id = DISPLAY_QUICKTIME_ID;
dtype->name = "quicktime";
dtype->description = "QuickTime display device";
dtype->formats = dformat;
dtype->num_formats = 1;
}
return dtype;
//fprintf(stdout, "Number of Quicktime Vido Display components %d\n", CountComponents (&cd));
fprintf(stdout, "Available playback devices:\n");
/* Print relevant video output components */
while ((c = FindNextComponent(c, &cd))) {
Handle componentNameHandle = NewHandle(0);
GetComponentInfo(c, &cd, componentNameHandle, NULL, NULL);
HLock(componentNameHandle);
char *cName = *componentNameHandle;
fprintf(stdout, " Device %d: ", (int)c);
nprintf(cName);
fprintf(stdout, "\n");
HUnlock(componentNameHandle);
DisposeHandle(componentNameHandle);
/* Get display modes of selected video output component */
QTAtomContainer modeListAtomContainer = NULL;
ComponentInstance videoDisplayComponentInstance;
videoDisplayComponentInstance = OpenComponent(c);
int ret =
QTVideoOutputGetDisplayModeList
(videoDisplayComponentInstance, &modeListAtomContainer);
if (ret != noErr || modeListAtomContainer == NULL) {
fprintf(stdout, "\tNo output modes available\n");
CloseComponent(videoDisplayComponentInstance);
continue;
}
int i = 1;
QTAtom atomDisplay = 0, nextAtomDisplay = 0;
QTAtomType type;
QTAtomID id;
/* Print modes of current display component */
while (i <
QTCountChildrenOfType(modeListAtomContainer,
kParentAtomIsContainer,
kQTVODisplayModeItem)) {
ret =
QTNextChildAnyType(modeListAtomContainer,
kParentAtomIsContainer,
atomDisplay, &nextAtomDisplay);
// Make sure its a display atom
ret =
QTGetAtomTypeAndID(modeListAtomContainer,
nextAtomDisplay, &type, &id);
if (type != kQTVODisplayModeItem)
continue;
atomDisplay = nextAtomDisplay;
QTAtom atom;
long dataSize, *dataPtr;
/* Print component ID */
fprintf(stdout, "\t - %ld: ", id);
/* Print component name */
atom =
QTFindChildByID(modeListAtomContainer, atomDisplay,
kQTVOName, 1, NULL);
ret =
QTGetAtomDataPtr(modeListAtomContainer, atom,
&dataSize, (Ptr *) & dataPtr);
fprintf(stdout, " %s; ", (char *)dataPtr);
//if (strcmp((char *)dataPtr, mode) == 0) {
// displayMode = id;
//}
/* Print component other info */
atom =
QTFindChildByID(modeListAtomContainer, atomDisplay,
kQTVODimensions, 1, NULL);
ret =
QTGetAtomDataPtr(modeListAtomContainer, atom,
&dataSize, (Ptr *) & dataPtr);
fprintf(stdout, "%dx%d px\n",
(int)EndianS32_BtoN(dataPtr[0]),
(int)EndianS32_BtoN(dataPtr[1]));
/* Do not print codecs */
if (!fullhelp) {
i++;
continue;
}
/* Print supported pixel formats */
fprintf(stdout, "\t\t - Codec: ");
QTAtom decompressorsAtom;
int j = 1;
int codecsPerLine = 0;
while ((decompressorsAtom =
QTFindChildByIndex(modeListAtomContainer,
atomDisplay,
kQTVODecompressors, j,
NULL)) != 0) {
atom =
QTFindChildByID(modeListAtomContainer,
decompressorsAtom,
kQTVODecompressorType, 1,
NULL);
ret =
QTGetAtomDataPtr(modeListAtomContainer,
atom, &dataSize,
(Ptr *) & dataPtr);
if (!(codecsPerLine % 9)) {
fprintf(stdout, "\n \t\t\t");
fprintf(stdout, "%s", (char *)dataPtr);
} else {
fprintf(stdout, ", %s",
(char *)dataPtr);
}
codecsPerLine++;
//atom = QTFindChildByID(modeListAtomContainer, decompressorsAtom, kQTVODecompressorComponent, 1, NULL);
//ret = QTGetAtomDataPtr(modeListAtomContainer, atom, &dataSize, (Ptr *)&dataPtr);
//fprintf(stdout, "%s\n", (char *)dataPtr);
j++;
}
fprintf(stdout, "\n\n");
i++;
CloseComponent(videoDisplayComponentInstance);
}
fprintf(stdout, "\n");
cd.componentType = QTVideoOutputComponentType;
cd.componentSubType = 0;
cd.componentManufacturer = 0;
cd.componentFlags = 0;
cd.componentFlagsMask = kQTVideoOutputDontDisplayToUser;
}
}
#endif /* HAVE_MACOSX */
static void show_help(int full)
{
printf("Quicktime output options:\n");
printf("\tdevice:mode:codec | help | fullhelp\n");
print_modes(full);
}
void *display_quicktime_init(char *fmt)
{
struct state_quicktime *s;
int ret;
int i;
/* Parse fmt input */
s = (struct state_quicktime *)malloc(sizeof(struct state_quicktime));
s->magic = MAGIC_QT_DISPLAY;
if (fmt != NULL) {
if (strcmp(fmt, "help") == 0) {
show_help(0);
free(s);
return NULL;
}
if (strcmp(fmt, "fullhelp") == 0) {
show_help(1);
free(s);
return NULL;
}
char *tmp = strdup(fmt);
char *tok;
tok = strtok(tmp, ":");
if (tok == NULL) {
show_help(0);
free(s);
free(tmp);
return NULL;
}
s->device = atol(tok);
tok = strtok(NULL, ":");
if (tok == NULL) {
show_help(0);
free(s);
free(tmp);
return NULL;
}
s->mode = atol(tok);
tok = strtok(NULL, ":");
if (tok == NULL) {
show_help(0);
free(s);
free(tmp);
return NULL;
}
s->codec = strdup(tok);
}
for (i = 0; codec_info[i].name != NULL; i++) {
if (strcmp(s->codec, codec_info[i].name) == 0) {
s->cinfo = &codec_info[i];
}
}
s->videoDisplayComponentInstance = 0;
s->seqID = 0;
/* Open device */
s->videoDisplayComponentInstance = OpenComponent((Component) s->device);
InitCursor();
EnterMovies();
/* Set the display mode */
ret =
QTVideoOutputSetDisplayMode(s->videoDisplayComponentInstance,
s->mode);
if (ret != noErr) {
fprintf(stderr, "Failed to set video output display mode.\n");
return NULL;
}
/* We don't want to use the video output component instance echo port */
ret = QTVideoOutputSetEchoPort(s->videoDisplayComponentInstance, nil);
if (ret != noErr) {
fprintf(stderr, "Failed to set video output echo port.\n");
return NULL;
}
/* Register Ultragrid with instande of the video outpiut */
ret =
QTVideoOutputSetClientName(s->videoDisplayComponentInstance,
(ConstStr255Param) "Ultragrid");
if (ret != noErr) {
fprintf(stderr,
"Failed to register Ultragrid with selected video output instance.\n");
return NULL;
}
/* Call QTVideoOutputBegin to gain exclusive access to the video output */
ret = QTVideoOutputBegin(s->videoDisplayComponentInstance);
if (ret != noErr) {
fprintf(stderr,
"Failed to get exclusive access to selected video output instance.\n");
return NULL;
}
/* Get a pointer to the gworld used by video output component */
ret =
QTVideoOutputGetGWorld(s->videoDisplayComponentInstance,
&s->gworld);
if (ret != noErr) {
fprintf(stderr,
"Failed to get selected video output instance GWorld.\n");
return NULL;
}
ImageDescriptionHandle gWorldImgDesc = NULL;
PixMapHandle gWorldPixmap = (PixMapHandle) GetGWorldPixMap(s->gworld);
/* Determine width and height */
ret = MakeImageDescriptionForPixMap(gWorldPixmap, &gWorldImgDesc);
if (ret != noErr) {
fprintf(stderr, "Failed to determine width and height.\n");
return NULL;
}
hd_size_x = s->width = (**gWorldImgDesc).width;
hd_size_y = s->height = (**gWorldImgDesc).height;
if (s->cinfo->h_align) {
hd_size_x =
((hd_size_x + s->cinfo->h_align -
1) / s->cinfo->h_align) * s->cinfo->h_align;
}
fprintf(stdout, "Selected mode: %d(%d)x%d, %fbpp\n", s->width,
hd_size_x, hd_size_y, s->cinfo->bpp);
platform_sem_init(&s->semaphore, 0, 0);
s->buffers[0] = malloc(hd_size_x * hd_size_y * s->cinfo->bpp);
s->buffers[1] = malloc(hd_size_x * hd_size_y * s->cinfo->bpp);
s->image_network = 0;
s->image_display = 1;
s->outBuffer = malloc(hd_size_x * hd_size_y * s->cinfo->bpp);
if (pthread_create
(&(s->thread_id), NULL, display_thread_quicktime, (void *)s) != 0) {
perror("Unable to create display thread\n");
return NULL;
}
return (void *)s;
}
void display_quicktime_done(void *state)
{
struct state_quicktime *s = (struct state_quicktime *)state;
int ret;
assert(s->magic == MAGIC_QT_DISPLAY);
ret = QTVideoOutputEnd(s->videoDisplayComponentInstance);
if (ret != noErr) {
fprintf(stderr,
"Failed to release the video output component.\n");
}
ret = CloseComponent(s->videoDisplayComponentInstance);
if (ret != noErr) {
fprintf(stderr,
"Failed to close the video output component.\n");
}
DisposeGWorld(s->gworld);
}
display_colour_t display_quicktime_colour(void *state)
{
struct state_quicktime *s = (struct state_quicktime *)state;
assert(s->magic == MAGIC_QT_DISPLAY);
return DC_YUV;
}
display_type_t *display_quicktime_probe(void)
{
display_type_t *dtype;
display_format_t *dformat;
dformat = malloc(sizeof(display_format_t));
if (dformat == NULL) {
return NULL;
}
dformat->size = DS_1920x1080;
dformat->colour_mode = DC_YUV;
dformat->num_images = 1;
dtype = malloc(sizeof(display_type_t));
if (dtype != NULL) {
dtype->id = DISPLAY_QUICKTIME_ID;
dtype->name = "quicktime";
dtype->description = "QuickTime display device";
dtype->formats = dformat;
dtype->num_formats = 1;
}
return dtype;
}
#endif /* HAVE_MACOSX */

View File

@@ -54,7 +54,6 @@
#include "video_display.h"
#include "video_display/sage.h"
#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glu.h>
@@ -75,17 +74,16 @@
#define HD_HEIGHT 1080
#define MAGIC_SAGE DISPLAY_SAGE_ID
struct state_sdl {
GLubyte *buffers[2];
GLubyte *outBuffer;
GLubyte *yuvBuffer;
int image_display, image_network;
/* Thread related information follows... */
pthread_t thread_id;
sem_t semaphore;
/* For debugging... */
uint32_t magic;
GLubyte *buffers[2];
GLubyte *outBuffer;
GLubyte *yuvBuffer;
int image_display, image_network;
/* Thread related information follows... */
pthread_t thread_id;
sem_t semaphore;
/* For debugging... */
uint32_t magic;
};
int *_0080;
@@ -93,24 +91,23 @@ int *_00ff;
//Cb = U, Cr = V
int *_YUV_Coef;
#define RED_v "0*16" //+ 1.596
#define GREEN_u "1*16" //- 0.391
#define GREEN_v "2*16" //- 0.813
#define BLUE_u "3*16" //+ 2.018
#define Y_COEF "4*16" //+ 1.164
#define RED_v "0*16" //+ 1.596
#define GREEN_u "1*16" //- 0.391
#define GREEN_v "2*16" //- 0.813
#define BLUE_u "3*16" //+ 2.018
#define Y_COEF "4*16" //+ 1.164
/** Prototyping */
inline void sage_copyline64(unsigned char *dst, unsigned char *src, int len);
inline void sage_copyline128(unsigned char *dst, unsigned char *src, int len);
inline void swapBytes(unsigned char *buf, int len);
void sage_deinterlace(unsigned char *buffer);
void sage_gl_resize_window(int width,int height);
void sage_gl_resize_window(int width, int height);
void yuv2rgba(unsigned char *buffer, unsigned char *rgbBuf);
int display_sage_handle_events(void)
{
return 0;
return 0;
}
/* TODO:
@@ -119,203 +116,169 @@ int display_sage_handle_events(void)
* vstup i vystup zarovnan na 16 bytu. */
void yuv2rgba(unsigned char *buffer, unsigned char *rgbBuf)
{
int i = 0;
int j = 0;
for (i = 0; i < HD_WIDTH*HD_HEIGHT*2; i+=32)
{
if (bitdepth == 8) {
j++; // interlace
if (j == 121) buffer += 2069760;
if (j == 241) { buffer -=2073600; j = 1; }
}
int i = 0;
int j = 0;
for (i = 0; i < HD_WIDTH * HD_HEIGHT * 2; i += 32) {
if (bitdepth == 8) {
j++; // interlace
if (j == 121)
buffer += 2069760;
if (j == 241) {
buffer -= 2073600;
j = 1;
}
}
asm (
"psubq %%xmm5, %%xmm5\n"
"movdqa (%0), %%xmm0\n" // U0 Y0 V0 Y1 U1 Y2 V1 Y3 U2 Y4 V2 Y5 U3 Y6 V3 Y7
"movdqa 16(%0), %%xmm1\n" // S0 X0 T0 X1 S1 X2 T1 X3 S2 X4 T2 X5 S3 X6 T3 X7
"movdqa (%2), %%xmm2\n"
asm("psubq %%xmm5, %%xmm5\n" "movdqa (%0), %%xmm0\n" // U0 Y0 V0 Y1 U1 Y2 V1 Y3 U2 Y4 V2 Y5 U3 Y6 V3 Y7
"movdqa 16(%0), %%xmm1\n" // S0 X0 T0 X1 S1 X2 T1 X3 S2 X4 T2 X5 S3 X6 T3 X7
"movdqa (%2), %%xmm2\n"
/** prepare Y*/
"movdqa %%xmm0, %%xmm3\n" //kopie
"movdqa %%xmm1, %%xmm4\n"
"pand %%xmm2, %%xmm3\n" // 00 Y0 00 Y1 00 Y2 00 Y3 00 Y4 00 Y5 00 Y6 00 Y7
"pand %%xmm2, %%xmm4\n" // 00 X0 00 X1 00 X2 00 X3 00 X4 00 X5 00 X6 00 X7
"psrldq $1, %%xmm3\n" // Y0 00 Y1 00 Y2 00 Y3 00 Y4 00 Y5 00 Y6 00 Y7 00
"psrldq $1, %%xmm4\n" // X0 00 X1 00 X2 00 X3 00 X4 00 X5 00 X6 00 X7 00
"packuswb %%xmm4, %%xmm3\n"// Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7 X0 X1 X2 X3 X4 X5 X6 X7
"movdqa %%xmm0, %%xmm3\n" //kopie
"movdqa %%xmm1, %%xmm4\n" "pand %%xmm2, %%xmm3\n" // 00 Y0 00 Y1 00 Y2 00 Y3 00 Y4 00 Y5 00 Y6 00 Y7
"pand %%xmm2, %%xmm4\n" // 00 X0 00 X1 00 X2 00 X3 00 X4 00 X5 00 X6 00 X7
"psrldq $1, %%xmm3\n" // Y0 00 Y1 00 Y2 00 Y3 00 Y4 00 Y5 00 Y6 00 Y7 00
"psrldq $1, %%xmm4\n" // X0 00 X1 00 X2 00 X3 00 X4 00 X5 00 X6 00 X7 00
"packuswb %%xmm4, %%xmm3\n" // Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7 X0 X1 X2 X3 X4 X5 X6 X7
/** prepare u*/
"psrldq $1, %%xmm2\n" //prepare U mask
"punpcklwd %%xmm5, %%xmm2\n" //xmm2: 0x000000ff000000ff000000ff000000ff
"movdqa %%xmm0, %%xmm5\n" //kopie puvodnich registru
"movdqa %%xmm1, %%xmm6\n"
"pand %%xmm2, %%xmm5\n" // U0 00 00 00 U1 00 00 00 U2 00 00 00 U3 00 00 00
"pand %%xmm2, %%xmm6\n" // S0 00 00 00 S1 00 00 00 S2 00 00 00 S3 00 00 00
"packssdw %%xmm6, %%xmm5\n" // U0 00 U1 00 U2 00 U3 00 S0 00 S1 00 S2 00 S3 00
"pslldq $1, %%xmm5\n" // 00 U0 00 U1 00 U2 00 U3 00 S0 00 S1 00 S2 00 S3
"psrldq $1, %%xmm2\n" //prepare U mask
"punpcklwd %%xmm5, %%xmm2\n" //xmm2: 0x000000ff000000ff000000ff000000ff
"movdqa %%xmm0, %%xmm5\n" //kopie puvodnich registru
"movdqa %%xmm1, %%xmm6\n" "pand %%xmm2, %%xmm5\n" // U0 00 00 00 U1 00 00 00 U2 00 00 00 U3 00 00 00
"pand %%xmm2, %%xmm6\n" // S0 00 00 00 S1 00 00 00 S2 00 00 00 S3 00 00 00
"packssdw %%xmm6, %%xmm5\n" // U0 00 U1 00 U2 00 U3 00 S0 00 S1 00 S2 00 S3 00
"pslldq $1, %%xmm5\n" // 00 U0 00 U1 00 U2 00 U3 00 S0 00 S1 00 S2 00 S3
/** prepare v*/
"pslldq $2, %%xmm2\n" //xmm2: 0x0000ff000000ff000000ff000000ff00
"movdqa %%xmm0, %%xmm6\n" //kopie puvodnich registru
"movdqa %%xmm1, %%xmm7\n"
"pand %%xmm2, %%xmm6\n" // 00 00 V0 00 00 00 V1 00 00 00 V2 00 00 00 V3 00
"pand %%xmm2, %%xmm7\n" // 00 00 T0 00 00 00 T1 00 00 00 T2 00 00 00 T3 00
"psrldq $2, %%xmm6\n" //shift <<
"psrldq $2, %%xmm7\n"
"packssdw %%xmm7, %%xmm6\n" // 00 V0 00 V1 00 V2 00 V3 00 T0 00 T1 00 T2 00 T3
"psllw $8, %%xmm6\n" // V0 00 V1 00 V2 00 V3 00 T0 00 T1 00 T2 00 T3 00
"movdqa (%3), %%xmm2\n"
"psubw %%xmm2, %%xmm5\n" /* u -= 128 */
"psubw %%xmm2, %%xmm6\n" /* v -= 128 */
"psrlw $3, %%xmm2\n" /* 128 -> 16 (0x8000 -> 0x1000) */
"movdqa %%xmm5, %%xmm0\n" //mov u -> xmm0
"movdqa %%xmm6, %%xmm1\n" //mov v -> xmm1
"pmulhw "GREEN_u"(%4), %%xmm0\n" /*Mul Green u coef -> Green u*/
"pmulhw "GREEN_v"(%4), %%xmm1\n" /*Mul Green v coef -> Green v*/
"pmulhw "BLUE_u"(%4), %%xmm5\n" /*Mul Blue u coef -> Blue u*/
"pmulhw "RED_v"(%4), %%xmm6\n" /*Mul Red v coef -> Red v*/
"paddsw %%xmm1, %%xmm0\n" /*Green u + Green v -> CGreen */
"pslldq $2, %%xmm2\n" //xmm2: 0x0000ff000000ff000000ff000000ff00
"movdqa %%xmm0, %%xmm6\n" //kopie puvodnich registru
"movdqa %%xmm1, %%xmm7\n" "pand %%xmm2, %%xmm6\n" // 00 00 V0 00 00 00 V1 00 00 00 V2 00 00 00 V3 00
"pand %%xmm2, %%xmm7\n" // 00 00 T0 00 00 00 T1 00 00 00 T2 00 00 00 T3 00
"psrldq $2, %%xmm6\n" //shift <<
"psrldq $2, %%xmm7\n" "packssdw %%xmm7, %%xmm6\n" // 00 V0 00 V1 00 V2 00 V3 00 T0 00 T1 00 T2 00 T3
"psllw $8, %%xmm6\n" // V0 00 V1 00 V2 00 V3 00 T0 00 T1 00 T2 00 T3 00
"movdqa (%3), %%xmm2\n" "psubw %%xmm2, %%xmm5\n" /* u -= 128 */
"psubw %%xmm2, %%xmm6\n" /* v -= 128 */
"psrlw $3, %%xmm2\n" /* 128 -> 16 (0x8000 -> 0x1000) */
"movdqa %%xmm5, %%xmm0\n" //mov u -> xmm0
"movdqa %%xmm6, %%xmm1\n" //mov v -> xmm1
"pmulhw " GREEN_u "(%4), %%xmm0\n" /*Mul Green u coef -> Green u */
"pmulhw " GREEN_v "(%4), %%xmm1\n" /*Mul Green v coef -> Green v */
"pmulhw " BLUE_u "(%4), %%xmm5\n" /*Mul Blue u coef -> Blue u */
"pmulhw " RED_v "(%4), %%xmm6\n" /*Mul Red v coef -> Red v */
"paddsw %%xmm1, %%xmm0\n" /*Green u + Green v -> CGreen */
/** process luma*/
"movdqa (%2), %%xmm4\n" //mov 00ff* mask to xmm2
"movdqa %%xmm3, %%xmm1\n" //copy Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7 X0 X1 X2 X3 X4 X5 X6 X7
"pand %%xmm4, %%xmm3\n" // get Y odd Y1 00 Y3 00 Y5 00 Y7 00 X1 00 X3 00 X5 00 X7 00
"psrldq $1, %%xmm4\n"
"pand %%xmm4, %%xmm1\n"
"psllw $8, %%xmm1\n" //get Y even Y0 00 Y2 00 Y4 00 Y6 00 X0 00 X2 00 X4 00 X6 00
"movdqa (%2), %%xmm4\n" //mov 00ff* mask to xmm2
"movdqa %%xmm3, %%xmm1\n" //copy Y0 Y1 Y2 Y3 Y4 Y5 Y6 Y7 X0 X1 X2 X3 X4 X5 X6 X7
"pand %%xmm4, %%xmm3\n" // get Y odd Y1 00 Y3 00 Y5 00 Y7 00 X1 00 X3 00 X5 00 X7 00
"psrldq $1, %%xmm4\n" "pand %%xmm4, %%xmm1\n" "psllw $8, %%xmm1\n" //get Y even Y0 00 Y2 00 Y4 00 Y6 00 X0 00 X2 00 X4 00 X6 00
"psubusw %%xmm2, %%xmm1\n" // Y -= 16
"psubusw %%xmm2, %%xmm3\n" // Y -= 16
"pmulhuw " Y_COEF "(%4), %%xmm1\n" // Y = (Y-16)*1.164
"pmulhuw " Y_COEF "(%4), %%xmm3\n" // Y = (Y-16)*1.164
// xmm0 -> green, xmm5 -> blue, xmm6 -> red
// xmm1 -> Y even, xmm3 -> Y odd
"movdqa %%xmm0, %%xmm2\n" // copy green
"movdqa %%xmm5, %%xmm4\n" // copy blue
"movdqa %%xmm6, %%xmm7\n" // copy red
"paddsw %%xmm1, %%xmm5\n" // Y even + blue
"paddsw %%xmm3, %%xmm4\n" // Y odd + blue
"paddsw %%xmm1, %%xmm6\n" // Y even + red
"paddsw %%xmm3, %%xmm7\n" // Y odd + red
"paddsw %%xmm1, %%xmm0\n" // Y even - green
"paddsw %%xmm3, %%xmm2\n" // Y odd - green
/*Limit RGB even to 0..255 */
"packuswb %%xmm0, %%xmm0\n" /* B6 B4 B2 B0 B6 B4 B2 B0 */
"packuswb %%xmm5, %%xmm5\n" /* R6 R4 R2 R0 R6 R4 R2 R0 */
"packuswb %%xmm6, %%xmm6\n" /* G6 G4 G2 G0 G6 G4 G2 G0 */
/*Limit RGB odd to 0..255 */
"packuswb %%xmm2, %%xmm2\n" /* B7 B5 B3 B1 B7 B5 B3 B1 */
"packuswb %%xmm4, %%xmm4\n" /* R7 R5 R3 R1 R7 R5 R3 R1 */
"packuswb %%xmm7, %%xmm7\n" /* G7 G5 G3 G1 G7 G5 G3 G1 */
/*Interleave RGB even and odd */
"punpcklbw %%xmm7, %%xmm6\n" //RED
"punpcklbw %%xmm2, %%xmm0\n" //GREEN
"punpcklbw %%xmm4, %%xmm5\n" //BLUE
"movdqa %%xmm6, %%xmm1\n" //copy R
"movdqa %%xmm5, %%xmm2\n" //copy B
"pxor %%xmm4, %%xmm4\n"
/*unpack high qword */
"punpckhbw %%xmm0, %%xmm5\n" //bg
"punpckhbw %%xmm4, %%xmm6\n" //r0
"movdqa %%xmm5, %%xmm7\n" "punpckhwd %%xmm6, %%xmm5\n" //bgr0
"punpcklwd %%xmm6, %%xmm7\n" //bgr0 low
/*unpack low qword */
"punpcklbw %%xmm0, %%xmm2\n" //bg
"punpcklbw %%xmm4, %%xmm1\n" //r0
"movdqa %%xmm2, %%xmm6\n" "punpckhwd %%xmm1, %%xmm2\n" //bgr0
"punpcklwd %%xmm1, %%xmm6\n" //bgr0 low
/* save */
"movdqa %%xmm6, (%1)\n" "movdqa %%xmm2, 16(%1)\n" "movdqa %%xmm7, 32(%1)\n" "movdqa %%xmm5, 48(%1)\n":
: "r"((unsigned long *)buffer),
"r"((unsigned long *)rgbBuf),
"r"((unsigned long *)_00ff),
"r"((unsigned long *)_0080), "r"((unsigned long *)_YUV_Coef)
);
"psubusw %%xmm2, %%xmm1\n" // Y -= 16
"psubusw %%xmm2, %%xmm3\n" // Y -= 16
"pmulhuw "Y_COEF"(%4), %%xmm1\n" // Y = (Y-16)*1.164
"pmulhuw "Y_COEF"(%4), %%xmm3\n" // Y = (Y-16)*1.164
// xmm0 -> green, xmm5 -> blue, xmm6 -> red
// xmm1 -> Y even, xmm3 -> Y odd
"movdqa %%xmm0, %%xmm2\n" // copy green
"movdqa %%xmm5, %%xmm4\n" // copy blue
"movdqa %%xmm6, %%xmm7\n" // copy red
"paddsw %%xmm1, %%xmm5\n" // Y even + blue
"paddsw %%xmm3, %%xmm4\n" // Y odd + blue
"paddsw %%xmm1, %%xmm6\n" // Y even + red
"paddsw %%xmm3, %%xmm7\n" // Y odd + red
"paddsw %%xmm1, %%xmm0\n" // Y even - green
"paddsw %%xmm3, %%xmm2\n" // Y odd - green
/*Limit RGB even to 0..255*/
"packuswb %%xmm0, %%xmm0\n" /* B6 B4 B2 B0 B6 B4 B2 B0 */
"packuswb %%xmm5, %%xmm5\n" /* R6 R4 R2 R0 R6 R4 R2 R0 */
"packuswb %%xmm6, %%xmm6\n" /* G6 G4 G2 G0 G6 G4 G2 G0 */
/*Limit RGB odd to 0..255*/
"packuswb %%xmm2, %%xmm2\n" /* B7 B5 B3 B1 B7 B5 B3 B1 */
"packuswb %%xmm4, %%xmm4\n" /* R7 R5 R3 R1 R7 R5 R3 R1 */
"packuswb %%xmm7, %%xmm7\n" /* G7 G5 G3 G1 G7 G5 G3 G1 */
/*Interleave RGB even and odd */
"punpcklbw %%xmm7, %%xmm6\n" //RED
"punpcklbw %%xmm2, %%xmm0\n" //GREEN
"punpcklbw %%xmm4, %%xmm5\n" //BLUE
"movdqa %%xmm6, %%xmm1\n" //copy R
"movdqa %%xmm5, %%xmm2\n" //copy B
"pxor %%xmm4, %%xmm4\n"
/*unpack high qword*/
"punpckhbw %%xmm0, %%xmm5\n" //bg
"punpckhbw %%xmm4, %%xmm6\n" //r0
"movdqa %%xmm5, %%xmm7\n"
"punpckhwd %%xmm6, %%xmm5\n" //bgr0
"punpcklwd %%xmm6, %%xmm7\n" //bgr0 low
/*unpack low qword*/
"punpcklbw %%xmm0, %%xmm2\n" //bg
"punpcklbw %%xmm4, %%xmm1\n" //r0
"movdqa %%xmm2, %%xmm6\n"
"punpckhwd %%xmm1, %%xmm2\n" //bgr0
"punpcklwd %%xmm1, %%xmm6\n" //bgr0 low
/* save */
"movdqa %%xmm6, (%1)\n"
"movdqa %%xmm2, 16(%1)\n"
"movdqa %%xmm7, 32(%1)\n"
"movdqa %%xmm5, 48(%1)\n"
:
: "r" ((unsigned long *) buffer),
"r" ((unsigned long *) rgbBuf),
"r" ((unsigned long *) _00ff),
"r" ((unsigned long *) _0080),
"r" ((unsigned long *) _YUV_Coef)
);
buffer += 32;
rgbBuf += 64;
}
buffer += 32;
rgbBuf += 64;
}
}
/* linear blend sage_deinterlace */
void sage_deinterlace(unsigned char *buffer)
{
int i,j;
long pitch = 1920*2;
register long pitch2 = pitch*2;
unsigned char *bline1, *bline2, *bline3;
register unsigned char *line1, *line2, *line3;
int i, j;
long pitch = 1920 * 2;
register long pitch2 = pitch * 2;
unsigned char *bline1, *bline2, *bline3;
register unsigned char *line1, *line2, *line3;
bline1 = buffer;
bline2 = buffer + pitch;
bline3 = buffer + 3*pitch;
for(i=0; i < 1920*2; i+=16) {
/* preload first two lines */
asm volatile(
"movdqa (%0), %%xmm0\n"
"movdqa (%1), %%xmm1\n"
:
: "r" ((unsigned long *)bline1),
"r" ((unsigned long *)bline2));
line1 = bline2;
line2 = bline2 + pitch;
line3 = bline3;
bline1 = buffer;
bline2 = buffer + pitch;
bline3 = buffer + 3 * pitch;
for (i = 0; i < 1920 * 2; i += 16) {
/* preload first two lines */
asm volatile ("movdqa (%0), %%xmm0\n"
"movdqa (%1), %%xmm1\n"::"r" ((unsigned long *)
bline1),
"r"((unsigned long *)bline2));
line1 = bline2;
line2 = bline2 + pitch;
line3 = bline3;
for(j=0; j < 1076; j+=2) {
asm volatile(
"movdqa (%1), %%xmm2\n"
"pavgb %%xmm2, %%xmm0\n"
"pavgb %%xmm1, %%xmm0\n"
"movdqa (%2), %%xmm1\n"
"movdqa %%xmm0, (%0)\n"
"pavgb %%xmm1, %%xmm0\n"
"pavgb %%xmm2, %%xmm0\n"
"movdqa %%xmm0, (%1)\n"
:
:"r" ((unsigned long *)line1),
"r" ((unsigned long *)line2),
"r" ((unsigned long *)line3)
);
line1 += pitch2;
line2 += pitch2;
line3 += pitch2;
}
bline1 += 16;
bline2 += 16;
bline3 += 16;
}
for (j = 0; j < 1076; j += 2) {
asm volatile ("movdqa (%1), %%xmm2\n"
"pavgb %%xmm2, %%xmm0\n"
"pavgb %%xmm1, %%xmm0\n"
"movdqa (%2), %%xmm1\n"
"movdqa %%xmm0, (%0)\n"
"pavgb %%xmm1, %%xmm0\n"
"pavgb %%xmm2, %%xmm0\n"
"movdqa %%xmm0, (%1)\n"::"r" ((unsigned
long *)
line1),
"r"((unsigned long *)line2),
"r"((unsigned long *)line3)
);
line1 += pitch2;
line2 += pitch2;
line3 += pitch2;
}
bline1 += 16;
bline2 += 16;
bline3 += 16;
}
}
inline void swapBytes(unsigned char *buf, int len)
{
register unsigned char b1;
int i =0;
register unsigned char b1;
int i = 0;
do {
b1 = buf[i];
buf[i] = buf[i+1];
buf[i+1] = b1;
} while ((i += 2)<len);
do {
b1 = buf[i];
buf[i] = buf[i + 1];
buf[i + 1] = b1;
} while ((i += 2) < len);
// i = open("/tmp/dump", O_CREAT|O_WRONLY,0644);
// write(i, buf, len);
@@ -324,27 +287,27 @@ inline void swapBytes(unsigned char *buf, int len)
inline void sage_copyline64(unsigned char *dst, unsigned char *src, int len)
{
register unsigned long *d, *s;
register unsigned long a1,a2,a3,a4;
register unsigned long *d, *s;
register unsigned long a1, a2, a3, a4;
d = (unsigned long *)dst;
s = (unsigned long *)src;
d = (unsigned long *)dst;
s = (unsigned long *)src;
while(len-- > 0) {
a1 = *(s++);
a2 = *(s++);
a3 = *(s++);
a4 = *(s++);
while (len-- > 0) {
a1 = *(s++);
a2 = *(s++);
a3 = *(s++);
a4 = *(s++);
a1 = (a1 & 0xffffff) | ((a1 >> 8) & 0xffffff000000);
a2 = (a2 & 0xffffff) | ((a2 >> 8) & 0xffffff000000);
a3 = (a3 & 0xffffff) | ((a3 >> 8) & 0xffffff000000);
a4 = (a4 & 0xffffff) | ((a4 >> 8) & 0xffffff000000);
a1 = (a1 & 0xffffff) | ((a1 >> 8) & 0xffffff000000);
a2 = (a2 & 0xffffff) | ((a2 >> 8) & 0xffffff000000);
a3 = (a3 & 0xffffff) | ((a3 >> 8) & 0xffffff000000);
a4 = (a4 & 0xffffff) | ((a4 >> 8) & 0xffffff000000);
*(d++) = a1 | (a2 << 48); /* 0xa2|a2|a1|a1|a1|a1|a1|a1 */
*(d++) = (a2 >> 16)|(a3 << 32); /* 0xa3|a3|a3|a3|a2|a2|a2|a2 */
*(d++) = (a3 >> 32)|(a4 << 16); /* 0xa4|a4|a4|a4|a4|a4|a3|a3 */
}
*(d++) = a1 | (a2 << 48); /* 0xa2|a2|a1|a1|a1|a1|a1|a1 */
*(d++) = (a2 >> 16) | (a3 << 32); /* 0xa3|a3|a3|a3|a2|a2|a2|a2 */
*(d++) = (a3 >> 32) | (a4 << 16); /* 0xa4|a4|a4|a4|a4|a4|a3|a3 */
}
}
/* convert 10bits Cb Y Cr A Y Cb Y A to 8bits Cb Y Cr Y Cb Y */
@@ -353,247 +316,247 @@ inline void sage_copyline64(unsigned char *dst, unsigned char *src, int len)
inline void sage_copyline128(unsigned char *d, unsigned char *s, int len)
{
register unsigned char *_d=d,*_s=s;
register unsigned char *_d = d, *_s = s;
while(--len >= 0) {
asm ("movd %0, %%xmm4\n": : "r" (0xffffff));
while (--len >= 0) {
asm("movd %0, %%xmm4\n": :"r"(0xffffff));
asm volatile ("movdqa (%0), %%xmm0\n"
"movdqa 16(%0), %%xmm5\n"
"movdqa %%xmm0, %%xmm1\n"
"movdqa %%xmm0, %%xmm2\n"
"movdqa %%xmm0, %%xmm3\n"
"pand %%xmm4, %%xmm0\n"
"movdqa %%xmm5, %%xmm6\n"
"movdqa %%xmm5, %%xmm7\n"
"movdqa %%xmm5, %%xmm8\n"
"pand %%xmm4, %%xmm5\n"
"pslldq $4, %%xmm4\n"
"pand %%xmm4, %%xmm1\n"
"pand %%xmm4, %%xmm6\n"
"pslldq $4, %%xmm4\n"
"psrldq $1, %%xmm1\n"
"psrldq $1, %%xmm6\n"
"pand %%xmm4, %%xmm2\n"
"pand %%xmm4, %%xmm7\n"
"pslldq $4, %%xmm4\n"
"psrldq $2, %%xmm2\n"
"psrldq $2, %%xmm7\n"
"pand %%xmm4, %%xmm3\n"
"pand %%xmm4, %%xmm8\n"
"por %%xmm1, %%xmm0\n"
"psrldq $3, %%xmm3\n"
"psrldq $3, %%xmm8\n"
"por %%xmm2, %%xmm0\n"
"por %%xmm6, %%xmm5\n"
"por %%xmm3, %%xmm0\n"
"por %%xmm7, %%xmm5\n"
"movdq2q %%xmm0, %%mm0\n"
"por %%xmm8, %%xmm5\n"
"movdqa %%xmm5, %%xmm1\n"
"pslldq $12, %%xmm5\n"
"psrldq $4, %%xmm1\n"
"por %%xmm5, %%xmm0\n"
"psrldq $8, %%xmm0\n"
"movq %%mm0, (%1)\n"
"movdq2q %%xmm0, %%mm1\n"
"movdq2q %%xmm1, %%mm2\n"
"movq %%mm1, 8(%1)\n"
"movq %%mm2, 16(%1)\n"
:
: "r" (_s), "r" (_d));
asm volatile ("movdqa (%0), %%xmm0\n"
"movdqa 16(%0), %%xmm5\n"
"movdqa %%xmm0, %%xmm1\n"
"movdqa %%xmm0, %%xmm2\n"
"movdqa %%xmm0, %%xmm3\n"
"pand %%xmm4, %%xmm0\n"
"movdqa %%xmm5, %%xmm6\n"
"movdqa %%xmm5, %%xmm7\n"
"movdqa %%xmm5, %%xmm8\n"
"pand %%xmm4, %%xmm5\n"
"pslldq $4, %%xmm4\n"
"pand %%xmm4, %%xmm1\n"
"pand %%xmm4, %%xmm6\n"
"pslldq $4, %%xmm4\n"
"psrldq $1, %%xmm1\n"
"psrldq $1, %%xmm6\n"
"pand %%xmm4, %%xmm2\n"
"pand %%xmm4, %%xmm7\n"
"pslldq $4, %%xmm4\n"
"psrldq $2, %%xmm2\n"
"psrldq $2, %%xmm7\n"
"pand %%xmm4, %%xmm3\n"
"pand %%xmm4, %%xmm8\n"
"por %%xmm1, %%xmm0\n"
"psrldq $3, %%xmm3\n"
"psrldq $3, %%xmm8\n"
"por %%xmm2, %%xmm0\n"
"por %%xmm6, %%xmm5\n"
"por %%xmm3, %%xmm0\n"
"por %%xmm7, %%xmm5\n"
"movdq2q %%xmm0, %%mm0\n"
"por %%xmm8, %%xmm5\n"
"movdqa %%xmm5, %%xmm1\n"
"pslldq $12, %%xmm5\n"
"psrldq $4, %%xmm1\n"
"por %%xmm5, %%xmm0\n"
"psrldq $8, %%xmm0\n"
"movq %%mm0, (%1)\n"
"movdq2q %%xmm0, %%mm1\n"
"movdq2q %%xmm1, %%mm2\n"
"movq %%mm1, 8(%1)\n"
"movq %%mm2, 16(%1)\n"::"r" (_s), "r"(_d));
_s += 32;
_d += 24;
}
}
#endif /* HAVE_MACOSX */
static void* display_thread_sage(void *arg)
{
struct state_sdl *s = (struct state_sdl *) arg;
int i;
while (1) {
GLubyte *line1, *line2;
//display_sage_handle_events();
sem_wait(&s->semaphore);
assert(s->outBuffer != NULL);
if (bitdepth == 10) {
line1 = s->buffers[s->image_display];
#ifdef SAGE_GLSL_YUV
line2 = s->outBuffer;
#else
line2 = s->yuvBuffer;
#endif
for(i=0; i<1080; i+=2) {
#ifdef HAVE_MACOSX || HAVE_32B_LINUX
sage_copyline64(line2, line1, 5120/32);
sage_copyline64(line2+3840, line1+5120*540, 5120/32);
#else /* HAVE_MACOSX */
sage_copyline128(line2, line1, 5120/32);
sage_copyline128(line2+3840, line1+5120*540, 5120/32);
#endif /* HAVE_MACOSX */
line1 += 5120;
line2 += 2*3840;
}
#ifndef SAGE_GLSL_YUV
yuv2rgba(s->yuvBuffer, s->outBuffer);
#endif
}
else {
#ifdef SAGE_GLSL_YUV
line1 = s->buffers[s->image_display];
line2 = s->outBuffer;
if (progressive == 1) {
memcpy(line2, line1, hd_size_x*hd_size_y*hd_color_bpp);
} else {
for(i=0; i<1080; i+=2){
memcpy(line2, line1, HD_WIDTH*2);
memcpy(line2+HD_WIDTH*2, line1+HD_WIDTH*2*540, HD_WIDTH*2);
line1 += HD_WIDTH*2;
line2 += HD_WIDTH*2*2;
}
}
#else
yuv2rgba(s->buffers[s->image_display], s->outBuffer);
#endif
_s += 32;
_d += 24;
}
// swapBytes(s->outBuffer, HD_WIDTH*HD_HEIGHT*2);
// int i = open("/tmp/testcard_image.yuv", O_WRONLY|O_CREAT, 0644);
// write(i,s->yuvBuffer, HD_WIDTH*HD_HEIGHT*2);
// close(i);
sage_swapBuffer();
s->outBuffer = sage_getBuffer();
}
return NULL;
}
#endif /* HAVE_MACOSX */
void * display_sage_init(void)
static void *display_thread_sage(void *arg)
{
struct state_sdl *s;
struct state_sdl *s = (struct state_sdl *)arg;
int i;
s = (struct state_sdl *) malloc(sizeof(struct state_sdl));
s->magic = MAGIC_SAGE;
while (1) {
GLubyte *line1, *line2;
//display_sage_handle_events();
//iopl(3);
sem_wait(&s->semaphore);
assert(s->outBuffer != NULL);
if (bitdepth == 10) {
line1 = s->buffers[s->image_display];
#ifdef SAGE_GLSL_YUV
line2 = s->outBuffer;
#else
line2 = s->yuvBuffer;
#endif
for (i = 0; i < 1080; i += 2) {
#ifdef HAVE_MACOSX || HAVE_32B_LINUX
sage_copyline64(line2, line1, 5120 / 32);
sage_copyline64(line2 + 3840,
line1 + 5120 * 540, 5120 / 32);
#else /* HAVE_MACOSX */
sage_copyline128(line2, line1, 5120 / 32);
sage_copyline128(line2 + 3840,
line1 + 5120 * 540, 5120 / 32);
#endif /* HAVE_MACOSX */
line1 += 5120;
line2 += 2 * 3840;
}
#ifndef SAGE_GLSL_YUV
yuv2rgba(s->yuvBuffer, s->outBuffer);
#endif
} else {
#ifdef SAGE_GLSL_YUV
line1 = s->buffers[s->image_display];
line2 = s->outBuffer;
if (progressive == 1) {
memcpy(line2, line1,
hd_size_x * hd_size_y * hd_color_bpp);
} else {
for (i = 0; i < 1080; i += 2) {
memcpy(line2, line1, HD_WIDTH * 2);
memcpy(line2 + HD_WIDTH * 2,
line1 + HD_WIDTH * 2 * 540,
HD_WIDTH * 2);
line1 += HD_WIDTH * 2;
line2 += HD_WIDTH * 2 * 2;
}
}
#else
yuv2rgba(s->buffers[s->image_display], s->outBuffer);
#endif
}
// swapBytes(s->outBuffer, HD_WIDTH*HD_HEIGHT*2);
// int i = open("/tmp/testcard_image.yuv", O_WRONLY|O_CREAT, 0644);
// write(i,s->yuvBuffer, HD_WIDTH*HD_HEIGHT*2);
// close(i);
sage_swapBuffer();
s->outBuffer = sage_getBuffer();
}
return NULL;
}
void *display_sage_init(void)
{
struct state_sdl *s;
s = (struct state_sdl *)malloc(sizeof(struct state_sdl));
s->magic = MAGIC_SAGE;
//iopl(3);
/** yuv2rgb constants init */
posix_memalign((void *)&_YUV_Coef, 16, 80+32);
_YUV_Coef[0] = _YUV_Coef[1] = _YUV_Coef[2] = _YUV_Coef[3] = 0x01990199;// RED_v 1.596
_YUV_Coef[4] = _YUV_Coef[5] = _YUV_Coef[6] = _YUV_Coef[7] = 0xff9cff9c;// GREEN_u 0.391
_YUV_Coef[8] = _YUV_Coef[9] = _YUV_Coef[10] = _YUV_Coef[11] = 0xff30ff30; // GREEN_v 0.813
_YUV_Coef[12] = _YUV_Coef[13] = _YUV_Coef[14] = _YUV_Coef[15] = 0x02050205; // BLUE_u 2.018
_YUV_Coef[16] = _YUV_Coef[17] = _YUV_Coef[18] = _YUV_Coef[19] = 0x012a012a; // Y 1.164
_00ff = & _YUV_Coef[20];
_0080 = & _YUV_Coef[24];
_00ff[0] = _00ff[1] = _00ff[2] = _00ff[3] = 0xff00ff00;
_0080[0] = _0080[1] = _0080[2] = _0080[3] = 0x80008000;
posix_memalign((void *)&_YUV_Coef, 16, 80 + 32);
_YUV_Coef[0] = _YUV_Coef[1] = _YUV_Coef[2] = _YUV_Coef[3] = 0x01990199; // RED_v 1.596
_YUV_Coef[4] = _YUV_Coef[5] = _YUV_Coef[6] = _YUV_Coef[7] = 0xff9cff9c; // GREEN_u 0.391
_YUV_Coef[8] = _YUV_Coef[9] = _YUV_Coef[10] = _YUV_Coef[11] = 0xff30ff30; // GREEN_v 0.813
_YUV_Coef[12] = _YUV_Coef[13] = _YUV_Coef[14] = _YUV_Coef[15] = 0x02050205; // BLUE_u 2.018
_YUV_Coef[16] = _YUV_Coef[17] = _YUV_Coef[18] = _YUV_Coef[19] = 0x012a012a; // Y 1.164
_00ff = &_YUV_Coef[20];
_0080 = &_YUV_Coef[24];
_00ff[0] = _00ff[1] = _00ff[2] = _00ff[3] = 0xff00ff00;
_0080[0] = _0080[1] = _0080[2] = _0080[3] = 0x80008000;
s->buffers[0] = malloc(HD_WIDTH*HD_HEIGHT*3);
s->buffers[1] = malloc(HD_WIDTH*HD_HEIGHT*3);
s->yuvBuffer = malloc(HD_WIDTH*HD_HEIGHT*2);
s->image_network=0;
s->image_display=1;
s->buffers[0] = malloc(HD_WIDTH * HD_HEIGHT * 3);
s->buffers[1] = malloc(HD_WIDTH * HD_HEIGHT * 3);
s->yuvBuffer = malloc(HD_WIDTH * HD_HEIGHT * 2);
s->image_network = 0;
s->image_display = 1;
asm("emms\n");
asm("emms\n");
/* sage init */
//FIXME sem se musi propasovat ty spravne parametry argc argv
int appID = 0;
int nodeID = 1;
initSage(appID, nodeID);
s->outBuffer = sage_getBuffer();
/* sage init */
//FIXME sem se musi propasovat ty spravne parametry argc argv
int appID = 0;
int nodeID = 1;
initSage(appID, nodeID);
s->outBuffer = sage_getBuffer();
/* thread init */
sem_init(&s->semaphore, 0, 0);
if (pthread_create
(&(s->thread_id), NULL, display_thread_sage, (void *)s) != 0) {
perror("Unable to create display thread\n");
return NULL;
}
/* thread init */
sem_init(&s->semaphore, 0, 0);
if (pthread_create(&(s->thread_id), NULL, display_thread_sage, (void *) s) != 0) {
perror("Unable to create display thread\n");
return NULL;
}
debug_msg("Window initialized %p\n", s);
return (void *)s;
debug_msg("Window initialized %p\n", s);
return (void *)s;
}
void display_sage_done(void *state)
{
struct state_sdl *s = (struct state_sdl *) state;
struct state_sdl *s = (struct state_sdl *)state;
assert(s->magic == MAGIC_SAGE);
sage_shutdown();
assert(s->magic == MAGIC_SAGE);
sage_shutdown();
}
char * display_sage_getf(void *state)
char *display_sage_getf(void *state)
{
struct state_sdl *s = (struct state_sdl *) state;
assert(s->magic == MAGIC_SAGE);
return (char *)s->buffers[s->image_network];
struct state_sdl *s = (struct state_sdl *)state;
assert(s->magic == MAGIC_SAGE);
return (char *)s->buffers[s->image_network];
}
int display_sage_putf(void *state, char *frame)
{
int tmp;
struct state_sdl *s = (struct state_sdl *) state;
int tmp;
struct state_sdl *s = (struct state_sdl *)state;
assert(s->magic == MAGIC_SAGE);
UNUSED(frame);
assert(s->magic == MAGIC_SAGE);
UNUSED(frame);
/* ...and give it more to do... */
tmp = s->image_display;
s->image_display = s->image_network;
s->image_network = tmp;
//s->work_to_do = TRUE;
/* ...and give it more to do... */
tmp = s->image_display;
s->image_display = s->image_network;
s->image_network = tmp;
//s->work_to_do = TRUE;
/* ...and signal the worker */
sem_post(&s->semaphore);
sem_getvalue(&s->semaphore, &tmp);
if(tmp > 1)
printf("frame drop!\n");
return 0;
/* ...and signal the worker */
sem_post(&s->semaphore);
sem_getvalue(&s->semaphore, &tmp);
if (tmp > 1)
printf("frame drop!\n");
return 0;
}
display_colour_t display_sage_colour(void *state)
{
struct state_sdl *s = (struct state_sdl *) state;
assert(s->magic == MAGIC_SAGE);
return DC_YUV;
struct state_sdl *s = (struct state_sdl *)state;
assert(s->magic == MAGIC_SAGE);
return DC_YUV;
}
display_type_t * display_sage_probe(void)
display_type_t *display_sage_probe(void)
{
display_type_t *dt;
display_format_t *dformat;
display_type_t *dt;
display_format_t *dformat;
dformat = malloc(4 * sizeof(display_format_t));
dformat[0].size = DS_176x144;
dformat[0].colour_mode = DC_YUV;
dformat[0].num_images = 1;
dformat[1].size = DS_352x288;
dformat[1].colour_mode = DC_YUV;
dformat[1].num_images = 1;
dformat[2].size = DS_702x576;
dformat[2].colour_mode = DC_YUV;
dformat[2].num_images = 1;
dformat[3].size = DS_1280x720;
dformat[3].colour_mode = DC_YUV;
dformat[3].num_images = 1;
dformat = malloc(4 * sizeof(display_format_t));
dformat[0].size = DS_176x144;
dformat[0].colour_mode = DC_YUV;
dformat[0].num_images = 1;
dformat[1].size = DS_352x288;
dformat[1].colour_mode = DC_YUV;
dformat[1].num_images = 1;
dformat[2].size = DS_702x576;
dformat[2].colour_mode = DC_YUV;
dformat[2].num_images = 1;
dformat[3].size = DS_1280x720;
dformat[3].colour_mode = DC_YUV;
dformat[3].num_images = 1;
dt = malloc(sizeof(display_type_t));
if (dt != NULL) {
dt->id = DISPLAY_SAGE_ID;
dt->name = "sage";
dt->description = "SAGE";
dt->formats = dformat;
dt->num_formats = 4;
}
return dt;
dt = malloc(sizeof(display_type_t));
if (dt != NULL) {
dt->id = DISPLAY_SAGE_ID;
dt->name = "sage";
dt->description = "SAGE";
dt->formats = dformat;
dt->num_formats = 4;
}
return dt;
}

View File

@@ -53,7 +53,7 @@
#include "config_unix.h"
#include "config_win32.h"
#ifndef X_DISPLAY_MISSING /* Don't try to compile if X is not present */
#ifndef X_DISPLAY_MISSING /* Don't try to compile if X is not present */
#include "debug.h"
#include "video_display.h"
@@ -74,9 +74,9 @@
#ifdef HAVE_MACOSX
#include <architecture/i386/io.h>
void NSApplicationLoad();
#else /* HAVE_MACOSX */
#else /* HAVE_MACOSX */
#include <sys/io.h>
#endif /* HAVE_MACOSX */
#endif /* HAVE_MACOSX */
#include <sys/time.h>
#include <math.h>
@@ -89,126 +89,130 @@ void NSApplicationLoad();
#define FOURCC_UYVY 0x59565955
struct state_sdl {
Display *display;
Window window;
GC gc;
int vw_depth;
Visual *vw_visual;
SDL_Overlay *yuv_image;
SDL_Surface *rgb_image;
struct video_frame frame;
XShmSegmentInfo vw_shm_segment[2];
int image_display, image_network;
XvAdaptorInfo *ai;
int xv_port;
/* Thread related information follows... */
pthread_t thread_id;
SDL_sem *semaphore;
/* For debugging... */
uint32_t magic;
Display *display;
Window window;
GC gc;
int vw_depth;
Visual *vw_visual;
SDL_Overlay *yuv_image;
SDL_Surface *rgb_image;
struct video_frame frame;
XShmSegmentInfo vw_shm_segment[2];
int image_display, image_network;
XvAdaptorInfo *ai;
int xv_port;
/* Thread related information follows... */
pthread_t thread_id;
SDL_sem *semaphore;
/* For debugging... */
uint32_t magic;
struct timeval tv;
int frames;
struct timeval tv;
int frames;
SDL_Surface *sdl_screen;
SDL_Rect src_rect;
SDL_Rect dst_rect;
SDL_Surface *sdl_screen;
SDL_Rect src_rect;
SDL_Rect dst_rect;
int width;
int height;
double bpp;
int src_linesize;
int dst_linesize;
int width;
int height;
double bpp;
int src_linesize;
int dst_linesize;
codec_t codec;
const struct codec_info_t *c_info;
unsigned rgb:1;
unsigned interlaced:1;
unsigned deinterlace:1;
unsigned fs:1;
codec_t codec;
const struct codec_info_t *c_info;
unsigned rgb:1;
unsigned interlaced:1;
unsigned deinterlace:1;
unsigned fs:1;
};
void show_help(void);
void cleanup_screen(struct state_sdl *s);
void reconfigure_screen(void *s, unsigned int width, unsigned int height, codec_t codec);
void reconfigure_screen(void *s, unsigned int width, unsigned int height,
codec_t codec);
extern int should_exit;
int
display_sdl_handle_events(void *arg)
int display_sdl_handle_events(void *arg)
{
SDL_Event sdl_event;
struct state_sdl *s = arg;
while (SDL_PollEvent(&sdl_event)) {
switch (sdl_event.type) {
case SDL_KEYDOWN:
case SDL_KEYUP:
if (!strcmp(SDL_GetKeyName(sdl_event.key.keysym.sym), "q")) {
should_exit = 1;
SDL_SemPost(s->semaphore);
SDL_Event sdl_event;
struct state_sdl *s = arg;
while (SDL_PollEvent(&sdl_event)) {
switch (sdl_event.type) {
case SDL_KEYDOWN:
case SDL_KEYUP:
if (!strcmp
(SDL_GetKeyName(sdl_event.key.keysym.sym), "q")) {
should_exit = 1;
SDL_SemPost(s->semaphore);
}
break;
default:
break;
}
break;
default:
break;
}
}
return 0;
return 0;
}
static void*
display_thread_sdl(void *arg)
static void *display_thread_sdl(void *arg)
{
struct state_sdl *s = (struct state_sdl *) arg;
struct timeval tv,tv1;
int i;
unsigned char *buff = NULL;
unsigned char *line1=NULL, *line2;
int linesize=0;
int height=0;
struct state_sdl *s = (struct state_sdl *)arg;
struct timeval tv, tv1;
int i;
unsigned char *buff = NULL;
unsigned char *line1 = NULL, *line2;
int linesize = 0;
int height = 0;
gettimeofday(&s->tv, NULL);
gettimeofday(&s->tv, NULL);
while (!should_exit) {
display_sdl_handle_events(s);
SDL_SemWait(s->semaphore);
while (!should_exit) {
display_sdl_handle_events(s);
SDL_SemWait(s->semaphore);
if(s->deinterlace) {
if(s->rgb) {
/*FIXME: this will not work! Should not deinterlace whole screen, just subwindow*/
vc_deinterlace(s->rgb_image->pixels, s->dst_linesize, s->height);
if (s->deinterlace) {
if (s->rgb) {
/*FIXME: this will not work! Should not deinterlace whole screen, just subwindow */
vc_deinterlace(s->rgb_image->pixels,
s->dst_linesize, s->height);
} else {
vc_deinterlace(*s->yuv_image->pixels,
s->dst_linesize, s->height);
}
}
if (s->rgb) {
SDL_Flip(s->sdl_screen);
s->frame.data = s->sdl_screen->pixels +
s->sdl_screen->pitch * s->dst_rect.y +
s->dst_rect.x *
s->sdl_screen->format->BytesPerPixel;
} else {
vc_deinterlace(*s->yuv_image->pixels, s->dst_linesize, s->height);
SDL_UnlockYUVOverlay(s->yuv_image);
SDL_DisplayYUVOverlay(s->yuv_image, &(s->dst_rect));
s->frame.data = (unsigned char *)*s->yuv_image->pixels;
}
s->frames++;
gettimeofday(&tv, NULL);
double seconds = tv_diff(tv, s->tv);
if (seconds > 5) {
double fps = s->frames / seconds;
fprintf(stdout, "%d frames in %g seconds = %g FPS\n",
s->frames, seconds, fps);
s->tv = tv;
s->frames = 0;
}
}
if(s->rgb) {
SDL_Flip(s->sdl_screen);
s->frame.data = s->sdl_screen->pixels +
s->sdl_screen->pitch * s->dst_rect.y + s->dst_rect.x * s->sdl_screen->format->BytesPerPixel;
} else {
SDL_UnlockYUVOverlay(s->yuv_image);
SDL_DisplayYUVOverlay(s->yuv_image, &(s->dst_rect));
s->frame.data = (unsigned char*)*s->yuv_image->pixels;
}
s->frames++;
gettimeofday(&tv, NULL);
double seconds = tv_diff(tv, s->tv);
if(seconds > 5) {
double fps = s->frames / seconds;
fprintf(stdout, "%d frames in %g seconds = %g FPS\n", s->frames, seconds, fps);
s->tv = tv;
s->frames = 0;
}
}
return NULL;
return NULL;
}
void
show_help(void)
void show_help(void)
{
printf("SDL options:\n");
printf("\twidth:height:codec[:fs][:i][:d][:f:filename] | help\n");
@@ -219,128 +223,142 @@ show_help(void)
show_codec_help();
}
void
cleanup_screen(struct state_sdl *s)
void cleanup_screen(struct state_sdl *s)
{
if(s->rgb == 0) {
SDL_FreeYUVOverlay(s->yuv_image);
}
if (s->rgb == 0) {
SDL_FreeYUVOverlay(s->yuv_image);
}
}
void
reconfigure_screen(void *state, unsigned int width, unsigned int height, codec_t color_spec)
reconfigure_screen(void *state, unsigned int width, unsigned int height,
codec_t color_spec)
{
struct state_sdl *s = (struct state_sdl *) state;
int itemp;
unsigned int utemp;
Window wtemp;
struct state_sdl *s = (struct state_sdl *)state;
int itemp;
unsigned int utemp;
Window wtemp;
unsigned int x_res_x;
unsigned int x_res_y;
unsigned int x_res_x;
unsigned int x_res_y;
int ret, i;
int ret, i;
cleanup_screen(s);
cleanup_screen(s);
fprintf(stdout, "Reconfigure to size %dx%d\n", width, height);
fprintf(stdout, "Reconfigure to size %dx%d\n", width, height);
s->width = width;
s->height = height;
s->width = width;
s->height = height;
ret = XGetGeometry(s->display, DefaultRootWindow(s->display), &wtemp, &itemp,
&itemp, &x_res_x, &x_res_y, &utemp, &utemp);
ret =
XGetGeometry(s->display, DefaultRootWindow(s->display), &wtemp,
&itemp, &itemp, &x_res_x, &x_res_y, &utemp, &utemp);
fprintf(stdout,"Setting video mode %dx%d.\n", x_res_x, x_res_y);
if(s->fs)
s->sdl_screen = SDL_SetVideoMode(x_res_x, x_res_y, 0, SDL_FULLSCREEN | SDL_HWSURFACE | SDL_DOUBLEBUF);
else {
x_res_x = s->width;
x_res_y = s->height;
s->sdl_screen = SDL_SetVideoMode(x_res_x, x_res_y, 0, SDL_HWSURFACE | SDL_DOUBLEBUF);
}
if(s->sdl_screen == NULL){
fprintf(stderr,"Error setting video mode %dx%d!\n", x_res_x, x_res_y);
free(s);
exit(128);
}
SDL_WM_SetCaption("Ultragrid - SDL Display", "Ultragrid");
SDL_ShowCursor(SDL_DISABLE);
for(i = 0; codec_info[i].name != NULL; i++) {
if(color_spec == codec_info[i].codec) {
s->c_info = &codec_info[i];
s->rgb = codec_info[i].rgb;
s->bpp = codec_info[i].bpp;
fprintf(stdout, "Setting video mode %dx%d.\n", x_res_x, x_res_y);
if (s->fs)
s->sdl_screen =
SDL_SetVideoMode(x_res_x, x_res_y, 0,
SDL_FULLSCREEN | SDL_HWSURFACE |
SDL_DOUBLEBUF);
else {
x_res_x = s->width;
x_res_y = s->height;
s->sdl_screen =
SDL_SetVideoMode(x_res_x, x_res_y, 0,
SDL_HWSURFACE | SDL_DOUBLEBUF);
}
}
if(s->rgb == 0) {
s->yuv_image = SDL_CreateYUVOverlay(s->width, s->height, FOURCC_UYVY, s->sdl_screen);
if (s->yuv_image == NULL) {
printf("SDL_overlay initialization failed.\n");
if (s->sdl_screen == NULL) {
fprintf(stderr, "Error setting video mode %dx%d!\n", x_res_x,
x_res_y);
free(s);
exit(127);
}
}
exit(128);
}
SDL_WM_SetCaption("Ultragrid - SDL Display", "Ultragrid");
int w = s->width;
SDL_ShowCursor(SDL_DISABLE);
if(s->c_info->h_align) {
w = ((w+s->c_info->h_align-1)/s->c_info->h_align)*s->c_info->h_align;
}
for (i = 0; codec_info[i].name != NULL; i++) {
if (color_spec == codec_info[i].codec) {
s->c_info = &codec_info[i];
s->rgb = codec_info[i].rgb;
s->bpp = codec_info[i].bpp;
}
}
s->src_linesize = w*s->bpp;
if(s->rgb)
s->dst_linesize = s->width*4;
else
s->dst_linesize = s->width*2;
if (s->rgb == 0) {
s->yuv_image =
SDL_CreateYUVOverlay(s->width, s->height, FOURCC_UYVY,
s->sdl_screen);
if (s->yuv_image == NULL) {
printf("SDL_overlay initialization failed.\n");
free(s);
exit(127);
}
}
s->dst_rect.w = s->width;
s->dst_rect.h = s->height;
int w = s->width;
if ((int)x_res_x > s->width) {
s->dst_rect.x = (x_res_x - s->width) / 2;
} else if((int)x_res_x < s->width){
s->dst_rect.w = x_res_x;
}
if ((int)x_res_y > s->height) {
s->dst_rect.y = (x_res_y - s->height) / 2;
} else if((int)x_res_y < s->height) {
s->dst_rect.h = x_res_y;
}
if (s->c_info->h_align) {
w = ((w + s->c_info->h_align -
1) / s->c_info->h_align) * s->c_info->h_align;
}
s->src_rect.w = s->width;
s->src_rect.h = s->height;
s->src_linesize = w * s->bpp;
if (s->rgb)
s->dst_linesize = s->width * 4;
else
s->dst_linesize = s->width * 2;
fprintf(stdout,"Setting SDL rect %dx%d - %d,%d.\n", s->dst_rect.w, s->dst_rect.h, s->dst_rect.x,
s->dst_rect.y);
s->dst_rect.w = s->width;
s->dst_rect.h = s->height;
s->frame.rshift = s->sdl_screen->format->Rshift;
s->frame.gshift = s->sdl_screen->format->Gshift;
s->frame.bshift = s->sdl_screen->format->Bshift;
s->frame.color_spec = s->c_info->codec;
s->frame.width = s->width;
s->frame.height = s->height;
s->frame.src_bpp = s->bpp;
s->frame.dst_linesize = s->dst_linesize;
if ((int)x_res_x > s->width) {
s->dst_rect.x = (x_res_x - s->width) / 2;
} else if ((int)x_res_x < s->width) {
s->dst_rect.w = x_res_x;
}
if ((int)x_res_y > s->height) {
s->dst_rect.y = (x_res_y - s->height) / 2;
} else if ((int)x_res_y < s->height) {
s->dst_rect.h = x_res_y;
}
if(s->rgb) {
s->frame.data = s->sdl_screen->pixels +
s->sdl_screen->pitch * s->dst_rect.y + s->dst_rect.x * s->sdl_screen->format->BytesPerPixel;
s->frame.data_len = s->sdl_screen->pitch * x_res_y -
s->sdl_screen->pitch * s->dst_rect.y + s->dst_rect.x * s->sdl_screen->format->BytesPerPixel;
s->frame.dst_x_offset = s->dst_rect.x * s->sdl_screen->format->BytesPerPixel;
s->frame.dst_bpp = s->sdl_screen->format->BytesPerPixel;
s->frame.dst_pitch = s->sdl_screen->pitch;
} else {
s->frame.data = (unsigned char*)*s->yuv_image->pixels;
s->frame.data_len = s->width * s->height * 2;
s->frame.dst_bpp = 2;
s->frame.dst_pitch = s->dst_linesize;
}
s->src_rect.w = s->width;
s->src_rect.h = s->height;
switch(color_spec) {
fprintf(stdout, "Setting SDL rect %dx%d - %d,%d.\n", s->dst_rect.w,
s->dst_rect.h, s->dst_rect.x, s->dst_rect.y);
s->frame.rshift = s->sdl_screen->format->Rshift;
s->frame.gshift = s->sdl_screen->format->Gshift;
s->frame.bshift = s->sdl_screen->format->Bshift;
s->frame.color_spec = s->c_info->codec;
s->frame.width = s->width;
s->frame.height = s->height;
s->frame.src_bpp = s->bpp;
s->frame.dst_linesize = s->dst_linesize;
if (s->rgb) {
s->frame.data = s->sdl_screen->pixels +
s->sdl_screen->pitch * s->dst_rect.y +
s->dst_rect.x * s->sdl_screen->format->BytesPerPixel;
s->frame.data_len =
s->sdl_screen->pitch * x_res_y -
s->sdl_screen->pitch * s->dst_rect.y +
s->dst_rect.x * s->sdl_screen->format->BytesPerPixel;
s->frame.dst_x_offset =
s->dst_rect.x * s->sdl_screen->format->BytesPerPixel;
s->frame.dst_bpp = s->sdl_screen->format->BytesPerPixel;
s->frame.dst_pitch = s->sdl_screen->pitch;
} else {
s->frame.data = (unsigned char *)*s->yuv_image->pixels;
s->frame.data_len = s->width * s->height * 2;
s->frame.dst_bpp = 2;
s->frame.dst_pitch = s->dst_linesize;
}
switch (color_spec) {
case R10k:
s->frame.decoder = vc_copyliner10k;
break;
@@ -359,251 +377,255 @@ reconfigure_screen(void *state, unsigned int width, unsigned int height, codec_t
s->frame.decoder = vc_copylineRGBA;
break;
}
}
}
void *
display_sdl_init(char *fmt)
void *display_sdl_init(char *fmt)
{
struct state_sdl *s;
int ret;
struct state_sdl *s;
int ret;
SDL_Surface *image;
SDL_Surface *temp;
SDL_Rect splash_src;
SDL_Rect splash_dest;
SDL_Surface *image;
SDL_Surface *temp;
SDL_Rect splash_src;
SDL_Rect splash_dest;
unsigned int i;
unsigned int i;
s = (struct state_sdl *) calloc(sizeof(struct state_sdl),1);
s->magic = MAGIC_SDL;
s = (struct state_sdl *)calloc(sizeof(struct state_sdl), 1);
s->magic = MAGIC_SDL;
if(fmt != NULL) {
if(strcmp(fmt, "help") == 0) {
show_help();
free(s);
return NULL;
}
if(strcmp(fmt, "fs") == 0) {
s->fs = 1;
fmt = NULL;
} else {
char *tmp = strdup(fmt);
char *tok;
tok = strtok(tmp, ":");
if(tok == NULL) {
if (fmt != NULL) {
if (strcmp(fmt, "help") == 0) {
show_help();
free(s);
free(tmp);
return NULL;
}
s->width = atol(tok);
tok = strtok(NULL, ":");
if(tok == NULL) {
show_help();
free(s);
free(tmp);
return NULL;
}
s->height = atol(tok);
tok = strtok(NULL, ":");
if(tok == NULL) {
show_help();
free(s);
free(tmp);
return NULL;
}
s->codec = 0xffffffff;
for(i = 0; codec_info[i].name != NULL; i++) {
if(strcmp(tok, codec_info[i].name) == 0) {
s->codec = codec_info[i].codec;
s->c_info = &codec_info[i];
s->rgb = codec_info[i].rgb;
if (strcmp(fmt, "fs") == 0) {
s->fs = 1;
fmt = NULL;
} else {
char *tmp = strdup(fmt);
char *tok;
tok = strtok(tmp, ":");
if (tok == NULL) {
show_help();
free(s);
free(tmp);
return NULL;
}
}
if(s->codec == 0xffffffff) {
fprintf(stderr, "SDL: unknown codec: %s\n", tok);
free(s);
free(tmp);
return NULL;
}
tok = strtok(NULL, ":");
while(tok != NULL) {
if(tok[0] == 'f' && tok[1] == 's') {
s->fs=1;
} else if(tok[0] == 'i') {
s->interlaced = 1;
} else if(tok[0] == 'd') {
s->deinterlace = 1;
s->width = atol(tok);
tok = strtok(NULL, ":");
if (tok == NULL) {
show_help();
free(s);
free(tmp);
return NULL;
}
s->height = atol(tok);
tok = strtok(NULL, ":");
if (tok == NULL) {
show_help();
free(s);
free(tmp);
return NULL;
}
s->codec = 0xffffffff;
for (i = 0; codec_info[i].name != NULL; i++) {
if (strcmp(tok, codec_info[i].name) == 0) {
s->codec = codec_info[i].codec;
s->c_info = &codec_info[i];
s->rgb = codec_info[i].rgb;
}
}
if (s->codec == 0xffffffff) {
fprintf(stderr, "SDL: unknown codec: %s\n",
tok);
free(s);
free(tmp);
return NULL;
}
tok = strtok(NULL, ":");
}
free(tmp);
while (tok != NULL) {
if (tok[0] == 'f' && tok[1] == 's') {
s->fs = 1;
} else if (tok[0] == 'i') {
s->interlaced = 1;
} else if (tok[0] == 'd') {
s->deinterlace = 1;
}
tok = strtok(NULL, ":");
}
free(tmp);
if(s->width <= 0 || s->height <= 0) {
printf("SDL: failed to parse config options: '%s'\n", fmt);
free(s);
return NULL;
if (s->width <= 0 || s->height <= 0) {
printf
("SDL: failed to parse config options: '%s'\n",
fmt);
free(s);
return NULL;
}
s->bpp = s->c_info->bpp;
printf("SDL setup: %dx%d codec %s\n", s->width,
s->height, s->c_info->name);
}
s->bpp = s->c_info->bpp;
printf("SDL setup: %dx%d codec %s\n", s->width, s->height, s->c_info->name);
}
}
asm("emms\n");
asm("emms\n");
s->semaphore = SDL_CreateSemaphore(0);
s->semaphore = SDL_CreateSemaphore(0);
if (!(s->display = XOpenDisplay(NULL))) {
if (!(s->display = XOpenDisplay(NULL))) {
printf("Unable to open display.\n");
return NULL;
}
}
#ifdef HAVE_MACOSX
/* Startup function to call when running Cocoa code from a Carbon application.
* Whatever the fuck that means.
* Avoids uncaught exception (1002) when creating CGSWindow */
NSApplicationLoad();
/* Startup function to call when running Cocoa code from a Carbon application.
* Whatever the fuck that means.
* Avoids uncaught exception (1002) when creating CGSWindow */
NSApplicationLoad();
#endif
ret = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE);
if (ret < 0) {
printf("Unable to initialize SDL.\n");
return NULL;
}
if(fmt != NULL) {
/*FIXME: kill hd_size at all, use another approach avoiding globals */
int w = s->width;
if(s->c_info->h_align) {
w = ((w+s->c_info->h_align-1)/s->c_info->h_align)*s->c_info->h_align;
ret = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE);
if (ret < 0) {
printf("Unable to initialize SDL.\n");
return NULL;
}
hd_size_x = w;
hd_size_y = s->height;
reconfigure_screen(s, w, s->height, s->c_info->codec);
temp = SDL_LoadBMP("/usr/share/uv-0.3.1/uv_startup.bmp");
if (temp == NULL) {
temp = SDL_LoadBMP("/usr/local/share/uv-0.3.1/uv_startup.bmp");
if (temp == NULL) {
temp = SDL_LoadBMP("uv_startup.bmp");
if (temp == NULL) {
printf("Unable to load splash bitmap: uv_startup.bmp.\n");
if (fmt != NULL) {
/*FIXME: kill hd_size at all, use another approach avoiding globals */
int w = s->width;
if (s->c_info->h_align) {
w = ((w + s->c_info->h_align -
1) / s->c_info->h_align) * s->c_info->h_align;
}
hd_size_x = w;
hd_size_y = s->height;
reconfigure_screen(s, w, s->height, s->c_info->codec);
temp = SDL_LoadBMP("/usr/share/uv-0.3.1/uv_startup.bmp");
if (temp == NULL) {
temp =
SDL_LoadBMP
("/usr/local/share/uv-0.3.1/uv_startup.bmp");
if (temp == NULL) {
temp = SDL_LoadBMP("uv_startup.bmp");
if (temp == NULL) {
printf
("Unable to load splash bitmap: uv_startup.bmp.\n");
}
}
}
if (temp != NULL) {
image = SDL_DisplayFormat(temp);
SDL_FreeSurface(temp);
splash_src.x = 0;
splash_src.y = 0;
splash_src.w = image->w;
splash_src.h = image->h;
splash_dest.x = (int)((s->width - splash_src.w) / 2);
splash_dest.y =
(int)((s->height - splash_src.h) / 2) + 60;
splash_dest.w = image->w;
splash_dest.h = image->h;
SDL_BlitSurface(image, &splash_src, s->sdl_screen,
&splash_dest);
SDL_Flip(s->sdl_screen);
}
}
}
if (temp != NULL) {
image = SDL_DisplayFormat(temp);
SDL_FreeSurface(temp);
splash_src.x = 0;
splash_src.y = 0;
splash_src.w = image->w;
splash_src.h = image->h;
splash_dest.x = (int)((s->width - splash_src.w) / 2);
splash_dest.y = (int)((s->height - splash_src.h) / 2) + 60;
splash_dest.w = image->w;
splash_dest.h = image->h;
SDL_BlitSurface(image, &splash_src, s->sdl_screen, &splash_dest);
SDL_Flip(s->sdl_screen);
}
}
s->frame.width = 0;
s->frame.height = 0;
s->frame.color_spec = 0;
s->frame.state = s;
s->frame.reconfigure = reconfigure_screen;
s->frame.width = 0;
s->frame.height = 0;
s->frame.color_spec = 0;
s->frame.state = s;
s->frame.reconfigure = reconfigure_screen;
if (pthread_create(&(s->thread_id), NULL, display_thread_sdl, (void *) s) != 0) {
perror("Unable to create display thread\n");
return NULL;
}
if (pthread_create(&(s->thread_id), NULL, display_thread_sdl, (void *)s)
!= 0) {
perror("Unable to create display thread\n");
return NULL;
}
return (void *)s;
return (void *)s;
}
void
display_sdl_done(void *state)
void display_sdl_done(void *state)
{
struct state_sdl *s = (struct state_sdl *) state;
struct state_sdl *s = (struct state_sdl *)state;
assert(s->magic == MAGIC_SDL);
assert(s->magic == MAGIC_SDL);
/*FIXME: free all the stuff */
SDL_ShowCursor(SDL_ENABLE);
/*FIXME: free all the stuff */
SDL_ShowCursor(SDL_ENABLE);
SDL_Quit();
SDL_Quit();
}
struct video_frame *
display_sdl_getf(void *state)
struct video_frame *display_sdl_getf(void *state)
{
struct state_sdl *s = (struct state_sdl *) state;
assert(s->magic == MAGIC_SDL);
return &s->frame;
struct state_sdl *s = (struct state_sdl *)state;
assert(s->magic == MAGIC_SDL);
return &s->frame;
}
int
display_sdl_putf(void *state, char *frame)
int display_sdl_putf(void *state, char *frame)
{
int tmp;
struct state_sdl *s = (struct state_sdl *) state;
int tmp;
struct state_sdl *s = (struct state_sdl *)state;
assert(s->magic == MAGIC_SDL);
assert(frame != NULL);
assert(s->magic == MAGIC_SDL);
assert(frame != NULL);
SDL_SemPost(s->semaphore);
tmp = SDL_SemValue(s->semaphore);
if(tmp > 1)
printf("%d frame(s) dropped!\n", tmp);
return 0;
SDL_SemPost(s->semaphore);
tmp = SDL_SemValue(s->semaphore);
if (tmp > 1)
printf("%d frame(s) dropped!\n", tmp);
return 0;
}
display_colour_t
display_sdl_colour(void *state)
display_colour_t display_sdl_colour(void *state)
{
struct state_sdl *s = (struct state_sdl *) state;
assert(s->magic == MAGIC_SDL);
return DC_YUV;
struct state_sdl *s = (struct state_sdl *)state;
assert(s->magic == MAGIC_SDL);
return DC_YUV;
}
display_type_t *
display_sdl_probe(void)
display_type_t *display_sdl_probe(void)
{
display_type_t *dt;
display_format_t *dformat;
display_type_t *dt;
display_format_t *dformat;
dformat = malloc(4 * sizeof(display_format_t));
dformat[0].size = DS_176x144;
dformat[0].colour_mode = DC_YUV;
dformat[0].num_images = 1;
dformat[1].size = DS_352x288;
dformat[1].colour_mode = DC_YUV;
dformat[1].num_images = 1;
dformat[2].size = DS_702x576;
dformat[2].colour_mode = DC_YUV;
dformat[2].num_images = 1;
dformat[3].size = DS_1280x720;
dformat[3].colour_mode = DC_YUV;
dformat[3].num_images = 1;
dformat = malloc(4 * sizeof(display_format_t));
dformat[0].size = DS_176x144;
dformat[0].colour_mode = DC_YUV;
dformat[0].num_images = 1;
dformat[1].size = DS_352x288;
dformat[1].colour_mode = DC_YUV;
dformat[1].num_images = 1;
dformat[2].size = DS_702x576;
dformat[2].colour_mode = DC_YUV;
dformat[2].num_images = 1;
dformat[3].size = DS_1280x720;
dformat[3].colour_mode = DC_YUV;
dformat[3].num_images = 1;
dt = malloc(sizeof(display_type_t));
if (dt != NULL) {
dt->id = DISPLAY_SDL_ID;
dt->name = "sdl";
dt->description = "SDL with Xvideo extension";
dt->formats = dformat;
dt->num_formats = 4;
}
return dt;
dt = malloc(sizeof(display_type_t));
if (dt != NULL) {
dt->id = DISPLAY_SDL_ID;
dt->name = "sdl";
dt->description = "SDL with Xvideo extension";
dt->formats = dformat;
dt->num_formats = 4;
}
return dt;
}
#endif /* X_DISPLAY_MISSING */
#endif /* X_DISPLAY_MISSING */

View File

@@ -51,11 +51,10 @@
#define DISPLAY_SDL_ID 0xba370a2b
display_type_t *display_sdl_probe(void);
void *display_sdl_init(char *fmt);
void display_sdl_done(void *state);
struct video_frame *display_sdl_getf(void *state);
int display_sdl_putf(void *state, char *frame);
display_colour_t display_sdl_colour(void *state);
int display_sdl_handle_events(void *s);
display_type_t *display_sdl_probe (void);
void *display_sdl_init (char *fmt);
void display_sdl_done (void *state);
struct video_frame *display_sdl_getf (void *state);
int display_sdl_putf (void *state, char *frame);
display_colour_t display_sdl_colour (void *state);
int display_sdl_handle_events (void *s);

View File

@@ -53,7 +53,7 @@
#include "config_unix.h"
#include "config_win32.h"
#ifndef X_DISPLAY_MISSING /* Don't try to compile if X is not present */
#ifndef X_DISPLAY_MISSING /* Don't try to compile if X is not present */
#include "debug.h"
#include "video_display.h"
@@ -75,155 +75,166 @@
#define MAGIC_X11 0xcafebabe
struct state_x11 {
Display *display;
Window window;
GC gc;
int vw_depth;
Visual *vw_visual;
XImage *vw_image;
XShmSegmentInfo vw_shm_segment;
int xv_port;
uint32_t magic; /* For debugging */
Display *display;
Window window;
GC gc;
int vw_depth;
Visual *vw_visual;
XImage *vw_image;
XShmSegmentInfo vw_shm_segment;
int xv_port;
uint32_t magic; /* For debugging */
};
void *
display_x11_init(void)
void *display_x11_init(void)
{
struct state_x11 *s;
struct state_x11 *s;
s = (struct state_x11 *) malloc(sizeof(struct state_x11));
s->magic = MAGIC_X11;
s = (struct state_x11 *)malloc(sizeof(struct state_x11));
s->magic = MAGIC_X11;
/* Create a bare window to draw into... */
/* Create a bare window to draw into... */
if (!(s->display = XOpenDisplay(NULL))) {
printf("Unable to open display.\n");
abort();
}
s->window = XCreateSimpleWindow(s->display, DefaultRootWindow(s->display), 0, 0, HD_WIDTH, HD_HEIGHT, 0, BlackPixel(s->display, DefaultScreen(s->display)), BlackPixel(s->display, DefaultScreen(s->display)));
s->window =
XCreateSimpleWindow(s->display, DefaultRootWindow(s->display), 0, 0,
HD_WIDTH, HD_HEIGHT, 0, BlackPixel(s->display,
DefaultScreen
(s->
display)),
BlackPixel(s->display,
DefaultScreen(s->display)));
if (s->window == 0) {
abort();
};
abort();
};
XMapWindow(s->display, s->window);
XStoreName(s->display, s->window, "UltraGrid");
XStoreName(s->display, s->window, "UltraGrid");
s->vw_depth = DefaultDepth(s->display, DefaultScreen(s->display));
s->vw_depth = DefaultDepth(s->display, DefaultScreen(s->display));
s->vw_visual = DefaultVisual(s->display, DefaultScreen(s->display));
/* For now, we only support 24-bit TrueColor displays... */
if (s->vw_depth != 24) {
printf("Unable to open display: not 24 bit colour\n");
return NULL;
}
if (s->vw_visual->class != TrueColor) {
printf("Unable to open display: not TrueColor visual\n");
return NULL;
}
/* For now, we only support 24-bit TrueColor displays... */
if (s->vw_depth != 24) {
printf("Unable to open display: not 24 bit colour\n");
return NULL;
}
if (s->vw_visual->class != TrueColor) {
printf("Unable to open display: not TrueColor visual\n");
return NULL;
}
/* Do the shared memory magic... */
s->vw_image = XShmCreateImage(s->display, s->vw_visual, s->vw_depth, ZPixmap, NULL, &s->vw_shm_segment, HD_WIDTH, HD_HEIGHT);
debug_msg("vw_image = %p\n", s->vw_image);
debug_msg("vw_image->width = %d\n", s->vw_image->width);
debug_msg("vw_image->height = %d\n", s->vw_image->height);
if (s->vw_image->width != (int)HD_WIDTH) {
printf("Display does not support %d pixel wide shared memory images\n", HD_WIDTH);
abort();
}
if (s->vw_image->height != (int)HD_HEIGHT) {
printf("Display does not support %d pixel tall shared memory images\n", HD_WIDTH);
abort();
}
/* Do the shared memory magic... */
s->vw_image =
XShmCreateImage(s->display, s->vw_visual, s->vw_depth, ZPixmap,
NULL, &s->vw_shm_segment, HD_WIDTH, HD_HEIGHT);
debug_msg("vw_image = %p\n", s->vw_image);
debug_msg("vw_image->width = %d\n", s->vw_image->width);
debug_msg("vw_image->height = %d\n", s->vw_image->height);
if (s->vw_image->width != (int)HD_WIDTH) {
printf
("Display does not support %d pixel wide shared memory images\n",
HD_WIDTH);
abort();
}
if (s->vw_image->height != (int)HD_HEIGHT) {
printf
("Display does not support %d pixel tall shared memory images\n",
HD_WIDTH);
abort();
}
s->vw_shm_segment.shmid = shmget(IPC_PRIVATE, s->vw_image->bytes_per_line * s->vw_image->height, IPC_CREAT|0777);
s->vw_shm_segment.shmaddr = shmat(s->vw_shm_segment.shmid, 0, 0);
s->vw_shm_segment.readOnly = False;
debug_msg("vw_shm_segment.shmid = %d\n", s->vw_shm_segment.shmid);
debug_msg("vw_shm_segment.shmaddr = %d\n", s->vw_shm_segment.shmaddr);
s->vw_shm_segment.shmid =
shmget(IPC_PRIVATE,
s->vw_image->bytes_per_line * s->vw_image->height,
IPC_CREAT | 0777);
s->vw_shm_segment.shmaddr = shmat(s->vw_shm_segment.shmid, 0, 0);
s->vw_shm_segment.readOnly = False;
debug_msg("vw_shm_segment.shmid = %d\n", s->vw_shm_segment.shmid);
debug_msg("vw_shm_segment.shmaddr = %d\n",
s->vw_shm_segment.shmaddr);
s->vw_image->data = s->vw_shm_segment.shmaddr;
s->vw_image->data = s->vw_shm_segment.shmaddr;
if (XShmAttach(s->display, &s->vw_shm_segment) == 0) {
printf("Cannot attach shared memory segment\n");
abort();
}
printf("Cannot attach shared memory segment\n");
abort();
}
/* Get our window onto the screen... */
XFlush(s->display);
/* Get our window onto the screen... */
XFlush(s->display);
s->gc = XCreateGC(s->display, s->window, 0, NULL);
s->gc = XCreateGC(s->display, s->window, 0, NULL);
printf ("X11 init done\n");
return (void *) s;
return NULL;
printf("X11 init done\n");
return (void *)s;
return NULL;
}
void
display_x11_done(void *state)
void display_x11_done(void *state)
{
struct state_x11 *s = (struct state_x11 *) state;
struct state_x11 *s = (struct state_x11 *)state;
assert(s->magic == MAGIC_X11);
assert(s->magic == MAGIC_X11);
XShmDetach(s->display, &(s->vw_shm_segment));
XDestroyImage(s->vw_image);
shmdt(s->vw_shm_segment.shmaddr);
shmctl(s->vw_shm_segment.shmid, IPC_RMID, 0);
XShmDetach(s->display, &(s->vw_shm_segment));
XDestroyImage(s->vw_image);
shmdt(s->vw_shm_segment.shmaddr);
shmctl(s->vw_shm_segment.shmid, IPC_RMID, 0);
}
char *
display_x11_getf(void *state)
char *display_x11_getf(void *state)
{
struct state_x11 *s = (struct state_x11 *) state;
assert(s->magic == MAGIC_X11);
return s->vw_image->data;
struct state_x11 *s = (struct state_x11 *)state;
assert(s->magic == MAGIC_X11);
return s->vw_image->data;
}
int
display_x11_putf(void *state, char *frame)
int display_x11_putf(void *state, char *frame)
{
struct state_x11 *s = (struct state_x11 *) state;
struct state_x11 *s = (struct state_x11 *)state;
assert(s->magic == MAGIC_X11);
assert(frame == s->vw_image->data);
XShmPutImage(s->display, s->window, s->gc, s->vw_image, 0, 0, 0, 0, s->vw_image->width, s->vw_image->height, True);
XFlush(s->display);
return 0;
assert(s->magic == MAGIC_X11);
assert(frame == s->vw_image->data);
XShmPutImage(s->display, s->window, s->gc, s->vw_image, 0, 0, 0, 0,
s->vw_image->width, s->vw_image->height, True);
XFlush(s->display);
return 0;
}
display_colour_t
display_x11_colour(void *state)
display_colour_t display_x11_colour(void *state)
{
struct state_x11 *s = (struct state_x11 *) state;
assert(s->magic == MAGIC_X11);
return DC_YUV;
struct state_x11 *s = (struct state_x11 *)state;
assert(s->magic == MAGIC_X11);
return DC_YUV;
}
display_type_t *
display_x11_probe(void)
display_type_t *display_x11_probe(void)
{
display_type_t *dt;
display_format_t *dformat;
display_type_t *dt;
display_format_t *dformat;
dformat = malloc(3 * sizeof(display_format_t));
dformat[0].size = DS_176x144;
dformat[0].colour_mode = DC_RGB;
dformat[0].num_images = -1;
dformat[1].size = DS_352x288;
dformat[1].colour_mode = DC_RGB;
dformat[1].num_images = -1;
dformat[2].size = DS_702x576;
dformat[2].colour_mode = DC_RGB;
dformat[2].num_images = -1;
dformat = malloc(3 * sizeof(display_format_t));
dformat[0].size = DS_176x144;
dformat[0].colour_mode = DC_RGB;
dformat[0].num_images = -1;
dformat[1].size = DS_352x288;
dformat[1].colour_mode = DC_RGB;
dformat[1].num_images = -1;
dformat[2].size = DS_702x576;
dformat[2].colour_mode = DC_RGB;
dformat[2].num_images = -1;
dt = malloc(sizeof(display_type_t));
if (dt != NULL) {
dt->id = DISPLAY_X11_ID;
dt->name = "x11";
dt->description = "X Window System";
dt->formats = dformat;
dt->num_formats = 3;
}
return dt;
dt = malloc(sizeof(display_type_t));
if (dt != NULL) {
dt->id = DISPLAY_X11_ID;
dt->name = "x11";
dt->description = "X Window System";
dt->formats = dformat;
dt->num_formats = 3;
}
return dt;
}
#endif /* X_DISPLAY_MISSING */
#endif /* X_DISPLAY_MISSING */

View File

@@ -53,7 +53,7 @@
#include "config_unix.h"
#include "config_win32.h"
#ifndef X_DISPLAY_MISSING /* Don't try to compile if X is not present */
#ifndef X_DISPLAY_MISSING /* Don't try to compile if X is not present */
#include "debug.h"
#include "video_display.h"
@@ -73,296 +73,325 @@
#include <X11/extensions/XShm.h>
#include <host.h>
extern int XShmQueryExtension(Display*);
extern int XShmGetEventBase(Display*);
extern XvImage *XvShmCreateImage(Display*, XvPortID, int, char*, int, int, XShmSegmentInfo*);
extern int XShmQueryExtension(Display *);
extern int XShmGetEventBase(Display *);
extern XvImage *XvShmCreateImage(Display *, XvPortID, int, char *, int, int,
XShmSegmentInfo *);
#define HD_WIDTH hd_size_x
#define HD_HEIGHT hd_size_y
#define MAGIC_XV DISPLAY_XV_ID
struct state_xv {
Display *display;
Window window;
GC gc;
int vw_depth;
Visual *vw_visual;
XvImage *vw_image[3];
XShmSegmentInfo vw_shm_segment[2];
int image_display, image_network;
XvAdaptorInfo *ai;
int xv_port;
/* Thread related information follows... */
pthread_t thread_id;
pthread_mutex_t lock;
pthread_cond_t boss_cv;
pthread_cond_t worker_cv;
int work_to_do;
int boss_waiting;
int worker_waiting;
/* For debugging... */
uint32_t magic;
Display *display;
Window window;
GC gc;
int vw_depth;
Visual *vw_visual;
XvImage *vw_image[3];
XShmSegmentInfo vw_shm_segment[2];
int image_display, image_network;
XvAdaptorInfo *ai;
int xv_port;
/* Thread related information follows... */
pthread_t thread_id;
pthread_mutex_t lock;
pthread_cond_t boss_cv;
pthread_cond_t worker_cv;
int work_to_do;
int boss_waiting;
int worker_waiting;
/* For debugging... */
uint32_t magic;
};
static void*
display_thread_xv(void *arg)
static void *display_thread_xv(void *arg)
{
struct state_xv *s = (struct state_xv *) arg;
struct state_xv *s = (struct state_xv *)arg;
while (1) {
pthread_mutex_lock(&s->lock);
while (1) {
pthread_mutex_lock(&s->lock);
while (s->work_to_do == FALSE) {
s->worker_waiting = TRUE;
pthread_cond_wait(&s->worker_cv, &s->lock);
s->worker_waiting = FALSE;
}
while (s->work_to_do == FALSE) {
s->worker_waiting = TRUE;
pthread_cond_wait(&s->worker_cv, &s->lock);
s->worker_waiting = FALSE;
}
s->work_to_do = FALSE;
s->work_to_do = FALSE;
if (s->boss_waiting) {
pthread_cond_signal(&s->boss_cv);
}
pthread_mutex_unlock(&s->lock);
if (s->boss_waiting) {
pthread_cond_signal(&s->boss_cv);
}
pthread_mutex_unlock(&s->lock);
XvShmPutImage(s->display, s->xv_port, s->window, s->gc, s->vw_image[s->image_display], 0, 0,
s->vw_image[s->image_display]->width, s->vw_image[s->image_display]->height, 0, 0, HD_WIDTH, HD_HEIGHT, False);
XvShmPutImage(s->display, s->xv_port, s->window, s->gc,
s->vw_image[s->image_display], 0, 0,
s->vw_image[s->image_display]->width,
s->vw_image[s->image_display]->height, 0, 0,
HD_WIDTH, HD_HEIGHT, False);
XFlush(s->display);
}
return NULL;
XFlush(s->display);
}
return NULL;
}
void *
display_xv_init(void)
void *display_xv_init(void)
{
struct state_xv *s;
unsigned int p_version, p_release, p_request_base, p_event_base, p_error_base, p;
unsigned int p_num_adaptors, i, j;
struct state_xv *s;
unsigned int p_version, p_release, p_request_base, p_event_base,
p_error_base, p;
unsigned int p_num_adaptors, i, j;
s = (struct state_xv *) malloc(sizeof(struct state_xv));
s->magic = MAGIC_XV;
s->xv_port = -1;
s = (struct state_xv *)malloc(sizeof(struct state_xv));
s->magic = MAGIC_XV;
s->xv_port = -1;
if (!(s->display = XOpenDisplay(NULL))) {
printf("Unable to open display.\n");
return NULL;
}
if (!(s->display = XOpenDisplay(NULL))) {
printf("Unable to open display.\n");
return NULL;
}
/* Do we support the Xv extension? */
if (XvQueryExtension(s->display, &p_version, &p_release, &p_request_base, &p_event_base, &p_error_base) != Success) {
printf("Cannot activate Xv extension\n");
abort();
}
debug_msg("Xv version = %u.%u\n", p_version, p_release);
debug_msg("Xv request base = %u\n", p_request_base);
debug_msg("Xv event base = %u\n", p_event_base);
debug_msg("Xv error base = %u\n", p_error_base);
if (XvQueryAdaptors(s->display, DefaultRootWindow(s->display), &p_num_adaptors, &s->ai) != Success) {
printf("Cannot query Xv adaptors\n");
abort();
}
s->xv_port = 0;
debug_msg("Xv adaptor count = %d\n", p_num_adaptors);
for (i = 0; i < p_num_adaptors && s->xv_port == 0; i++) {
debug_msg("Xv adaptor %d name = %s\n", i, s->ai[i].name);
debug_msg("Xv adaptor %d type = %s%s%s%s%s\n", i, (s->ai[i].type & XvInputMask) ? "[input] " : "",
(s->ai[i].type & XvOutputMask) ? "[output] " : "",
(s->ai[i].type & XvVideoMask) ? "[video] " : "",
(s->ai[i].type & XvStillMask) ? "[still] " : "",
(s->ai[i].type & XvImageMask) ? "[image] " : "");
for (p = s->ai[i].base_id; p < s->ai[i].base_id + s->ai[i].num_ports; p++) {
unsigned int encodings;
int formats;
int k;
XvEncodingInfo *ei;
XvImageFormatValues *fo;
/* Do we support the Xv extension? */
if (XvQueryExtension
(s->display, &p_version, &p_release, &p_request_base, &p_event_base,
&p_error_base) != Success) {
printf("Cannot activate Xv extension\n");
abort();
}
debug_msg("Xv version = %u.%u\n", p_version, p_release);
debug_msg("Xv request base = %u\n", p_request_base);
debug_msg("Xv event base = %u\n", p_event_base);
debug_msg("Xv error base = %u\n", p_error_base);
if (XvQueryAdaptors
(s->display, DefaultRootWindow(s->display), &p_num_adaptors,
&s->ai) != Success) {
printf("Cannot query Xv adaptors\n");
abort();
}
s->xv_port = 0;
debug_msg("Xv adaptor count = %d\n", p_num_adaptors);
for (i = 0; i < p_num_adaptors && s->xv_port == 0; i++) {
debug_msg("Xv adaptor %d name = %s\n", i, s->ai[i].name);
debug_msg("Xv adaptor %d type = %s%s%s%s%s\n", i,
(s->ai[i].type & XvInputMask) ? "[input] " : "",
(s->ai[i].type & XvOutputMask) ? "[output] " : "",
(s->ai[i].type & XvVideoMask) ? "[video] " : "",
(s->ai[i].type & XvStillMask) ? "[still] " : "",
(s->ai[i].type & XvImageMask) ? "[image] " : "");
for (p = s->ai[i].base_id;
p < s->ai[i].base_id + s->ai[i].num_ports; p++) {
unsigned int encodings;
int formats;
int k;
XvEncodingInfo *ei;
XvImageFormatValues *fo;
if(!XvGrabPort(s->display, p, CurrentTime)) {
debug_msg("Grabed port: %d\n", p);
s->xv_port = p;
} else {
debug_msg("Cannot grab port: %d\n", p);
abort();
}
if (!XvGrabPort(s->display, p, CurrentTime)) {
debug_msg("Grabed port: %d\n", p);
s->xv_port = p;
} else {
debug_msg("Cannot grab port: %d\n", p);
abort();
}
if (XvQueryEncodings(s->display, p, &encodings, &ei) != Success) {
printf("Cannot query Xv encodings\n");
abort();
}
for (j = 0; j < encodings; j++) {
debug_msg("Xv adaptor %d port %d coding %d = %s\n", i, p - s->ai[i].base_id, j, ei[j].name);
}
XvFreeEncodingInfo(ei);
fo = XvListImageFormats(s->display, p, &formats);
for (k = 0; k < formats; k++) {
debug_msg("Xv adaptor %d port %d format %d = 0x%08lx %s\n", i, p - s->ai[i].base_id, k, fo[k].id, fo[k].guid);
}
if (fo != NULL) {
XFree(fo);
}
}
}
if (XvQueryEncodings(s->display, p, &encodings, &ei) !=
Success) {
printf("Cannot query Xv encodings\n");
abort();
}
for (j = 0; j < encodings; j++) {
debug_msg
("Xv adaptor %d port %d coding %d = %s\n",
i, p - s->ai[i].base_id, j, ei[j].name);
}
XvFreeEncodingInfo(ei);
fo = XvListImageFormats(s->display, p, &formats);
for (k = 0; k < formats; k++) {
debug_msg
("Xv adaptor %d port %d format %d = 0x%08lx %s\n",
i, p - s->ai[i].base_id, k, fo[k].id,
fo[k].guid);
}
if (fo != NULL) {
XFree(fo);
}
}
}
s->window = XCreateSimpleWindow(s->display, DefaultRootWindow(s->display), 0, 0, HD_WIDTH, HD_HEIGHT, 0, XWhitePixel(s->display, DefaultScreen(s->display)), XBlackPixel(s->display, DefaultScreen(s->display)));
s->window =
XCreateSimpleWindow(s->display, DefaultRootWindow(s->display), 0, 0,
HD_WIDTH, HD_HEIGHT, 0, XWhitePixel(s->display,
DefaultScreen
(s->
display)),
XBlackPixel(s->display,
DefaultScreen(s->display)));
s->gc = XCreateGC(s->display, s->window, 0, 0);
s->gc = XCreateGC(s->display, s->window, 0, 0);
XMapWindow(s->display, s->window);
XMapWindow(s->display, s->window);
XStoreName(s->display, s->window, "UltraGrid");
XStoreName(s->display, s->window, "UltraGrid");
/* Create the image buffer, shared with the X server... */
for (i = 0; i < 2; i++) {
s->vw_image[i] = XvShmCreateImage(s->display, s->xv_port, 0x59565955, 0, HD_WIDTH, HD_HEIGHT, &s->vw_shm_segment[i]);
if (s->vw_image[i] == NULL) {
printf("Cannot create XV shared memory image\n");
abort();
}
debug_msg("vw_image = %p\n", s->vw_image[i]);
debug_msg("vw_image->width = %d\n", s->vw_image[i]->width);
debug_msg("vw_image->height = %d\n", s->vw_image[i]->height);
debug_msg("vw_image->data_size = %d\n", s->vw_image[i]->data_size);
if (s->vw_image[i]->width != (int)HD_WIDTH) {
printf("Display does not support %d pixel wide Xvideo shared memory images\n", HD_WIDTH);
abort();
}
if (s->vw_image[i]->height != (int)HD_HEIGHT) {
printf("Display does not support %d pixel tall Xvideo shared memory images\n", HD_WIDTH);
abort();
}
/* Create the image buffer, shared with the X server... */
for (i = 0; i < 2; i++) {
s->vw_image[i] =
XvShmCreateImage(s->display, s->xv_port, 0x59565955, 0,
HD_WIDTH, HD_HEIGHT,
&s->vw_shm_segment[i]);
if (s->vw_image[i] == NULL) {
printf("Cannot create XV shared memory image\n");
abort();
}
debug_msg("vw_image = %p\n", s->vw_image[i]);
debug_msg("vw_image->width = %d\n",
s->vw_image[i]->width);
debug_msg("vw_image->height = %d\n",
s->vw_image[i]->height);
debug_msg("vw_image->data_size = %d\n",
s->vw_image[i]->data_size);
if (s->vw_image[i]->width != (int)HD_WIDTH) {
printf
("Display does not support %d pixel wide Xvideo shared memory images\n",
HD_WIDTH);
abort();
}
if (s->vw_image[i]->height != (int)HD_HEIGHT) {
printf
("Display does not support %d pixel tall Xvideo shared memory images\n",
HD_WIDTH);
abort();
}
s->vw_shm_segment[i].shmid = shmget(IPC_PRIVATE, s->vw_image[i]->data_size, IPC_CREAT|0777);
s->vw_shm_segment[i].shmaddr = shmat(s->vw_shm_segment[i].shmid, 0, 0);
s->vw_shm_segment[i].readOnly = False;
debug_msg("vw_shm_segment.shmid = %d\n", s->vw_shm_segment[i].shmid);
debug_msg("vw_shm_segment.shmaddr = %d\n", s->vw_shm_segment[i].shmaddr);
s->vw_shm_segment[i].shmid =
shmget(IPC_PRIVATE, s->vw_image[i]->data_size,
IPC_CREAT | 0777);
s->vw_shm_segment[i].shmaddr =
shmat(s->vw_shm_segment[i].shmid, 0, 0);
s->vw_shm_segment[i].readOnly = False;
debug_msg("vw_shm_segment.shmid = %d\n",
s->vw_shm_segment[i].shmid);
debug_msg("vw_shm_segment.shmaddr = %d\n",
s->vw_shm_segment[i].shmaddr);
s->vw_image[i]->data = s->vw_shm_segment[i].shmaddr;
s->vw_image[i]->data = s->vw_shm_segment[i].shmaddr;
if (XShmAttach(s->display, &s->vw_shm_segment[i]) == 0) {
printf("Cannot attach shared memory segment\n");
abort();
}
}
s->image_network = 0;
s->image_display = 1;
if (XShmAttach(s->display, &s->vw_shm_segment[i]) == 0) {
printf("Cannot attach shared memory segment\n");
abort();
}
}
s->image_network = 0;
s->image_display = 1;
/* Get our window onto the screen... */
XFlush(s->display);
/* Get our window onto the screen... */
XFlush(s->display);
pthread_mutex_init(&s->lock, NULL);
pthread_cond_init(&s->boss_cv, NULL);
pthread_cond_init(&s->worker_cv, NULL);
s->work_to_do = FALSE;
s->boss_waiting = FALSE;
s->worker_waiting = TRUE;
if (pthread_create(&(s->thread_id), NULL, display_thread_xv, (void *) s) != 0) {
perror("Unable to create display thread\n");
return NULL;
}
pthread_mutex_init(&s->lock, NULL);
pthread_cond_init(&s->boss_cv, NULL);
pthread_cond_init(&s->worker_cv, NULL);
s->work_to_do = FALSE;
s->boss_waiting = FALSE;
s->worker_waiting = TRUE;
if (pthread_create(&(s->thread_id), NULL, display_thread_xv, (void *)s)
!= 0) {
perror("Unable to create display thread\n");
return NULL;
}
debug_msg("Window initialized %p\n", s);
return (void *) s;
debug_msg("Window initialized %p\n", s);
return (void *)s;
}
void
display_xv_done(void *state)
void display_xv_done(void *state)
{
int i;
struct state_xv *s = (struct state_xv *) state;
int i;
struct state_xv *s = (struct state_xv *)state;
assert(s->magic == MAGIC_XV);
assert(s->magic == MAGIC_XV);
for (i = 0; i < 2; i++) {
XShmDetach(s->display, &(s->vw_shm_segment[i]));
shmdt(s->vw_shm_segment[i].shmaddr);
shmctl(s->vw_shm_segment[i].shmid, IPC_RMID, 0);
//XDestroyImage(s->vw_image[i]);
}
XvFreeAdaptorInfo(s->ai);
for (i = 0; i < 2; i++) {
XShmDetach(s->display, &(s->vw_shm_segment[i]));
shmdt(s->vw_shm_segment[i].shmaddr);
shmctl(s->vw_shm_segment[i].shmid, IPC_RMID, 0);
//XDestroyImage(s->vw_image[i]);
}
XvFreeAdaptorInfo(s->ai);
}
char *
display_xv_getf(void *state)
char *display_xv_getf(void *state)
{
struct state_xv *s = (struct state_xv *) state;
assert(s->magic == MAGIC_XV);
return s->vw_image[s->image_network]->data;
struct state_xv *s = (struct state_xv *)state;
assert(s->magic == MAGIC_XV);
return s->vw_image[s->image_network]->data;
}
int
display_xv_putf(void *state, char *frame)
int display_xv_putf(void *state, char *frame)
{
int tmp;
struct state_xv *s = (struct state_xv *) state;
int tmp;
struct state_xv *s = (struct state_xv *)state;
assert(s->magic == MAGIC_XV);
assert(frame == s->vw_image[s->image_network]->data);
assert(s->magic == MAGIC_XV);
assert(frame == s->vw_image[s->image_network]->data);
pthread_mutex_lock(&s->lock);
/* Wait for the worker to finish... */
while (s->work_to_do) {
s->boss_waiting = TRUE;
pthread_cond_wait(&s->boss_cv, &s->lock);
s->boss_waiting = FALSE;
}
pthread_mutex_lock(&s->lock);
/* Wait for the worker to finish... */
while (s->work_to_do) {
s->boss_waiting = TRUE;
pthread_cond_wait(&s->boss_cv, &s->lock);
s->boss_waiting = FALSE;
}
/* ...and give it more to do... */
tmp = s->image_display;
s->image_display = s->image_network;
s->image_network = tmp;
s->work_to_do = TRUE;
/* ...and give it more to do... */
tmp = s->image_display;
s->image_display = s->image_network;
s->image_network = tmp;
s->work_to_do = TRUE;
/* ...and signal the worker */
if (s->worker_waiting) {
pthread_cond_signal(&s->worker_cv);
}
pthread_mutex_unlock(&s->lock);
return 0;
/* ...and signal the worker */
if (s->worker_waiting) {
pthread_cond_signal(&s->worker_cv);
}
pthread_mutex_unlock(&s->lock);
return 0;
}
display_colour_t
display_xv_colour(void *state)
display_colour_t display_xv_colour(void *state)
{
struct state_xv *s = (struct state_xv *) state;
assert(s->magic == MAGIC_XV);
return DC_YUV;
struct state_xv *s = (struct state_xv *)state;
assert(s->magic == MAGIC_XV);
return DC_YUV;
}
display_type_t *
display_xv_probe(void)
display_type_t *display_xv_probe(void)
{
display_type_t *dt;
display_format_t *dformat;
display_type_t *dt;
display_format_t *dformat;
dformat = malloc(4 * sizeof(display_format_t));
dformat[0].size = DS_176x144;
dformat = malloc(4 * sizeof(display_format_t));
dformat[0].size = DS_176x144;
dformat[0].colour_mode = DC_YUV;
dformat[0].num_images = 1;
dformat[1].size = DS_352x288;
dformat[0].num_images = 1;
dformat[1].size = DS_352x288;
dformat[1].colour_mode = DC_YUV;
dformat[1].num_images = 1;
dformat[2].size = DS_702x576;
dformat[1].num_images = 1;
dformat[2].size = DS_702x576;
dformat[2].colour_mode = DC_YUV;
dformat[2].num_images = 1;
dformat[3].size = DS_1280x720;
dformat[2].num_images = 1;
dformat[3].size = DS_1280x720;
dformat[3].colour_mode = DC_YUV;
dformat[3].num_images = 1;
dformat[3].num_images = 1;
dt = malloc(sizeof(display_type_t));
if (dt != NULL) {
dt->id = DISPLAY_XV_ID;
dt->name = "xv";
dt->description = "X Window System with Xvideo extension";
dt->formats = dformat;
dt->id = DISPLAY_XV_ID;
dt->name = "xv";
dt->description = "X Window System with Xvideo extension";
dt->formats = dformat;
dt->num_formats = 4;
}
return dt;
}
#endif /* X_DISPLAY_MISSING */
#endif /* X_DISPLAY_MISSING */

View File

@@ -61,45 +61,61 @@
#include "test_video_capture.h"
#include "test_video_display.h"
uint32_t RTT; /* FIXME: will be removed once the global in main.c is removed */
uint32_t RTT; /* FIXME: will be removed once the global in main.c is removed */
/* These globals should be fixed in the future as well */
uint32_t hd_size_x=1920;
uint32_t hd_size_y=1080;
uint32_t hd_color_bpp=3;
uint32_t bitdepth = 10;
uint32_t progressive = 0;
uint32_t hd_video_mode;
uint32_t hd_size_x = 1920;
uint32_t hd_size_y = 1080;
uint32_t hd_color_bpp = 3;
uint32_t bitdepth = 10;
uint32_t progressive = 0;
uint32_t hd_video_mode;
long packet_rate = 13600;
long packet_rate = 13600;
int
main()
int main()
{
if (test_bitstream() != 0) return 1;
if (test_codec_dvi() != 0) return 1;
if (test_codec_g711() != 0) return 1;
if (test_codec_g726() != 0) return 1;
if (test_codec_gsm() != 0) return 1;
if (test_codec_l16() != 0) return 1;
if (test_codec_l8() != 0) return 1;
if (test_codec_lpc() != 0) return 1;
if (test_codec_vdvi() != 0) return 1;
if (test_des() != 0) return 1;
if (test_aes() != 0) return 1;
if (test_md5() != 0) return 1;
if (test_random() != 0) return 1;
if (test_tv() != 0) return 1;
if (test_net_udp() != 0) return 1;
if (test_rtp() != 0) return 1;
if (test_bitstream() != 0)
return 1;
if (test_codec_dvi() != 0)
return 1;
if (test_codec_g711() != 0)
return 1;
if (test_codec_g726() != 0)
return 1;
if (test_codec_gsm() != 0)
return 1;
if (test_codec_l16() != 0)
return 1;
if (test_codec_l8() != 0)
return 1;
if (test_codec_lpc() != 0)
return 1;
if (test_codec_vdvi() != 0)
return 1;
if (test_des() != 0)
return 1;
if (test_aes() != 0)
return 1;
if (test_md5() != 0)
return 1;
if (test_random() != 0)
return 1;
if (test_tv() != 0)
return 1;
if (test_net_udp() != 0)
return 1;
if (test_rtp() != 0)
return 1;
#ifdef TEST_AV_HW
if (test_audio_hw() != 0) return 1;
if (test_video_capture() != 0) return 1;
if (test_video_display() != 0) return 1;
if (test_audio_hw() != 0)
return 1;
if (test_video_capture() != 0)
return 1;
if (test_video_display() != 0)
return 1;
#endif
return 0;
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -43,54 +43,54 @@
#define BUFSIZE 10
int
test_bitstream(void)
int test_bitstream(void)
{
bitstream_t *bs;
u_char *buffer;
int buflen;
bitstream_t *bs;
u_char *buffer;
int buflen;
printf("Testing bitstreams ....................................................... "); fflush(stdout);
printf
("Testing bitstreams ....................................................... ");
fflush(stdout);
buffer = malloc(BUFSIZE);
if (buffer == NULL) {
printf("FAIL\n");
return 1;
}
buflen = BUFSIZE;
buffer = malloc(BUFSIZE);
if (buffer == NULL) {
printf("FAIL\n");
return 1;
}
buflen = BUFSIZE;
bs_create(&bs);
bs_attach(bs, buffer, buflen);
bs_put(bs, 0x0f, 4);
bs_put(bs, 0x01, 1);
bs_put(bs, 0x02, 3);
bs_put(bs, 0xa8, 8);
bs_put(bs, 0xff, 1);
if (buffer[0] != 0xfa) {
printf("FAIL\n");
printf(" buffer[0] = 0x%02x\n", buffer[0]);
return 1;
}
if (buffer[1] != 0xa8) {
printf("FAIL\n");
printf(" buffer[1] = 0x%02x\n", buffer[1]);
return 1;
}
if (buffer[2] != 0x80) {
printf("FAIL\n");
printf(" buffer[2] = 0x%02x\n", buffer[2]);
return 1;
}
bs_put(bs, 0x01, 7);
if (buffer[2] != 0x81) {
printf("FAIL\n");
printf(" buffer[2] = 0x%02x\n", buffer[2]);
return 1;
}
bs_create(&bs);
bs_attach(bs, buffer, buflen);
bs_put(bs, 0x0f, 4);
bs_put(bs, 0x01, 1);
bs_put(bs, 0x02, 3);
bs_put(bs, 0xa8, 8);
bs_put(bs, 0xff, 1);
if (buffer[0] != 0xfa) {
printf("FAIL\n");
printf(" buffer[0] = 0x%02x\n", buffer[0]);
return 1;
}
if (buffer[1] != 0xa8) {
printf("FAIL\n");
printf(" buffer[1] = 0x%02x\n", buffer[1]);
return 1;
}
if (buffer[2] != 0x80) {
printf("FAIL\n");
printf(" buffer[2] = 0x%02x\n", buffer[2]);
return 1;
}
bs_put(bs, 0x01, 7);
if (buffer[2] != 0x81) {
printf("FAIL\n");
printf(" buffer[2] = 0x%02x\n", buffer[2]);
return 1;
}
bs_destroy(&bs);
bs_destroy(&bs);
printf("Ok\n");
return 0;
printf("Ok\n");
return 0;
}

View File

@@ -47,180 +47,188 @@
#define NUM_TESTS 36
static unsigned char key_data[NUM_TESTS][8]={
{0x12,0x34,0x57,0x79,0x9b,0xbc,0xdf,0xf1},
{0x0e,0x32,0x92,0x32,0xea,0x6d,0x0d,0x72},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
{0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11},
{0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF},
{0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10},
{0x7C,0xA1,0x10,0x45,0x4A,0x1A,0x6E,0x57},
{0x01,0x31,0xD9,0x61,0x9D,0xC1,0x37,0x6E},
{0x07,0xA1,0x13,0x3E,0x4A,0x0B,0x26,0x86},
{0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E},
{0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6},
{0x01,0x13,0xB9,0x70,0xFD,0x34,0xF2,0xCE},
{0x01,0x70,0xF1,0x75,0x46,0x8F,0xB5,0xE6},
{0x43,0x29,0x7F,0xAD,0x38,0xE3,0x73,0xFE},
{0x07,0xA7,0x13,0x70,0x45,0xDA,0x2A,0x16},
{0x04,0x68,0x91,0x04,0xC2,0xFD,0x3B,0x2F},
{0x37,0xD0,0x6B,0xB5,0x16,0xCB,0x75,0x46},
{0x1F,0x08,0x26,0x0D,0x1A,0xC2,0x46,0x5E},
{0x58,0x40,0x23,0x64,0x1A,0xBA,0x61,0x76},
{0x02,0x58,0x16,0x16,0x46,0x29,0xB0,0x07},
{0x49,0x79,0x3E,0xBC,0x79,0xB3,0x25,0x8F},
{0x4F,0xB0,0x5E,0x15,0x15,0xAB,0x73,0xA7},
{0x49,0xE9,0x5D,0x6D,0x4C,0xA2,0x29,0xBF},
{0x01,0x83,0x10,0xDC,0x40,0x9B,0x26,0xD6},
{0x1C,0x58,0x7F,0x1C,0x13,0x92,0x4F,0xEF},
{0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01},
{0x1F,0x1F,0x1F,0x1F,0x0E,0x0E,0x0E,0x0E},
{0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
{0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF},
{0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10}};
static unsigned char key_data[NUM_TESTS][8] = {
{0x12, 0x34, 0x57, 0x79, 0x9b, 0xbc, 0xdf, 0xf1},
{0x0e, 0x32, 0x92, 0x32, 0xea, 0x6d, 0x0d, 0x72},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
{0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57},
{0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E},
{0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86},
{0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E},
{0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6},
{0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE},
{0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6},
{0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE},
{0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16},
{0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F},
{0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46},
{0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E},
{0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76},
{0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07},
{0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F},
{0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7},
{0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF},
{0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6},
{0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF},
{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
{0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E},
{0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}
};
static unsigned char plain_data[NUM_TESTS][8]={
{0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef},
{0x87,0x87,0x87,0x87,0x87,0x87,0x87,0x87},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
{0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x01},
{0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11},
{0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11},
{0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF},
{0x01,0xA1,0xD6,0xD0,0x39,0x77,0x67,0x42},
{0x5C,0xD5,0x4C,0xA8,0x3D,0xEF,0x57,0xDA},
{0x02,0x48,0xD4,0x38,0x06,0xF6,0x71,0x72},
{0x51,0x45,0x4B,0x58,0x2D,0xDF,0x44,0x0A},
{0x42,0xFD,0x44,0x30,0x59,0x57,0x7F,0xA2},
{0x05,0x9B,0x5E,0x08,0x51,0xCF,0x14,0x3A},
{0x07,0x56,0xD8,0xE0,0x77,0x47,0x61,0xD2},
{0x76,0x25,0x14,0xB8,0x29,0xBF,0x48,0x6A},
{0x3B,0xDD,0x11,0x90,0x49,0x37,0x28,0x02},
{0x26,0x95,0x5F,0x68,0x35,0xAF,0x60,0x9A},
{0x16,0x4D,0x5E,0x40,0x4F,0x27,0x52,0x32},
{0x6B,0x05,0x6E,0x18,0x75,0x9F,0x5C,0xCA},
{0x00,0x4B,0xD6,0xEF,0x09,0x17,0x60,0x62},
{0x48,0x0D,0x39,0x00,0x6E,0xE7,0x62,0xF2},
{0x43,0x75,0x40,0xC8,0x69,0x8F,0x3C,0xFA},
{0x07,0x2D,0x43,0xA0,0x77,0x07,0x52,0x92},
{0x02,0xFE,0x55,0x77,0x81,0x17,0xF1,0x2A},
{0x1D,0x9D,0x5C,0x50,0x18,0xF7,0x28,0xC2},
{0x30,0x55,0x32,0x28,0x6D,0x6F,0x29,0x5A},
{0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF},
{0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF},
{0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF},
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};
static unsigned char plain_data[NUM_TESTS][8] = {
{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
{0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42},
{0x5C, 0xD5, 0x4C, 0xA8, 0x3D, 0xEF, 0x57, 0xDA},
{0x02, 0x48, 0xD4, 0x38, 0x06, 0xF6, 0x71, 0x72},
{0x51, 0x45, 0x4B, 0x58, 0x2D, 0xDF, 0x44, 0x0A},
{0x42, 0xFD, 0x44, 0x30, 0x59, 0x57, 0x7F, 0xA2},
{0x05, 0x9B, 0x5E, 0x08, 0x51, 0xCF, 0x14, 0x3A},
{0x07, 0x56, 0xD8, 0xE0, 0x77, 0x47, 0x61, 0xD2},
{0x76, 0x25, 0x14, 0xB8, 0x29, 0xBF, 0x48, 0x6A},
{0x3B, 0xDD, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02},
{0x26, 0x95, 0x5F, 0x68, 0x35, 0xAF, 0x60, 0x9A},
{0x16, 0x4D, 0x5E, 0x40, 0x4F, 0x27, 0x52, 0x32},
{0x6B, 0x05, 0x6E, 0x18, 0x75, 0x9F, 0x5C, 0xCA},
{0x00, 0x4B, 0xD6, 0xEF, 0x09, 0x17, 0x60, 0x62},
{0x48, 0x0D, 0x39, 0x00, 0x6E, 0xE7, 0x62, 0xF2},
{0x43, 0x75, 0x40, 0xC8, 0x69, 0x8F, 0x3C, 0xFA},
{0x07, 0x2D, 0x43, 0xA0, 0x77, 0x07, 0x52, 0x92},
{0x02, 0xFE, 0x55, 0x77, 0x81, 0x17, 0xF1, 0x2A},
{0x1D, 0x9D, 0x5C, 0x50, 0x18, 0xF7, 0x28, 0xC2},
{0x30, 0x55, 0x32, 0x28, 0x6D, 0x6F, 0x29, 0x5A},
{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
};
static unsigned char crypt_data[NUM_TESTS][8]={
{0x85,0xe8,0x13,0x54,0x0f,0x0a,0xb4,0x05},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x8C,0xA6,0x4D,0xE9,0xC1,0xB1,0x23,0xA7},
{0x73,0x59,0xB2,0x16,0x3E,0x4E,0xDC,0x58},
{0x95,0x8E,0x6E,0x62,0x7A,0x05,0x55,0x7B},
{0xF4,0x03,0x79,0xAB,0x9E,0x0E,0xC5,0x33},
{0x17,0x66,0x8D,0xFC,0x72,0x92,0x53,0x2D},
{0x8A,0x5A,0xE1,0xF8,0x1A,0xB8,0xF2,0xDD},
{0x8C,0xA6,0x4D,0xE9,0xC1,0xB1,0x23,0xA7},
{0xED,0x39,0xD9,0x50,0xFA,0x74,0xBC,0xC4},
{0x69,0x0F,0x5B,0x0D,0x9A,0x26,0x93,0x9B},
{0x7A,0x38,0x9D,0x10,0x35,0x4B,0xD2,0x71},
{0x86,0x8E,0xBB,0x51,0xCA,0xB4,0x59,0x9A},
{0x71,0x78,0x87,0x6E,0x01,0xF1,0x9B,0x2A},
{0xAF,0x37,0xFB,0x42,0x1F,0x8C,0x40,0x95},
{0x86,0xA5,0x60,0xF1,0x0E,0xC6,0xD8,0x5B},
{0x0C,0xD3,0xDA,0x02,0x00,0x21,0xDC,0x09},
{0xEA,0x67,0x6B,0x2C,0xB7,0xDB,0x2B,0x7A},
{0xDF,0xD6,0x4A,0x81,0x5C,0xAF,0x1A,0x0F},
{0x5C,0x51,0x3C,0x9C,0x48,0x86,0xC0,0x88},
{0x0A,0x2A,0xEE,0xAE,0x3F,0xF4,0xAB,0x77},
{0xEF,0x1B,0xF0,0x3E,0x5D,0xFA,0x57,0x5A},
{0x88,0xBF,0x0D,0xB6,0xD7,0x0D,0xEE,0x56},
{0xA1,0xF9,0x91,0x55,0x41,0x02,0x0B,0x56},
{0x6F,0xBF,0x1C,0xAF,0xCF,0xFD,0x05,0x56},
{0x2F,0x22,0xE4,0x9B,0xAB,0x7C,0xA1,0xAC},
{0x5A,0x6B,0x61,0x2C,0xC2,0x6C,0xCE,0x4A},
{0x5F,0x4C,0x03,0x8E,0xD1,0x2B,0x2E,0x41},
{0x63,0xFA,0xC0,0xD0,0x34,0xD9,0xF7,0x93},
{0x61,0x7B,0x3A,0x0C,0xE8,0xF0,0x71,0x00},
{0xDB,0x95,0x86,0x05,0xF8,0xC8,0xC6,0x06},
{0xED,0xBF,0xD1,0xC6,0x6C,0x29,0xCC,0xC7},
{0x35,0x55,0x50,0xB2,0x15,0x0E,0x24,0x51},
{0xCA,0xAA,0xAF,0x4D,0xEA,0xF1,0xDB,0xAE},
{0xD5,0xD4,0x4F,0xF7,0x20,0x68,0x3D,0x0D},
{0x2A,0x2B,0xB0,0x08,0xDF,0x97,0xC2,0xF2}};
static unsigned char crypt_data[NUM_TESTS][8] = {
{0x85, 0xe8, 0x13, 0x54, 0x0f, 0x0a, 0xb4, 0x05},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x8C, 0xA6, 0x4D, 0xE9, 0xC1, 0xB1, 0x23, 0xA7},
{0x73, 0x59, 0xB2, 0x16, 0x3E, 0x4E, 0xDC, 0x58},
{0x95, 0x8E, 0x6E, 0x62, 0x7A, 0x05, 0x55, 0x7B},
{0xF4, 0x03, 0x79, 0xAB, 0x9E, 0x0E, 0xC5, 0x33},
{0x17, 0x66, 0x8D, 0xFC, 0x72, 0x92, 0x53, 0x2D},
{0x8A, 0x5A, 0xE1, 0xF8, 0x1A, 0xB8, 0xF2, 0xDD},
{0x8C, 0xA6, 0x4D, 0xE9, 0xC1, 0xB1, 0x23, 0xA7},
{0xED, 0x39, 0xD9, 0x50, 0xFA, 0x74, 0xBC, 0xC4},
{0x69, 0x0F, 0x5B, 0x0D, 0x9A, 0x26, 0x93, 0x9B},
{0x7A, 0x38, 0x9D, 0x10, 0x35, 0x4B, 0xD2, 0x71},
{0x86, 0x8E, 0xBB, 0x51, 0xCA, 0xB4, 0x59, 0x9A},
{0x71, 0x78, 0x87, 0x6E, 0x01, 0xF1, 0x9B, 0x2A},
{0xAF, 0x37, 0xFB, 0x42, 0x1F, 0x8C, 0x40, 0x95},
{0x86, 0xA5, 0x60, 0xF1, 0x0E, 0xC6, 0xD8, 0x5B},
{0x0C, 0xD3, 0xDA, 0x02, 0x00, 0x21, 0xDC, 0x09},
{0xEA, 0x67, 0x6B, 0x2C, 0xB7, 0xDB, 0x2B, 0x7A},
{0xDF, 0xD6, 0x4A, 0x81, 0x5C, 0xAF, 0x1A, 0x0F},
{0x5C, 0x51, 0x3C, 0x9C, 0x48, 0x86, 0xC0, 0x88},
{0x0A, 0x2A, 0xEE, 0xAE, 0x3F, 0xF4, 0xAB, 0x77},
{0xEF, 0x1B, 0xF0, 0x3E, 0x5D, 0xFA, 0x57, 0x5A},
{0x88, 0xBF, 0x0D, 0xB6, 0xD7, 0x0D, 0xEE, 0x56},
{0xA1, 0xF9, 0x91, 0x55, 0x41, 0x02, 0x0B, 0x56},
{0x6F, 0xBF, 0x1C, 0xAF, 0xCF, 0xFD, 0x05, 0x56},
{0x2F, 0x22, 0xE4, 0x9B, 0xAB, 0x7C, 0xA1, 0xAC},
{0x5A, 0x6B, 0x61, 0x2C, 0xC2, 0x6C, 0xCE, 0x4A},
{0x5F, 0x4C, 0x03, 0x8E, 0xD1, 0x2B, 0x2E, 0x41},
{0x63, 0xFA, 0xC0, 0xD0, 0x34, 0xD9, 0xF7, 0x93},
{0x61, 0x7B, 0x3A, 0x0C, 0xE8, 0xF0, 0x71, 0x00},
{0xDB, 0x95, 0x86, 0x05, 0xF8, 0xC8, 0xC6, 0x06},
{0xED, 0xBF, 0xD1, 0xC6, 0x6C, 0x29, 0xCC, 0xC7},
{0x35, 0x55, 0x50, 0xB2, 0x15, 0x0E, 0x24, 0x51},
{0xCA, 0xAA, 0xAF, 0x4D, 0xEA, 0xF1, 0xDB, 0xAE},
{0xD5, 0xD4, 0x4F, 0xF7, 0x20, 0x68, 0x3D, 0x0D},
{0x2A, 0x2B, 0xB0, 0x08, 0xDF, 0x97, 0xC2, 0xF2}
};
static unsigned char cbc_key[8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};
static unsigned char cbc_iv[8]={0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};
static unsigned char cbc_data[32]="7654321 Now is the time for ";
static unsigned char cbc_key[8] =
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
static unsigned char cbc_iv[8] =
{ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
static unsigned char cbc_data[32] = "7654321 Now is the time for ";
static unsigned char cbc_ok[32]={
0xcc,0xd1,0x73,0xff,0xab,0x20,0x39,0xf4,
0xac,0xd8,0xae,0xfd,0xdf,0xd8,0xa1,0xeb,
0x46,0x8e,0x91,0x15,0x78,0x88,0xba,0x68,
0x1d,0x26,0x93,0x97,0xf7,0xfe,0x62,0xb4};
static unsigned char cbc_ok[32] = {
0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4,
0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb,
0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68,
0x1d, 0x26, 0x93, 0x97, 0xf7, 0xfe, 0x62, 0xb4
};
int
test_des(void)
int test_des(void)
{
int i, j;
unsigned char key[8], plain[8], crypt[8], buffer[8];
unsigned char cbc_buffer[32], cbc_iv_buf[8];
int i, j;
unsigned char key[8], plain[8], crypt[8], buffer[8];
unsigned char cbc_buffer[32], cbc_iv_buf[8];
printf("Testing DES in ECB mode .................................................. "); fflush(stdout);
for (i = 0; i < NUM_TESTS; i++) {
for (j = 0; j < 8; j++) {
key[j] = key_data[i][j];
plain[j] = plain_data[i][j];
crypt[j] = crypt_data[i][j];
}
memcpy(buffer, crypt, 8);
qfDES_ECB_d(key, buffer, 8);
if (memcmp(buffer, plain, 8) != 0) {
printf("FAIL\n");
goto abort_ecb;
}
memcpy(buffer, plain, 8);
qfDES_ECB_e(key, buffer, 8);
if (memcmp(buffer, crypt, 8) != 0) {
printf("FAIL\n");
goto abort_ecb;
}
qfDES_ECB_d(key, buffer, 8);
if (memcmp(buffer, plain, 8) != 0) {
printf("FAIL\n");
goto abort_ecb;
}
}
printf("Ok\n");
abort_ecb:
printf
("Testing DES in ECB mode .................................................. ");
fflush(stdout);
for (i = 0; i < NUM_TESTS; i++) {
for (j = 0; j < 8; j++) {
key[j] = key_data[i][j];
plain[j] = plain_data[i][j];
crypt[j] = crypt_data[i][j];
}
memcpy(buffer, crypt, 8);
qfDES_ECB_d(key, buffer, 8);
if (memcmp(buffer, plain, 8) != 0) {
printf("FAIL\n");
goto abort_ecb;
}
memcpy(buffer, plain, 8);
qfDES_ECB_e(key, buffer, 8);
if (memcmp(buffer, crypt, 8) != 0) {
printf("FAIL\n");
goto abort_ecb;
}
qfDES_ECB_d(key, buffer, 8);
if (memcmp(buffer, plain, 8) != 0) {
printf("FAIL\n");
goto abort_ecb;
}
}
printf("Ok\n");
abort_ecb:
printf("Testing DES in CBC mode .................................................. "); fflush(stdout);
memcpy(cbc_buffer, cbc_data, 32);
memcpy(cbc_iv_buf, cbc_iv, 8);
qfDES_CBC_e(cbc_key, cbc_buffer, 32, cbc_iv_buf);
if (memcmp(cbc_buffer, cbc_ok, 32) != 0) {
printf("FAIL\n");
return 1;
}
memcpy(cbc_iv_buf, cbc_iv, 8);
qfDES_CBC_d(cbc_key, cbc_buffer, 32, cbc_iv_buf);
if (memcmp(cbc_buffer, cbc_data, 32) != 0) {
printf("FAIL\n");
return 1;
}
printf("Ok\n");
return 0;
printf
("Testing DES in CBC mode .................................................. ");
fflush(stdout);
memcpy(cbc_buffer, cbc_data, 32);
memcpy(cbc_iv_buf, cbc_iv, 8);
qfDES_CBC_e(cbc_key, cbc_buffer, 32, cbc_iv_buf);
if (memcmp(cbc_buffer, cbc_ok, 32) != 0) {
printf("FAIL\n");
return 1;
}
memcpy(cbc_iv_buf, cbc_iv, 8);
qfDES_CBC_d(cbc_key, cbc_buffer, 32, cbc_iv_buf);
if (memcmp(cbc_buffer, cbc_data, 32) != 0) {
printf("FAIL\n");
return 1;
}
printf("Ok\n");
return 0;
}

View File

@@ -43,85 +43,100 @@
#include "crypto/md5.h"
#include "test_md5.h"
int
test_md5(void)
int test_md5(void)
{
MD5_CTX context;
unsigned char digest[16];
unsigned char i1[] = "";
unsigned char o1[] = {0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e};
unsigned char i2[] = "a";
unsigned char o2[] = {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61};
unsigned char i3[] = "abc";
unsigned char o3[] = {0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72};
unsigned char i4[] = "message digest";
unsigned char o4[] = {0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0};
unsigned char i5[] = "abcdefghijklmnopqrstuvwxyz";
unsigned char o5[] = {0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b};
unsigned char i6[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
unsigned char o6[] = {0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f};
unsigned char i7[] = "12345678901234567890123456789012345678901234567890123456789012345678901234567890";
unsigned char o7[] = {0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a};
MD5_CTX context;
unsigned char digest[16];
unsigned char i1[] = "";
unsigned char o1[] =
{ 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09,
0x98, 0xec, 0xf8, 0x42, 0x7e };
unsigned char i2[] = "a";
unsigned char o2[] =
{ 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 0x31, 0xc3, 0x99,
0xe2, 0x69, 0x77, 0x26, 0x61 };
unsigned char i3[] = "abc";
unsigned char o3[] =
{ 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f,
0x7d, 0x28, 0xe1, 0x7f, 0x72 };
unsigned char i4[] = "message digest";
unsigned char o4[] =
{ 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, 0x52, 0x5a, 0x2f,
0x31, 0xaa, 0xf1, 0x61, 0xd0 };
unsigned char i5[] = "abcdefghijklmnopqrstuvwxyz";
unsigned char o5[] =
{ 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49,
0x6c, 0xca, 0x67, 0xe1, 0x3b };
unsigned char i6[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
unsigned char o6[] =
{ 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, 0xa5, 0x61, 0x1c,
0x2c, 0x9f, 0x41, 0x9d, 0x9f };
unsigned char i7[] =
"12345678901234567890123456789012345678901234567890123456789012345678901234567890";
unsigned char o7[] =
{ 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 0xac, 0x49, 0xda,
0x2e, 0x21, 0x07, 0xb6, 0x7a };
printf
("Testing MD5 .............................................................. ");
fflush(stdout);
printf("Testing MD5 .............................................................. "); fflush(stdout);
MD5Init(&context);
MD5Update(&context, i1, strlen(i1));
MD5Final(digest, &context);
if (strncmp(digest, o1, 16) != 0) {
printf("FAIL\n");
return 1;
}
MD5Init(&context);
MD5Update(&context, i1, strlen(i1));
MD5Final(digest, &context);
if (strncmp(digest, o1, 16) != 0) {
printf("FAIL\n");
return 1;
}
MD5Init(&context);
MD5Update(&context, i2, strlen(i2));
MD5Final(digest, &context);
if (strncmp(digest, o2, 16) != 0) {
printf("FAIL\n");
return 1;
}
MD5Init(&context);
MD5Update(&context, i2, strlen(i2));
MD5Final(digest, &context);
if (strncmp(digest, o2, 16) != 0) {
printf("FAIL\n");
return 1;
}
MD5Init(&context);
MD5Update(&context, i3, strlen(i3));
MD5Final(digest, &context);
if (strncmp(digest, o3, 16) != 0) {
printf("FAIL\n");
return 1;
}
MD5Init(&context);
MD5Update(&context, i3, strlen(i3));
MD5Final(digest, &context);
if (strncmp(digest, o3, 16) != 0) {
printf("FAIL\n");
return 1;
}
MD5Init(&context);
MD5Update(&context, i4, strlen(i4));
MD5Final(digest, &context);
if (strncmp(digest, o4, 16) != 0) {
printf("FAIL\n");
return 1;
}
MD5Init(&context);
MD5Update(&context, i4, strlen(i4));
MD5Final(digest, &context);
if (strncmp(digest, o4, 16) != 0) {
printf("FAIL\n");
return 1;
}
MD5Init(&context);
MD5Update(&context, i5, strlen(i5));
MD5Final(digest, &context);
if (strncmp(digest, o5, 16) != 0) {
printf("FAIL\n");
return 1;
}
MD5Init(&context);
MD5Update(&context, i5, strlen(i5));
MD5Final(digest, &context);
if (strncmp(digest, o5, 16) != 0) {
printf("FAIL\n");
return 1;
}
MD5Init(&context);
MD5Update(&context, i6, strlen(i6));
MD5Final(digest, &context);
if (strncmp(digest, o6, 16) != 0) {
printf("FAIL\n");
return 1;
}
MD5Init(&context);
MD5Update(&context, i6, strlen(i6));
MD5Final(digest, &context);
if (strncmp(digest, o6, 16) != 0) {
printf("FAIL\n");
return 1;
}
MD5Init(&context);
MD5Update(&context, i7, strlen(i7));
MD5Final(digest, &context);
if (strncmp(digest, o7, 16) != 0) {
printf("FAIL\n");
return 1;
}
printf("Ok\n");
return 0;
MD5Init(&context);
MD5Update(&context, i7, strlen(i7));
MD5Final(digest, &context);
if (strncmp(digest, o7, 16) != 0) {
printf("FAIL\n");
return 1;
}
printf("Ok\n");
return 0;
}

View File

@@ -45,481 +45,493 @@
static void randomize(char buf[], int buflen)
{
int i;
int i;
for (i = 0; i < buflen; i++) {
buf[i] = (lrand48() && 0xff00) >> 8;
}
for (i = 0; i < buflen; i++) {
buf[i] = (lrand48() && 0xff00) >> 8;
}
}
int
test_net_udp(void)
int test_net_udp(void)
{
struct timeval timeout;
socket_udp *s1, *s2;
char buf1[BUFSIZE], buf2[BUFSIZE];
const char *hname;
int rc, i;
struct timeval timeout;
socket_udp *s1, *s2;
char buf1[BUFSIZE], buf2[BUFSIZE];
const char *hname;
int rc, i;
#ifndef WIN32
/* "BSD" bug test that appears in this function uses fork and
* exec, that are not present on WIN32. Since the original
* bug has not been seen on Win32 it's probably not worth
* converting to use CreateProcess() */
/* "BSD" bug test that appears in this function uses fork and
* exec, that are not present on WIN32. Since the original
* bug has not been seen on Win32 it's probably not worth
* converting to use CreateProcess() */
int status_parent, status_child;
int status_parent, status_child;
#endif /* WIN32 */
#endif /* WIN32 */
srand48(time(NULL));
srand48(time(NULL));
/**********************************************************************/
/* The first test is to loopback a packet to ourselves... */
printf("Testing UDP/IP networking (IPv4 loopback) ................................ ");
fflush(stdout);
s1 = udp_init("127.0.0.1", 5004, 5004, 1);
if (s1 == NULL) {
printf("FAIL\n");
printf(" Cannot initialize socket\n");
return 1;
}
randomize(buf1, BUFSIZE);
randomize(buf2, BUFSIZE);
if (udp_send(s1, buf1, BUFSIZE) < 0) {
printf("FAIL\n");
perror(" Cannot send packet");
goto abort_loopback;
}
timeout.tv_sec = 1;
timeout.tv_usec = 0;
udp_fd_zero();
udp_fd_set(s1);
rc = udp_select(&timeout);
if (rc < 0) {
printf("FAIL\n");
perror(" Select failed");
goto abort_loopback;
}
if (rc == 0) {
printf("FAIL\n");
printf(" No data waiting\n");
goto abort_loopback;
}
if (!udp_fd_isset(s1)) {
printf("FAIL\n");
printf(" No data on file descriptor\n");
goto abort_loopback;
}
if (udp_recv(s1, buf2, BUFSIZE) < 0) {
printf("FAIL\n");
perror(" Receive failed");
goto abort_loopback;
}
if (memcmp(buf1, buf2, BUFSIZE) != 0) {
printf("FAIL\n");
printf(" Buffer corrupt\n");
goto abort_loopback;
}
printf("Ok\n");
abort_loopback:
hname = udp_host_addr(s1); /* we need this for the unicast test... */
udp_exit(s1);
/**********************************************************************/
/* Now we send a packet to ourselves via our real network address... */
printf("Testing UDP/IP networking (IPv4 unicast) ................................. ");
fflush(stdout);
s1 = udp_init(hname, 5004, 5005, 1);
if (s1 == NULL) {
printf("FAIL\n");
printf(" Cannot initialize socket\n");
return 1;
}
s2 = udp_init(hname, 5005, 5004, 1);
if (s2 == NULL) {
printf("FAIL\n");
printf(" Cannot initialize socket\n");
return 1;
}
randomize(buf1, BUFSIZE);
randomize(buf2, BUFSIZE);
if (udp_send(s1, buf1, BUFSIZE) < 0) {
printf("FAIL\n");
perror(" Cannot send");
goto abort_unicast;
}
timeout.tv_sec = 1;
timeout.tv_usec = 0;
udp_fd_zero();
udp_fd_set(s1);
udp_fd_set(s2);
rc = udp_select(&timeout);
if (rc < 0) {
printf("FAIL\n");
perror(" Select failed");
goto abort_unicast;
}
if (rc == 0) {
printf("FAIL\n");
printf(" No data waiting (no route to %s?)\n", hname);
goto abort_unicast;
}
if (!udp_fd_isset(s2)) {
printf("FAIL\n");
printf(" No data on file descriptor\n");
goto abort_unicast;
}
if (udp_recv(s2, buf2, BUFSIZE) < 0) {
printf("FAIL\n");
perror(" Cannot receive");
goto abort_unicast;
}
if (memcmp(buf1, buf2, BUFSIZE) != 0) {
printf("FAIL\n");
printf(" Buffer corrupt\n");
goto abort_unicast;
}
printf("Ok\n");
abort_unicast:
udp_exit(s1);
udp_exit(s2);
/**********************************************************************/
/* Loopback a packet to ourselves via multicast... */
printf("Testing UDP/IP networking (IPv4 multicast) ............................... ");
fflush(stdout);
s1 = udp_init("224.2.0.1", 5004, 5004, 1);
if (s1 == NULL) {
printf("FAIL\n");
printf(" Cannot initialize socket\n");
return 1;
}
randomize(buf1, BUFSIZE);
randomize(buf2, BUFSIZE);
if (udp_send(s1, buf1, BUFSIZE) < 0) {
printf("FAIL\n");
perror(" Cannot send");
goto abort_multicast;
}
timeout.tv_sec = 1;
timeout.tv_usec = 0;
udp_fd_zero();
udp_fd_set(s1);
rc = udp_select(&timeout);
if (rc < 0) {
printf("FAIL\n");
perror(" Select failed");
goto abort_multicast;
}
if (rc == 0) {
printf("FAIL\n");
printf(" No data waiting (no multicast loopback route?)\n");
goto abort_multicast;
}
if (!udp_fd_isset(s1)) {
printf("FAIL\n");
printf(" No data on file descriptor\n");
goto abort_multicast;
}
if (udp_recv(s1, buf2, BUFSIZE) < 0) {
printf("FAIL\n");
perror(" Cannot receive");
goto abort_multicast;
}
if (memcmp(buf1, buf2, BUFSIZE) != 0) {
printf("FAIL\n");
printf(" Buffer corrupt\n");
goto abort_multicast;
}
printf("Ok\n");
abort_multicast:
udp_exit(s1);
/**********************************************************************/
/* Loopback a packet to ourselves via multicast, checking lengths... */
printf("Testing UDP/IP networking (IPv4 length check) ............................ ");
fflush(stdout);
s1 = udp_init("224.2.0.1", 5004, 5004, 1);
if (s1 == NULL) {
printf("FAIL\n");
printf(" Cannot initialize socket\n");
return 1;
}
for (i = 1; i < BUFSIZE; i++) {
randomize(buf1, i);
randomize(buf2, i);
if (udp_send(s1, buf1, i) < 0) {
printf("FAIL\n");
perror(" Cannot send");
goto abort_length;
}
timeout.tv_sec = 1;
timeout.tv_usec = 0;
udp_fd_zero();
udp_fd_set(s1);
rc = udp_select(&timeout);
if (rc < 0) {
printf("FAIL\n");
perror(" Select failed");
goto abort_length;
}
if (rc == 0) {
printf("FAIL\n");
printf(" No data waiting (no multicast loopback route?)\n");
goto abort_length;
}
if (!udp_fd_isset(s1)) {
printf("FAIL\n");
printf(" No data on file descriptor\n");
goto abort_length;
}
if (udp_recv(s1, buf2, BUFSIZE) != i) {
printf("FAIL\n");
perror(" Cannot receive");
goto abort_length;
}
if (memcmp(buf1, buf2, i) != 0) {
printf("FAIL\n");
printf(" Buffer corrupt\n");
goto abort_length;
}
}
/**********************************************************************/
/* The first test is to loopback a packet to ourselves... */
printf
("Testing UDP/IP networking (IPv4 loopback) ................................ ");
fflush(stdout);
s1 = udp_init("127.0.0.1", 5004, 5004, 1);
if (s1 == NULL) {
printf("FAIL\n");
printf(" Cannot initialize socket\n");
return 1;
}
randomize(buf1, BUFSIZE);
randomize(buf2, BUFSIZE);
if (udp_send(s1, buf1, BUFSIZE) < 0) {
printf("FAIL\n");
perror(" Cannot send packet");
goto abort_loopback;
}
timeout.tv_sec = 1;
timeout.tv_usec = 0;
udp_fd_zero();
udp_fd_set(s1);
rc = udp_select(&timeout);
if (rc < 0) {
printf("FAIL\n");
perror(" Select failed");
goto abort_loopback;
}
if (rc == 0) {
printf("FAIL\n");
printf(" No data waiting\n");
goto abort_loopback;
}
if (!udp_fd_isset(s1)) {
printf("FAIL\n");
printf(" No data on file descriptor\n");
goto abort_loopback;
}
if (udp_recv(s1, buf2, BUFSIZE) < 0) {
printf("FAIL\n");
perror(" Receive failed");
goto abort_loopback;
}
if (memcmp(buf1, buf2, BUFSIZE) != 0) {
printf("FAIL\n");
printf(" Buffer corrupt\n");
goto abort_loopback;
}
printf("Ok\n");
abort_length:
abort_loopback:
hname = udp_host_addr(s1); /* we need this for the unicast test... */
udp_exit(s1);
/**********************************************************************/
/* Now we send a packet to ourselves via our real network address... */
printf
("Testing UDP/IP networking (IPv4 unicast) ................................. ");
fflush(stdout);
s1 = udp_init(hname, 5004, 5005, 1);
if (s1 == NULL) {
printf("FAIL\n");
printf(" Cannot initialize socket\n");
return 1;
}
s2 = udp_init(hname, 5005, 5004, 1);
if (s2 == NULL) {
printf("FAIL\n");
printf(" Cannot initialize socket\n");
return 1;
}
#ifdef HAVE_IPv6
/**********************************************************************/
/* The first test is to loopback a packet to ourselves... */
printf("Testing UDP/IP networking (IPv6 loopback) ................................ ");
fflush(stdout);
s1 = udp_init("::1", 5004, 5004, 1);
if (s1 == NULL) {
printf("FAIL\n");
printf(" Cannot initialize socket\n");
return 1;
}
randomize(buf1, BUFSIZE);
randomize(buf2, BUFSIZE);
if (udp_send(s1, buf1, BUFSIZE) < 0) {
printf("FAIL\n");
perror(" Cannot send");
goto abort_loopback_ipv6;
}
timeout.tv_sec = 1;
timeout.tv_usec = 0;
udp_fd_zero();
udp_fd_set(s1);
rc = udp_select(&timeout);
if (rc < 0) {
printf("FAIL\n");
perror(" Select failed");
goto abort_loopback_ipv6;
}
if (rc == 0) {
printf("FAIL\n");
printf(" No data waiting\n");
goto abort_loopback_ipv6;
}
if (!udp_fd_isset(s1)) {
printf("FAIL\n");
printf(" No data on file descriptor\n");
goto abort_loopback_ipv6;
}
if (udp_recv(s1, buf2, BUFSIZE) < 0) {
printf("FAIL\n");
perror(" Cannot receive");
goto abort_loopback_ipv6;
}
if (memcmp(buf1, buf2, BUFSIZE) != 0) {
printf("FAIL\n");
printf(" Buffer corrupt\n");
goto abort_loopback_ipv6;
}
printf("Ok\n");
abort_loopback_ipv6:
udp_exit(s1);
randomize(buf1, BUFSIZE);
randomize(buf2, BUFSIZE);
if (udp_send(s1, buf1, BUFSIZE) < 0) {
printf("FAIL\n");
perror(" Cannot send");
goto abort_unicast;
}
timeout.tv_sec = 1;
timeout.tv_usec = 0;
udp_fd_zero();
udp_fd_set(s1);
udp_fd_set(s2);
rc = udp_select(&timeout);
if (rc < 0) {
printf("FAIL\n");
perror(" Select failed");
goto abort_unicast;
}
if (rc == 0) {
printf("FAIL\n");
printf(" No data waiting (no route to %s?)\n", hname);
goto abort_unicast;
}
if (!udp_fd_isset(s2)) {
printf("FAIL\n");
printf(" No data on file descriptor\n");
goto abort_unicast;
}
if (udp_recv(s2, buf2, BUFSIZE) < 0) {
printf("FAIL\n");
perror(" Cannot receive");
goto abort_unicast;
}
if (memcmp(buf1, buf2, BUFSIZE) != 0) {
printf("FAIL\n");
printf(" Buffer corrupt\n");
goto abort_unicast;
}
printf("Ok\n");
abort_unicast:
udp_exit(s1);
udp_exit(s2);
/**********************************************************************/
/* Loopback a packet to ourselves via multicast. The address is the */
/* SAP address, but we use a different port. */
printf("Testing UDP/IP networking (IPv6 multicast) ............................... ");
fflush(stdout);
s1 = udp_init("ff01::2:7ffe", 5004, 5004, 1);
if (s1 == NULL) {
printf("FAIL\n");
printf(" Cannot initialize socket\n");
return 1;
}
randomize(buf1, BUFSIZE);
randomize(buf2, BUFSIZE);
if (udp_send(s1, buf1, BUFSIZE) < 0) {
printf("FAIL\n");
perror(" Cannot send");
goto abort_multicast_ipv6;
}
timeout.tv_sec = 1;
timeout.tv_usec = 0;
udp_fd_zero();
udp_fd_set(s1);
rc = udp_select(&timeout);
if (rc < 0) {
printf("FAIL\n");
perror(" Select failed");
goto abort_multicast_ipv6;
}
if (rc == 0) {
printf("FAIL\n");
printf(" No data waiting (no multicast loopback route?)\n");
goto abort_multicast_ipv6;
}
if (!udp_fd_isset(s1)) {
printf("FAIL\n");
printf(" No data on file descriptor\n");
goto abort_multicast_ipv6;
}
if (udp_recv(s1, buf2, BUFSIZE) < 0) {
printf("FAIL\n");
perror(" Cannot receive");
goto abort_multicast_ipv6;
}
if (memcmp(buf1, buf2, BUFSIZE) != 0) {
printf("FAIL\n");
printf(" Buffer corrupt\n");
goto abort_multicast_ipv6;
}
hname = udp_host_addr(s1); /* we need this for the unicast test... */
printf("Ok\n");
abort_multicast_ipv6:
udp_exit(s1);
#else
printf("Testing UDP/IP networking (IPv6 loopback) ................................ --\n");
printf("Testing UDP/IP networking (IPv6 unicast) ................................. --\n");
printf("Testing UDP/IP networking (IPv6 multicast) ............................... --\n");
#endif
/**********************************************************************/
/* Loopback a packet to ourselves via multicast... */
printf
("Testing UDP/IP networking (IPv4 multicast) ............................... ");
fflush(stdout);
s1 = udp_init("224.2.0.1", 5004, 5004, 1);
if (s1 == NULL) {
printf("FAIL\n");
printf(" Cannot initialize socket\n");
return 1;
}
randomize(buf1, BUFSIZE);
randomize(buf2, BUFSIZE);
if (udp_send(s1, buf1, BUFSIZE) < 0) {
printf("FAIL\n");
perror(" Cannot send");
goto abort_multicast;
}
timeout.tv_sec = 1;
timeout.tv_usec = 0;
udp_fd_zero();
udp_fd_set(s1);
rc = udp_select(&timeout);
if (rc < 0) {
printf("FAIL\n");
perror(" Select failed");
goto abort_multicast;
}
if (rc == 0) {
printf("FAIL\n");
printf(" No data waiting (no multicast loopback route?)\n");
goto abort_multicast;
}
if (!udp_fd_isset(s1)) {
printf("FAIL\n");
printf(" No data on file descriptor\n");
goto abort_multicast;
}
if (udp_recv(s1, buf2, BUFSIZE) < 0) {
printf("FAIL\n");
perror(" Cannot receive");
goto abort_multicast;
}
if (memcmp(buf1, buf2, BUFSIZE) != 0) {
printf("FAIL\n");
printf(" Buffer corrupt\n");
goto abort_multicast;
}
printf("Ok\n");
abort_multicast:
udp_exit(s1);
/**********************************************************************/
#ifdef WIN32
printf("Testing UDP/IP networking (FreeBSD bug) .................................. --\n");
#else
printf("Testing UDP/IP networking (FreeBSD bug) .................................. ");
fflush(stdout);
status_parent = 0;
randomize(buf1, 64);
s1 = udp_init("224.2.0.1", 5004, 5004, 1);
if (s1 == NULL) {
printf("fail (parent): cannot initialize socket\n");
return 1;
}
rc = fork();
if (rc == -1) {
printf("fail: cannot fork\n");
goto abort_bsd;
} else if (rc == 0) {
/* child */
s2 = udp_init("224.2.0.1", 5004, 5004, 1);
if (s2 == NULL) {
printf("FAIL\n");
printf(" Child cannot initialize socket\n");
exit(0);
}
if (udp_send(s2, buf1, 64) < 0) {
printf("FAIL\n");
perror(" Child cannot send");
exit(0);
}
timeout.tv_sec = 10;
timeout.tv_usec = 0;
udp_fd_zero();
udp_fd_set(s2);
rc = udp_select(&timeout);
if (rc < 0) {
printf("FAIL\n");
perror(" Child select");
exit(0);
}
if (rc == 0) {
printf("FAIL\n");
printf(" Child: no data waiting (no multicast loopback route?)\n");
exit(0);
}
if (!udp_fd_isset(s2)) {
printf("FAIL\n");
printf(" Child: no data on file descriptor\n");
exit(0);
}
rc = udp_recv(s2, buf2, BUFSIZE);
if (rc < 0) {
printf("FAIL\n");
perror(" Child cannot receive");
exit(0);
}
if (rc != 64) {
printf("FAIL\n");
printf(" Child: read size incorrect (%d != %d)\n", rc, 64);
exit(0);
}
if (memcmp(buf1, buf2, 64) != 0) {
printf("FAIL\n");
printf(" Child: buffer corrupt\n");
exit(0);
}
udp_exit(s2);
exit(1);
} else {
/* parent */
timeout.tv_sec = 10;
/**********************************************************************/
/* Loopback a packet to ourselves via multicast, checking lengths... */
printf
("Testing UDP/IP networking (IPv4 length check) ............................ ");
fflush(stdout);
s1 = udp_init("224.2.0.1", 5004, 5004, 1);
if (s1 == NULL) {
printf("FAIL\n");
printf(" Cannot initialize socket\n");
return 1;
}
for (i = 1; i < BUFSIZE; i++) {
randomize(buf1, i);
randomize(buf2, i);
if (udp_send(s1, buf1, i) < 0) {
printf("FAIL\n");
perror(" Cannot send");
goto abort_length;
}
timeout.tv_sec = 1;
timeout.tv_usec = 0;
udp_fd_zero();
udp_fd_set(s1);
rc = udp_select(&timeout);
if (rc < 0) {
printf("FAIL\n");
perror(" Parent select");
goto abort_bsd;
}
if (rc == 0) {
printf("FAIL\n");
printf(" Parent: no data waiting (no multicast loopback route?)\n");
goto abort_bsd;
}
if (!udp_fd_isset(s1)) {
printf("FAIL\n");
printf(" Parent: no data on file descriptor\n");
goto abort_bsd;
}
rc = udp_recv(s1, buf2, BUFSIZE);
if (rc < 0) {
printf("FAIL\n");
perror(" Parent cannot receive");
goto abort_bsd;
printf("FAIL\n");
perror(" Select failed");
goto abort_length;
}
if (rc == 0) {
printf("FAIL\n");
printf
(" No data waiting (no multicast loopback route?)\n");
goto abort_length;
}
if (!udp_fd_isset(s1)) {
printf("FAIL\n");
printf(" No data on file descriptor\n");
goto abort_length;
}
if (udp_recv(s1, buf2, BUFSIZE) != i) {
printf("FAIL\n");
perror(" Cannot receive");
goto abort_length;
}
if (memcmp(buf1, buf2, i) != 0) {
printf("FAIL\n");
printf(" Buffer corrupt\n");
goto abort_length;
}
}
printf("Ok\n");
abort_length:
udp_exit(s1);
#ifdef HAVE_IPv6
/**********************************************************************/
/* The first test is to loopback a packet to ourselves... */
printf
("Testing UDP/IP networking (IPv6 loopback) ................................ ");
fflush(stdout);
s1 = udp_init("::1", 5004, 5004, 1);
if (s1 == NULL) {
printf("FAIL\n");
printf(" Cannot initialize socket\n");
return 1;
}
randomize(buf1, BUFSIZE);
randomize(buf2, BUFSIZE);
if (udp_send(s1, buf1, BUFSIZE) < 0) {
printf("FAIL\n");
perror(" Cannot send");
goto abort_loopback_ipv6;
}
timeout.tv_sec = 1;
timeout.tv_usec = 0;
udp_fd_zero();
udp_fd_set(s1);
rc = udp_select(&timeout);
if (rc < 0) {
printf("FAIL\n");
perror(" Select failed");
goto abort_loopback_ipv6;
}
if (rc == 0) {
printf("FAIL\n");
printf(" No data waiting\n");
goto abort_loopback_ipv6;
}
if (!udp_fd_isset(s1)) {
printf("FAIL\n");
printf(" No data on file descriptor\n");
goto abort_loopback_ipv6;
}
if (udp_recv(s1, buf2, BUFSIZE) < 0) {
printf("FAIL\n");
perror(" Cannot receive");
goto abort_loopback_ipv6;
}
if (memcmp(buf1, buf2, BUFSIZE) != 0) {
printf("FAIL\n");
printf(" Buffer corrupt\n");
goto abort_loopback_ipv6;
}
printf("Ok\n");
abort_loopback_ipv6:
udp_exit(s1);
/**********************************************************************/
/* Loopback a packet to ourselves via multicast. The address is the */
/* SAP address, but we use a different port. */
printf
("Testing UDP/IP networking (IPv6 multicast) ............................... ");
fflush(stdout);
s1 = udp_init("ff01::2:7ffe", 5004, 5004, 1);
if (s1 == NULL) {
printf("FAIL\n");
printf(" Cannot initialize socket\n");
return 1;
}
randomize(buf1, BUFSIZE);
randomize(buf2, BUFSIZE);
if (udp_send(s1, buf1, BUFSIZE) < 0) {
printf("FAIL\n");
perror(" Cannot send");
goto abort_multicast_ipv6;
}
timeout.tv_sec = 1;
timeout.tv_usec = 0;
udp_fd_zero();
udp_fd_set(s1);
rc = udp_select(&timeout);
if (rc < 0) {
printf("FAIL\n");
perror(" Select failed");
goto abort_multicast_ipv6;
}
if (rc == 0) {
printf("FAIL\n");
printf(" No data waiting (no multicast loopback route?)\n");
goto abort_multicast_ipv6;
}
if (!udp_fd_isset(s1)) {
printf("FAIL\n");
printf(" No data on file descriptor\n");
goto abort_multicast_ipv6;
}
if (udp_recv(s1, buf2, BUFSIZE) < 0) {
printf("FAIL\n");
perror(" Cannot receive");
goto abort_multicast_ipv6;
}
if (memcmp(buf1, buf2, BUFSIZE) != 0) {
printf("FAIL\n");
printf(" Buffer corrupt\n");
goto abort_multicast_ipv6;
}
hname = udp_host_addr(s1); /* we need this for the unicast test... */
printf("Ok\n");
abort_multicast_ipv6:
udp_exit(s1);
#else
printf
("Testing UDP/IP networking (IPv6 loopback) ................................ --\n");
printf
("Testing UDP/IP networking (IPv6 unicast) ................................. --\n");
printf
("Testing UDP/IP networking (IPv6 multicast) ............................... --\n");
#endif
/**********************************************************************/
#ifdef WIN32
printf
("Testing UDP/IP networking (FreeBSD bug) .................................. --\n");
#else
printf
("Testing UDP/IP networking (FreeBSD bug) .................................. ");
fflush(stdout);
status_parent = 0;
randomize(buf1, 64);
s1 = udp_init("224.2.0.1", 5004, 5004, 1);
if (s1 == NULL) {
printf("fail (parent): cannot initialize socket\n");
return 1;
}
rc = fork();
if (rc == -1) {
printf("fail: cannot fork\n");
goto abort_bsd;
} else if (rc == 0) {
/* child */
s2 = udp_init("224.2.0.1", 5004, 5004, 1);
if (s2 == NULL) {
printf("FAIL\n");
printf(" Child cannot initialize socket\n");
exit(0);
}
if (udp_send(s2, buf1, 64) < 0) {
printf("FAIL\n");
perror(" Child cannot send");
exit(0);
}
timeout.tv_sec = 10;
timeout.tv_usec = 0;
udp_fd_zero();
udp_fd_set(s2);
rc = udp_select(&timeout);
if (rc < 0) {
printf("FAIL\n");
perror(" Child select");
exit(0);
}
if (rc == 0) {
printf("FAIL\n");
printf
(" Child: no data waiting (no multicast loopback route?)\n");
exit(0);
}
if (!udp_fd_isset(s2)) {
printf("FAIL\n");
printf(" Child: no data on file descriptor\n");
exit(0);
}
rc = udp_recv(s2, buf2, BUFSIZE);
if (rc < 0) {
printf("FAIL\n");
perror(" Child cannot receive");
exit(0);
}
if (rc != 64) {
printf("FAIL\n");
printf(" Parent: read size incorrect (%d != %d)\n", rc, 64);
goto abort_bsd;
printf("FAIL\n");
printf(" Child: read size incorrect (%d != %d)\n", rc,
64);
exit(0);
}
if (memcmp(buf1, buf2, 64) != 0) {
printf("FAIL\n");
printf(" Parent: buffer corrupt\n");
goto abort_bsd;
}
status_parent = 1;
}
abort_bsd:
wait(&status_child);
if (status_parent && status_child) {
printf("Ok\n");
}
udp_exit(s1);
#endif /* WIN32 */
if (memcmp(buf1, buf2, 64) != 0) {
printf("FAIL\n");
printf(" Child: buffer corrupt\n");
exit(0);
}
udp_exit(s2);
exit(1);
} else {
/* parent */
timeout.tv_sec = 10;
timeout.tv_usec = 0;
udp_fd_zero();
udp_fd_set(s1);
rc = udp_select(&timeout);
if (rc < 0) {
printf("FAIL\n");
perror(" Parent select");
goto abort_bsd;
}
if (rc == 0) {
printf("FAIL\n");
printf
(" Parent: no data waiting (no multicast loopback route?)\n");
goto abort_bsd;
}
if (!udp_fd_isset(s1)) {
printf("FAIL\n");
printf(" Parent: no data on file descriptor\n");
goto abort_bsd;
}
rc = udp_recv(s1, buf2, BUFSIZE);
if (rc < 0) {
printf("FAIL\n");
perror(" Parent cannot receive");
goto abort_bsd;
}
if (rc != 64) {
printf("FAIL\n");
printf(" Parent: read size incorrect (%d != %d)\n", rc,
64);
goto abort_bsd;
}
if (memcmp(buf1, buf2, 64) != 0) {
printf("FAIL\n");
printf(" Parent: buffer corrupt\n");
goto abort_bsd;
}
status_parent = 1;
}
abort_bsd:
wait(&status_child);
if (status_parent && status_child) {
printf("Ok\n");
}
udp_exit(s1);
#endif /* WIN32 */
return 0;
return 0;
}

View File

@@ -43,10 +43,9 @@
#include "crypto/random.h"
#include "test_random.h"
int
test_random(void)
int test_random(void)
{
printf("Testing random number generator .......................................... --\n");
return 0;
printf
("Testing random number generator .......................................... --\n");
return 0;
}

View File

@@ -36,14 +36,12 @@
#include "rtp/rtp.h"
#include "test_rtp.h"
int
test_rtp(void)
int test_rtp(void)
{
printf("Testing RTP .............................................................. ");
fflush(stdout);
printf
("Testing RTP .............................................................. ");
fflush(stdout);
printf("--\n");
return 0;
printf("--\n");
return 0;
}

View File

@@ -39,135 +39,134 @@
#include "tv.h"
#include "test_tv.h"
int
test_tv(void)
int test_tv(void)
{
struct timeval t1, t2;
double d;
double e = 0.0000001; /* epsilon for double comparisons. this is evil. */
uint32_t m1, m2, m3;
struct timeval t1, t2;
double d;
double e = 0.0000001; /* epsilon for double comparisons. this is evil. */
uint32_t m1, m2, m3;
printf("Testing time conversion functions ........................................ ");
printf
("Testing time conversion functions ........................................ ");
/* Test 1: check that tv_add() works... */
/* 1A) Normal operation */
t1.tv_sec = 1;
t1.tv_usec = 0;
tv_add(&t1, 0.8);
if ((t1.tv_sec != 1) && (t1.tv_usec != 800000)) {
printf("FAIL\n");
printf(" tv_add() part A\n");
return 1;
}
/* 1B) Wraparound of tv_usec during the addition */
tv_add(&t1, 0.5);
if ((t1.tv_sec != 2) && (t1.tv_usec != 300000)) {
printf("FAIL\n");
printf(" tv_add() part B\n");
return 1;
}
/* 1C) Wraparound when the offset is greater than one second */
tv_add(&t1, 4.2);
if ((t1.tv_sec != 6) && (t1.tv_usec != 500000)) {
printf("FAIL\n");
printf(" tv_add() part C\n");
return 1;
}
/* Test 1: check that tv_add() works... */
/* 1A) Normal operation */
t1.tv_sec = 1;
t1.tv_usec = 0;
tv_add(&t1, 0.8);
if ((t1.tv_sec != 1) && (t1.tv_usec != 800000)) {
printf("FAIL\n");
printf(" tv_add() part A\n");
return 1;
}
/* 1B) Wraparound of tv_usec during the addition */
tv_add(&t1, 0.5);
if ((t1.tv_sec != 2) && (t1.tv_usec != 300000)) {
printf("FAIL\n");
printf(" tv_add() part B\n");
return 1;
}
/* 1C) Wraparound when the offset is greater than one second */
tv_add(&t1, 4.2);
if ((t1.tv_sec != 6) && (t1.tv_usec != 500000)) {
printf("FAIL\n");
printf(" tv_add() part C\n");
return 1;
}
/* Test 2: check that tv_gt() works... */
/* 2A) Normal operation */
t1.tv_sec = 8143;
t1.tv_usec = 500000;
t2.tv_sec = 4294;
t2.tv_usec = 345678;
if (tv_gt(t2, t1) || !tv_gt(t1, t2)) {
printf("FAIL\n");
printf(" tv_gt() part A\n");
return 1;
}
/* Test 2: check that tv_gt() works... */
/* 2A) Normal operation */
t1.tv_sec = 8143;
t1.tv_usec = 500000;
t2.tv_sec = 4294;
t2.tv_usec = 345678;
if (tv_gt(t2, t1) || !tv_gt(t1, t2)) {
printf("FAIL\n");
printf(" tv_gt() part A\n");
return 1;
}
/* 2B) See if it works when tv_sec values are the same */
t1.tv_sec = 8147;
t1.tv_usec = 500000;
t2.tv_sec = 8147;
t2.tv_usec = 345678;
if (tv_gt(t2, t1) || !tv_gt(t1, t2)) {
printf("FAIL\n");
printf(" tv_gt() part B\n");
return 1;
}
/* 2B) See if it works when tv_sec values are the same */
t1.tv_sec = 8147;
t1.tv_usec = 500000;
t2.tv_sec = 8147;
t2.tv_usec = 345678;
if (tv_gt(t2, t1) || !tv_gt(t1, t2)) {
printf("FAIL\n");
printf(" tv_gt() part B\n");
return 1;
}
/* Test 3: check that tv_diff() works... */
/* 3A) normal operation. comparing floats is tricky :( */
t1.tv_sec = 1065356371; /* Sunday afternoon, 5th October 2003 */
t1.tv_usec = 234947;
t2.tv_sec = 1065356528; /* ...a few minutes later, see how */
t2.tv_usec = 864316; /* fast I type :) */
d = tv_diff(t2, t1);
if ((d <= 157.629369 - e) || (d >= 157.629369 + e)) {
printf("FAIL\n");
printf(" tv_diff: %f != 157.629369\n", d);
return 1;
}
/* 3B) when prev_time is newer than curr_time? Not what we */
/* expect to work, but may as well make sure it gives a */
/* sensible answer, rather than crashing out. */
d = tv_diff(t1, t2);
if ((d <= -157.629369 - e) || (d >= -157.629369 + e)) {
printf("FAIL\n");
printf(" tv_diff: %f != -157.629369\n", d);
return 1;
}
/* Test 3: check that tv_diff() works... */
/* 3A) normal operation. comparing floats is tricky :( */
t1.tv_sec = 1065356371; /* Sunday afternoon, 5th October 2003 */
t1.tv_usec = 234947;
t2.tv_sec = 1065356528; /* ...a few minutes later, see how */
t2.tv_usec = 864316; /* fast I type :) */
d = tv_diff(t2, t1);
if ((d <= 157.629369 - e) || (d >= 157.629369 + e)) {
printf("FAIL\n");
printf(" tv_diff: %f != 157.629369\n", d);
return 1;
}
/* 3B) when prev_time is newer than curr_time? Not what we */
/* expect to work, but may as well make sure it gives a */
/* sensible answer, rather than crashing out. */
d = tv_diff(t1, t2);
if ((d <= -157.629369 - e) || (d >= -157.629369 + e)) {
printf("FAIL\n");
printf(" tv_diff: %f != -157.629369\n", d);
return 1;
}
/* Test 4: check that tv_diff_usec() works... */
/* 4A) normal operation */
t1.tv_sec = 1065356371;
t1.tv_usec = 234947;
t2.tv_sec = 1065356528;
t2.tv_usec = 864316;
if (tv_diff_usec(t2, t1) != 157629369) {
printf("FAIL\n");
printf(" tv_diff_usec: A\n");
return 1;
}
/* 4B) see what happens if the tv_sec values are the same */
t1.tv_sec = 1065356371;
t1.tv_usec = 234947;
t2.tv_sec = 1065356371;
t2.tv_usec = 864316;
if (tv_diff_usec(t2, t1) != 629369) {
printf("FAIL\n");
printf(" tv_diff_usec: B\n");
return 1;
}
/* 4C) close values on a second boundary */
t1.tv_sec = 1065356371;
t1.tv_usec = 999999;
t2.tv_sec = 1065356372;
t2.tv_usec = 000000;
if (tv_diff_usec(t2, t1) != 1) {
printf("FAIL\n");
printf(" tv_diff_usec: B\n");
return 1;
}
/* Test 4: check that tv_diff_usec() works... */
/* 4A) normal operation */
t1.tv_sec = 1065356371;
t1.tv_usec = 234947;
t2.tv_sec = 1065356528;
t2.tv_usec = 864316;
if (tv_diff_usec(t2, t1) != 157629369) {
printf("FAIL\n");
printf(" tv_diff_usec: A\n");
return 1;
}
/* 4B) see what happens if the tv_sec values are the same */
t1.tv_sec = 1065356371;
t1.tv_usec = 234947;
t2.tv_sec = 1065356371;
t2.tv_usec = 864316;
if (tv_diff_usec(t2, t1) != 629369) {
printf("FAIL\n");
printf(" tv_diff_usec: B\n");
return 1;
}
/* 4C) close values on a second boundary */
t1.tv_sec = 1065356371;
t1.tv_usec = 999999;
t2.tv_sec = 1065356372;
t2.tv_usec = 000000;
if (tv_diff_usec(t2, t1) != 1) {
printf("FAIL\n");
printf(" tv_diff_usec: B\n");
return 1;
}
/* Test 5: check that get_local_mediatime() works... */
m1 = get_local_mediatime();
usleep(250000); /* Sleep for a minimum of 250ms */
m2 = get_local_mediatime();
if (m2 - m1 < 22500) {
printf("FAIL\n");
printf(" get_local_mediatime() runs fast\n");
return 1;
}
m3 = get_local_mediatime();
if (m3 < m2) {
printf("FAIL\n");
printf(" get_local_mediatime() time runs backwards\n");
return 1;
}
/* Test 5: check that get_local_mediatime() works... */
m1 = get_local_mediatime();
usleep(250000); /* Sleep for a minimum of 250ms */
m2 = get_local_mediatime();
if (m2 - m1 < 22500) {
printf("FAIL\n");
printf(" get_local_mediatime() runs fast\n");
return 1;
}
m3 = get_local_mediatime();
if (m3 < m2) {
printf("FAIL\n");
printf(" get_local_mediatime() time runs backwards\n");
return 1;
}
printf("Ok\n");
return 0;
printf("Ok\n");
return 0;
}

View File

@@ -44,27 +44,26 @@
#include "video_capture.h"
#include "test_video_capture.h"
int
test_video_capture(void)
int test_video_capture(void)
{
struct vidcap_type *vt;
int i;
printf("Testing video capture device detection ................................... ");
if (vidcap_init_devices() != 0) {
printf("FAIL\n");
printf(" Cannot probe video capture devices\n");
return 1;
}
printf("Ok\n");
struct vidcap_type *vt;
int i;
for (i = 0; i < vidcap_get_device_count(); i++) {
vt = vidcap_get_device_details(i);
printf(" \"%s\"\n", vt->name);
printf(" description: %s\n", vt->description);
printf(" image size : %dx%d\n", vt->width, vt->height);
}
vidcap_free_devices();
return 0;
printf
("Testing video capture device detection ................................... ");
if (vidcap_init_devices() != 0) {
printf("FAIL\n");
printf(" Cannot probe video capture devices\n");
return 1;
}
printf("Ok\n");
for (i = 0; i < vidcap_get_device_count(); i++) {
vt = vidcap_get_device_details(i);
printf(" \"%s\"\n", vt->name);
printf(" description: %s\n", vt->description);
printf(" image size : %dx%d\n", vt->width, vt->height);
}
vidcap_free_devices();
return 0;
}

View File

@@ -44,60 +44,68 @@
#include "video_display.h"
#include "test_video_display.h"
int
test_video_display(void)
int test_video_display(void)
{
display_type_t *dt;
int i;
unsigned int j;
int argc = 0;
char *argv[1];
display_type_t *dt;
int i;
unsigned int j;
int argc = 0;
char *argv[1];
argv[0] = "run_tests";
printf("Testing video hardware detection ......................................... ");
if (display_init_devices() != 0) {
printf("FAIL\n");
printf(" Cannot probe video devices\n");
return 1;
}
printf("Ok\n");
argv[0] = "run_tests";
for (i = 0; i < display_get_device_count(); i++) {
dt = display_get_device_details(i);
printf(" \"%s\"\n", dt->name);
printf(" description: %s\n", dt->description);
printf(" formats :");
for (j = 0; j < dt->num_formats; j++) {
switch (dt->formats[j].size) {
case DS_176x144 : printf(" QCIF");
break;
case DS_352x288 : printf(" CIF");
break;
case DS_702x576 : printf(" SCIF");
break;
case DS_1920x1080 : printf(" 1080i");
break;
case DS_1280x720 : printf(" 720p");
break;
case DS_NONE : printf(" NONE");
continue;
}
switch (dt->formats[j].colour_mode) {
case DC_YUV : printf("/YUV");
break;
case DC_RGB : printf("/RGB");
break;
case DC_NONE : printf("/NONE");
break;
}
if (dt->formats[j].num_images != -1) {
printf("/%d", dt->formats[j].num_images);
}
}
printf("\n");
}
display_free_devices();
return 0;
printf
("Testing video hardware detection ......................................... ");
if (display_init_devices() != 0) {
printf("FAIL\n");
printf(" Cannot probe video devices\n");
return 1;
}
printf("Ok\n");
for (i = 0; i < display_get_device_count(); i++) {
dt = display_get_device_details(i);
printf(" \"%s\"\n", dt->name);
printf(" description: %s\n", dt->description);
printf(" formats :");
for (j = 0; j < dt->num_formats; j++) {
switch (dt->formats[j].size) {
case DS_176x144:
printf(" QCIF");
break;
case DS_352x288:
printf(" CIF");
break;
case DS_702x576:
printf(" SCIF");
break;
case DS_1920x1080:
printf(" 1080i");
break;
case DS_1280x720:
printf(" 720p");
break;
case DS_NONE:
printf(" NONE");
continue;
}
switch (dt->formats[j].colour_mode) {
case DC_YUV:
printf("/YUV");
break;
case DC_RGB:
printf("/RGB");
break;
case DC_NONE:
printf("/NONE");
break;
}
if (dt->formats[j].num_images != -1) {
printf("/%d", dt->formats[j].num_images);
}
}
printf("\n");
}
display_free_devices();
return 0;
}