|
From: <do...@us...> - 2010-02-02 14:48:50
|
Revision: 1464
http://iaxclient.svn.sourceforge.net/iaxclient/?rev=1464&view=rev
Author: dohpaz
Date: 2010-02-02 14:48:34 +0000 (Tue, 02 Feb 2010)
Log Message:
-----------
Merge trunk r1449:1463 out to elbunce branch.
Modified Paths:
--------------
branches/team/elbunce/iaxclient/lib/audio_portaudio.c
branches/team/elbunce/iaxclient/lib/codec_ffmpeg.c
branches/team/elbunce/iaxclient/lib/codec_theora.c
branches/team/elbunce/iaxclient/lib/iaxclient.h
branches/team/elbunce/iaxclient/lib/iaxclient_lib.h
branches/team/elbunce/iaxclient/lib/slice.c
branches/team/elbunce/iaxclient/lib/slice.h
branches/team/elbunce/iaxclient/lib/video.c
branches/team/elbunce/iaxclient/simpleclient/stresstest/file.c
branches/team/elbunce/iaxclient/simpleclient/stresstest/stresstest.c
Property Changed:
----------------
branches/team/elbunce/iaxclient/
Property changes on: branches/team/elbunce/iaxclient
___________________________________________________________________
Added: svn:mergeinfo
+ /trunk:1450-1463
Modified: branches/team/elbunce/iaxclient/lib/audio_portaudio.c
===================================================================
--- branches/team/elbunce/iaxclient/lib/audio_portaudio.c 2010-01-29 17:41:25 UTC (rev 1463)
+++ branches/team/elbunce/iaxclient/lib/audio_portaudio.c 2010-02-02 14:48:34 UTC (rev 1464)
@@ -551,51 +551,67 @@
return 0;
}
+// NOTE: pa_open does not require an input device for success
static int pa_open(int single, int inMono, int outMono)
{
PaError err;
- PaDeviceInfo *result;
+ PaDeviceInfo *in_dev_info, *out_dev_info;
- struct PaStreamParameters in_stream_params, out_stream_params, no_device;
+ struct PaStreamParameters in_stream_params, out_stream_params, *in_params;
+
+ if ( selectedInput != paNoDevice )
+ {
+ in_dev_info = (PaDeviceInfo *)Pa_GetDeviceInfo(selectedInput);
+ if ( in_dev_info == NULL )
+ return -1;
+
in_stream_params.device = selectedInput;
in_stream_params.channelCount = (inMono ? 1 : 2);
in_stream_params.sampleFormat = paInt16;
- result = (PaDeviceInfo *)Pa_GetDeviceInfo(selectedInput);
- if ( result == NULL ) return -1;
- in_stream_params.suggestedLatency = result->defaultLowInputLatency;
+ in_stream_params.suggestedLatency = in_dev_info->defaultLowInputLatency;
in_stream_params.hostApiSpecificStreamInfo = NULL;
+ in_params = &in_stream_params;
+ }
+ else
+ in_params = NULL;
+
+ out_dev_info = (PaDeviceInfo *)Pa_GetDeviceInfo(selectedOutput);
+ if ( out_dev_info == NULL )
+ return -1;
+
out_stream_params.device = selectedOutput;
out_stream_params.channelCount = (outMono ? 1 : 2);
out_stream_params.sampleFormat = paInt16;
- result = (PaDeviceInfo *)Pa_GetDeviceInfo(selectedOutput);
- if ( result == NULL ) return -1;
- out_stream_params.suggestedLatency = result->defaultLowOutputLatency;
+ out_stream_params.suggestedLatency = out_dev_info->defaultLowOutputLatency;
out_stream_params.hostApiSpecificStreamInfo = NULL;
- no_device.device = paNoDevice;
- no_device.channelCount = 0;
- no_device.sampleFormat = paInt16;
- result = (PaDeviceInfo *)Pa_GetDeviceInfo(selectedInput);
- if ( result == NULL ) return -1;
- no_device.suggestedLatency = result->defaultLowInputLatency; // FEEDBACK - unsure if appropriate
- no_device.hostApiSpecificStreamInfo = NULL;
-
- if ( single )
+ // if there is no input device, there's no point in dual streams
+ if ( single || selectedInput == paNoDevice )
{
- err = Pa_OpenStream(&iStream,
- &in_stream_params,
+ err = Pa_OpenStream(&oStream,
+ in_params,
&out_stream_params,
iaxci_sample_rate,
SAMPLES_PER_FRAME,
paNoFlag,
(PaStreamCallback *)pa_callback,
NULL);
- if (err != paNoError) return -1;
- oStream = iStream;
+ if (err != paNoError)
+ return -1;
+
+ iStream = oStream;
oneStream = 1;
} else
{
+ struct PaStreamParameters no_device;
+
+ no_device.device = paNoDevice;
+ no_device.channelCount = 0;
+ no_device.sampleFormat = paInt16;
+ no_device.suggestedLatency = in_dev_info->defaultLowInputLatency; // FEEDBACK - unsure if appropriate
+ no_device.hostApiSpecificStreamInfo = NULL;
+
err = Pa_OpenStream(&iStream,
&in_stream_params,
&no_device,
@@ -604,7 +620,8 @@
paNoFlag,
(PaStreamCallback *)pa_callback,
NULL);
- if ( err != paNoError ) return -1;
+ if ( err != paNoError )
+ return -1;
err = Pa_OpenStream(&oStream,
&no_device,
@@ -762,19 +779,28 @@
if ( pa_openstreams(d) )
return -1;
- if ( Pa_StartStream(iStream) != paNoError )
+ if ( selectedInput == paNoDevice )
+ {
+ if ( Pa_StartStream(oStream) != paNoError )
return -1;
+ oMixer = Px_OpenMixer(oStream, 0);
+ }
+ else
+ {
+ if ( Pa_StartStream(iStream) != paNoError )
+ return -1;
+
iMixer = Px_OpenMixer(iStream, 0);
if ( !oneStream )
{
- PaError err = Pa_StartStream(oStream);
- oMixer = Px_OpenMixer(oStream, 0);
- if ( err != paNoError )
+ if ( Pa_StartStream(oStream) != paNoError )
{
Pa_StopStream(iStream);
return -1;
+ }
+ oMixer = Px_OpenMixer(oStream, 0);
}
}
@@ -842,13 +868,13 @@
if ( sounds )
return 0;
- err = Pa_AbortStream(iStream);
- err = Pa_CloseStream(iStream);
+ err = Pa_AbortStream(oStream);
+ err = Pa_CloseStream(oStream);
if ( !oneStream )
{
- err = Pa_AbortStream(oStream);
- err = Pa_CloseStream(oStream);
+ err = Pa_AbortStream(iStream);
+ err = Pa_CloseStream(iStream);
}
if ( auxStream )
@@ -865,8 +891,8 @@
* I bet if it's gone, no one will miss it. Such a cold, cold world!
static void pa_shutdown()
{
- CloseAudioStream( iStream );
- if(!oneStream) CloseAudioStream( oStream );
+ CloseAudioStream( oStream );
+ if(!oneStream) CloseAudioStream( iStream );
if(auxStream) CloseAudioStream( aStream );
}
*/
Modified: branches/team/elbunce/iaxclient/lib/codec_ffmpeg.c
===================================================================
--- branches/team/elbunce/iaxclient/lib/codec_ffmpeg.c 2010-01-29 17:41:25 UTC (rev 1463)
+++ branches/team/elbunce/iaxclient/lib/codec_ffmpeg.c 2010-02-02 14:48:34 UTC (rev 1464)
@@ -209,7 +209,7 @@
}
static int decode_iaxc_slice(struct iaxc_video_codec * c, int inlen,
- char * in, int * outlen, char * out)
+ char * in, int * outlen, char * out, int * frames_dropped)
{
struct decoder_ctx *d = (struct decoder_ctx *) c->decstate;
struct slice_header_t * sh_saved = &d->slice_header;
@@ -217,10 +217,15 @@
char * inp;
int ret;
+ *frames_dropped = 0;
+
inp = parse_slice_header(in, &sh_this);
if ( !inp )
+ {
+ *frames_dropped = 1;
return -1;
+ }
inlen -= inp - in;
@@ -237,6 +242,8 @@
}
else if ( frame_delta > 0 )
{
+ *frames_dropped = frame_delta - 1;
+
/* This slice belongs to a future frame */
if ( sh_saved->slice_index > 0 )
{
@@ -254,7 +261,10 @@
reset_decoder_frame_state(d);
if ( ret )
+ {
+ *frames_dropped += 1;
return -1;
+ }
}
sh_saved->frame_index = sh_this.frame_index;
@@ -272,6 +282,7 @@
{
fprintf(stderr,
"codec_ffmpeg: decode: slice overflows decoder frame buffer\n");
+ *frames_dropped = 1;
return -1;
}
@@ -294,7 +305,10 @@
reset_decoder_frame_state(d);
if ( ret )
+ {
+ *frames_dropped = 1;
return -1;
+ }
return 0;
}
Modified: branches/team/elbunce/iaxclient/lib/codec_theora.c
===================================================================
--- branches/team/elbunce/iaxclient/lib/codec_theora.c 2010-01-29 17:41:25 UTC (rev 1463)
+++ branches/team/elbunce/iaxclient/lib/codec_theora.c 2010-02-02 14:48:34 UTC (rev 1464)
@@ -66,6 +66,7 @@
theora_comment tc;
struct deslicer_context *dsc;
int got_key_frame;
+ unsigned short prev_src_id;
};
struct theora_encoder
@@ -112,7 +113,7 @@
}
static int decode(struct iaxc_video_codec *c, int inlen, const char *in,
- int *outlen, char *out)
+ int *outlen, char *out, int * frames_dropped)
{
struct theora_decoder *d;
ogg_packet op;
@@ -123,6 +124,8 @@
int flen;
char *frame;
+ *frames_dropped = 0;
+
// Sanity checks
if ( !c || !c->decstate || !in || inlen <= 0 || !out || !outlen )
return -1;
@@ -132,7 +135,7 @@
if ( !d->dsc )
return -1;
- frame = deslice(in, inlen, &flen, d->dsc);
+ frame = deslice(in, inlen, &flen, d->dsc, frames_dropped);
if ( frame == NULL )
return 1;
@@ -141,8 +144,12 @@
op.bytes = flen;
op.packet = (unsigned char *)frame;
- /* reject all incoming frames until we get a key frame */
- if ( !d->got_key_frame )
+ /* Reject all incoming frames until we get a key frame.
+ * Similarly, check for a change in who is sending the video.
+ * We shouldn't use frames from a new source until
+ * we get a keyframe
+ */
+ if ( !d->got_key_frame || d->prev_src_id != d->dsc->source_id )
{
if ( theora_packet_iskeyframe(&op) )
d->got_key_frame = 1;
@@ -177,6 +184,10 @@
return -1;
}
+ // keep track of the source id (from the most
+ // recent valid desliced frame) to detect a switch
+ d->prev_src_id = d->dsc->source_id;
+
//clear output
memset(out, 127, my_out_len);
@@ -304,7 +315,11 @@
slice_set->key_frame = theora_packet_iskeyframe(&op) == 1;
// Slice the frame
- slice((char *)op.packet, op.bytes, slice_set, e->sc);
+ if ( slice((char *)op.packet, op.bytes, slice_set, e->sc) )
+ {
+ fprintf(stderr, "codec_theora: failed to slice an encoded packet\n");
+ return -1;
+ }
return 0;
}
Modified: branches/team/elbunce/iaxclient/lib/iaxclient.h
===================================================================
--- branches/team/elbunce/iaxclient/lib/iaxclient.h 2010-01-29 17:41:25 UTC (rev 1463)
+++ branches/team/elbunce/iaxclient/lib/iaxclient.h 2010-02-02 14:48:34 UTC (rev 1464)
@@ -270,7 +270,7 @@
int format;
/*!
- The audio format of the call.
+ The video format of the call.
\see IAXC_FORMAT_JPEG, IAXC_FORMAT_PNG, IAXC_FORMAT_H261, IAXC_FORMAT_H263,
IAXC_FORMAT_H263_PLUS, IAXC_FORMAT_H264, IAXC_FORMAT_MPEG4,
Modified: branches/team/elbunce/iaxclient/lib/iaxclient_lib.h
===================================================================
--- branches/team/elbunce/iaxclient/lib/iaxclient_lib.h 2010-01-29 17:41:25 UTC (rev 1463)
+++ branches/team/elbunce/iaxclient/lib/iaxclient_lib.h 2010-02-02 14:48:34 UTC (rev 1464)
@@ -171,8 +171,10 @@
void (*destroy) ( struct iaxc_audio_codec *codec);
};
+//FIXME: This is all very static. What of higher
+// bitrates, that require more slices?
#define MAX_TRUNK_LEN (1<<16)
-#define MAX_NO_SLICES 32
+#define MAX_NO_SLICES 64
struct slice_set_t
{
@@ -197,7 +199,8 @@
int (*encode)(struct iaxc_video_codec * codec, int inlen,
const char * in, struct slice_set_t * out);
int (*decode)(struct iaxc_video_codec * codec, int inlen,
- const char * in, int * outlen, char * out);
+ const char * in, int * outlen, char * out,
+ int * frames_dropped);
void (*destroy)(struct iaxc_video_codec * codec);
};
Modified: branches/team/elbunce/iaxclient/lib/slice.c
===================================================================
--- branches/team/elbunce/iaxclient/lib/slice.c 2010-01-29 17:41:25 UTC (rev 1463)
+++ branches/team/elbunce/iaxclient/lib/slice.c 2010-02-02 14:48:34 UTC (rev 1464)
@@ -41,10 +41,30 @@
int i, ssize;
if ( data == NULL || slice_set == NULL || sc == NULL)
+ {
+ fprintf(stderr, "slice: invalid param(s): data=%p, set=%p, context=%p\n",
+ data, slice_set, sc);
return -1;
+ }
+ // Theora packets can be 0-byte (delta-frame with no coded blocks)
+ if ( size )
+ {
// Figure out how many slices we need
slice_set->num_slices = (size - 1) / sc->slice_size + 1;
+
+ if ( slice_set->num_slices > MAX_NO_SLICES )
+ {
+ fprintf(stderr, "slice: %d-byte frame is too large "
+ "- would require %d slices\n",
+ size, slice_set->num_slices);
+ return -1;
+ }
+ }
+ else
+ {
+ slice_set->num_slices = 1;
+ }
for ( i = 0; i < slice_set->num_slices; i++ )
{
@@ -94,11 +114,13 @@
}
char *
-deslice(const char *in, int inlen, int *outlen, struct deslicer_context *dsc)
+deslice(const char *in, int inlen, int *outlen, struct deslicer_context *dsc, int *frames_dropped)
{
unsigned char frame_index, slice_index, num_slices, version;
unsigned short source_id;
+ *frames_dropped = 0;
+
// Sanity checks
if ( dsc == NULL || in == NULL || inlen <= 0 || outlen == NULL )
return NULL;
@@ -139,10 +161,14 @@
/* Slice belongs to a new frame */
dsc->frame_index = frame_index;
+ *frames_dropped += frame_delta - 1;
+
if ( dsc->slice_count > 0 )
{
/* Current frame is incomplete, drop it */
reset_deslicer_context(dsc);
+
+ *frames_dropped += 1;
}
}
} else
@@ -159,6 +185,9 @@
if ( dsc->slice_size * slice_index + inlen > MAX_ENCODED_FRAME_SIZE )
{
// Frame would be too large, ignore slice
+ fprintf(stderr, "deslice: dropping frame that's > %d bytes\n",
+ MAX_ENCODED_FRAME_SIZE);
+ *frames_dropped = 1;
return NULL;
}
Modified: branches/team/elbunce/iaxclient/lib/slice.h
===================================================================
--- branches/team/elbunce/iaxclient/lib/slice.h 2010-01-29 17:41:25 UTC (rev 1463)
+++ branches/team/elbunce/iaxclient/lib/slice.h 2010-02-02 14:48:34 UTC (rev 1464)
@@ -39,7 +39,12 @@
#include "iaxclient_lib.h"
-#define MAX_ENCODED_FRAME_SIZE 48 * 1024
+// We don't bother deslicing frames larger than this,
+// but we DO slice-up frames as long as they don't exceed
+// MAX_NO_SLICES, each up to MAX_TRUNK_LEN long
+// ( see definition of struct slice_set_t )
+//FIXME: this doesn't depend on the bitrate
+#define MAX_ENCODED_FRAME_SIZE 96 * 1024
struct slicer_context
{
@@ -104,6 +109,7 @@
* outlen with the frame size if successful
*/
char *
-deslice(const char *in, int inlen, int *outlen, struct deslicer_context *dsc);
+deslice(const char *in, int inlen, int *outlen, struct deslicer_context *dsc,
+ int * frames_dropped);
#endif
Modified: branches/team/elbunce/iaxclient/lib/video.c
===================================================================
--- branches/team/elbunce/iaxclient/lib/video.c 2010-01-29 17:41:25 UTC (rev 1463)
+++ branches/team/elbunce/iaxclient/lib/video.c 2010-02-02 14:48:34 UTC (rev 1464)
@@ -1255,6 +1255,7 @@
int ret;
struct timeval now;
long time;
+ int frames_dropped;
if ( !call )
return 0;
@@ -1311,8 +1312,10 @@
call->vdecoder->video_stats.acc_recv_size * 8000 / time;
ret = call->vdecoder->decode(call->vdecoder, encoded_video_len,
- (char *)encoded_video, &out_size, yuv_buf);
+ (char *)encoded_video, &out_size, yuv_buf, &frames_dropped);
+ call->vdecoder->video_stats.dropped_frames += (unsigned long) frames_dropped;
+
if ( ret < 0 )
{
fprintf(stderr, "ERROR: decode error\n");
@@ -1823,7 +1826,14 @@
vinfo.sc = create_slicer_context((unsigned short)rand(),
vfinfo.fragsize);
- slice(data, size, &slice_set, vinfo.sc);
+ if ( slice(data, size, &slice_set, vinfo.sc) )
+ {
+ fprintf(stderr, "iaxc_push_video: Failed to slice frame,"
+ " call %d, size %d\n",
+ selected_call, size);
+ return -1;
+ }
+
for ( i = 0 ; i < slice_set.num_slices ; i++ )
{
if ( iax_send_video_trunk(call->session,
Modified: branches/team/elbunce/iaxclient/simpleclient/stresstest/file.c
===================================================================
--- branches/team/elbunce/iaxclient/simpleclient/stresstest/file.c 2010-01-29 17:41:25 UTC (rev 1463)
+++ branches/team/elbunce/iaxclient/simpleclient/stresstest/file.c 2010-02-02 14:48:34 UTC (rev 1464)
@@ -199,8 +199,8 @@
read_speex_cb(oggz, op, serialno, data);
} else
{
- mylog("Got unknown ogg packet, serialno=%d, size=%d, "
- "packetno=%d, granulepos=%d\n",
+ mylog("Got unknown ogg packet, serialno=%ld, size=%ld, "
+ "packetno=%lld, granulepos=%lld\n",
serialno, op->bytes,
op->packetno, op->granulepos);
}
Modified: branches/team/elbunce/iaxclient/simpleclient/stresstest/stresstest.c
===================================================================
--- branches/team/elbunce/iaxclient/simpleclient/stresstest/stresstest.c 2010-01-29 17:41:25 UTC (rev 1463)
+++ branches/team/elbunce/iaxclient/simpleclient/stresstest/stresstest.c 2010-02-02 14:48:34 UTC (rev 1464)
@@ -69,8 +69,9 @@
static int fragsize = 1400;
static int call_established = 0;
-static int running = 0;
+static int running = 1;
+static int camera_enabled_sent = 0;
static int send_video = 1;
static int send_audio = 1;
static int print_netstats = 0;
@@ -221,27 +222,31 @@
return 0;
}
-void process_text_message(char *message)
+void process_text_message(const char * message)
{
unsigned int prefs;
+ const char ctrl_str[] = "CONTROL:";
+ const int ctrl_strlen = strlen(ctrl_str);
- if ( strncmp(message, "CONTROL:", strlen("CONTROL:")) == 0 )
+ if ( strncmp(message, ctrl_str, ctrl_strlen) == 0 )
{
- message += strlen("CONTROL:");
+ message += ctrl_strlen;
if ( strcmp(message, "STOPVIDEO") == 0 )
{
// Stop sending video
prefs = iaxc_get_video_prefs();
prefs = prefs | IAXC_VIDEO_PREF_SEND_DISABLE ;
iaxc_set_video_prefs(prefs);
- } else if ( strcmp(message, "STARTVIDEO") == 0 )
+ }
+ else if ( strcmp(message, "STARTVIDEO") == 0 )
{
// Start sending video
prefs = iaxc_get_video_prefs();
prefs = prefs & ~IAXC_VIDEO_PREF_SEND_DISABLE ;
iaxc_set_video_prefs(prefs);
}
- } else
+ }
+ else
mylog("Text message received: %s\n", message);
}
@@ -534,8 +539,7 @@
// Wait for the call to be established;
while ( !call_established && running )
{
- struct timeval now;
- now = get_now();
+ struct timeval now = get_now();
if ( connect_timeout_ms > 0 &&
msecdiff(&start_time, &now) > connect_timeout_ms )
{
@@ -546,7 +550,6 @@
iaxc_millisleep(5);
}
- running = 1;
while ( running )
{
struct timeval now = get_now();
@@ -571,7 +574,15 @@
if ( !loop && video_is_eos() )
break;
if ( send_video && op != NULL && op->bytes > 0 )
+ {
+ if ( !camera_enabled_sent )
+ {
+ /* Let app_conference know that we can send video */
+ iaxc_send_text("CONTROL:CAMERA_ENABLED");
+ camera_enabled_sent = 1;
+ }
iaxc_push_video(op->packet, op->bytes, 1);
+ }
}
// Tight spinloops are bad, mmmkay?
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|