mirror of
https://github.com/outbackdingo/UltraGrid.git
synced 2026-04-05 08:04:41 +00:00
reindent
This commit is contained in:
@@ -62,9 +62,7 @@
|
||||
#undef DEBUG
|
||||
#undef DEBUG_MEM
|
||||
|
||||
@BOTTOM@
|
||||
|
||||
@ BOTTOM @
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
#define WORDS_SMALLENDIAN
|
||||
#endif
|
||||
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
double drand48(void)
|
||||
{
|
||||
unsigned int x = (rand() << 16) | rand();
|
||||
return ((double)x / (double)0xffffffff);
|
||||
return ((double)x / (double)0xffffffff);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
1240
ultragrid/src/main.c
1240
ultragrid/src/main.c
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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, ×tamp) < 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, ×tamp) < 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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) */
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user