Index: /pjproject/trunk/pjmedia/src/pjmedia-codec/g7221.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia-codec/g7221.c	(revision 4000)
+++ /pjproject/trunk/pjmedia/src/pjmedia-codec/g7221.c	(revision 4001)
@@ -760,13 +760,12 @@
 {
     codec_private_t *codec_data = (codec_private_t*) codec->codec_data;
-    const Word16 *pcm_input;
-    Word16 mlt_coefs[MAX_SAMPLES_PER_FRAME];
-    Word16 mag_shift;
+    unsigned nsamples, processed;
 
     /* Check frame in & out size */
-    PJ_ASSERT_RETURN((pj_uint16_t)input->size == 
-		     (codec_data->samples_per_frame<<1),
-		     PJMEDIA_CODEC_EPCMTOOSHORT);
-    PJ_ASSERT_RETURN(output_buf_len >= codec_data->frame_size,
+    nsamples = input->size >> 1;
+    PJ_ASSERT_RETURN(nsamples % codec_data->samples_per_frame == 0, 
+		     PJMEDIA_CODEC_EPCMFRMINLEN);
+    PJ_ASSERT_RETURN(output_buf_len >= codec_data->frame_size * nsamples /
+		     codec_data->samples_per_frame,
 		     PJMEDIA_CODEC_EFRMTOOSHORT);
 
@@ -800,39 +799,50 @@
     }
 
-    /* Encoder adjust the input signal level */
-    if (codec_data->pcm_shift) {
-	unsigned i;
-	pcm_input = (const Word16*)input->buf;
-	for (i=0; i<codec_data->samples_per_frame; ++i) {
-	    codec_data->enc_frame[i] = 
-		(pj_int16_t)(pcm_input[i] >> codec_data->pcm_shift);
+    processed = 0;
+    output->size = 0;
+    while (processed < nsamples) {
+	Word16 mlt_coefs[MAX_SAMPLES_PER_FRAME];
+	Word16 mag_shift;
+	const Word16 *pcm_input;
+	pj_int8_t *out_bits;
+	
+	pcm_input = (const Word16*)input->buf + processed;
+	out_bits = (pj_int8_t*)output->buf + output->size;
+
+	/* Encoder adjust the input signal level */
+	if (codec_data->pcm_shift) {
+	    unsigned i;
+	    for (i=0; i<codec_data->samples_per_frame; ++i) {
+		codec_data->enc_frame[i] = 
+			(Word16)(pcm_input[i] >> codec_data->pcm_shift);
+	    }
+	    pcm_input = codec_data->enc_frame;
 	}
-	pcm_input = codec_data->enc_frame;
-    } else {
-	pcm_input = (const Word16*)input->buf;
-    }
-
-    /* Convert input samples to rmlt coefs */
-    mag_shift = samples_to_rmlt_coefs(pcm_input,
-				      codec_data->enc_old_frame, 
-				      mlt_coefs, 
-				      codec_data->samples_per_frame);
-
-    /* Encode the mlt coefs. Note that encoder output stream is 16 bit array,
-     * so we need to take care about endianness.
-     */
-    encoder(codec_data->frame_size_bits,
-	    codec_data->number_of_regions,
-	    mlt_coefs,
-	    mag_shift,
-	    output->buf);
-
-    /* Encoder output are in native host byte order, while ITU says
-     * it must be in network byte order (MSB first).
-     */
-    swap_bytes((pj_uint16_t*)output->buf, codec_data->frame_size/2);
+
+	/* Convert input samples to rmlt coefs */
+	mag_shift = samples_to_rmlt_coefs(pcm_input,
+					  codec_data->enc_old_frame, 
+					  mlt_coefs, 
+					  codec_data->samples_per_frame);
+
+	/* Encode the mlt coefs. Note that encoder output stream is
+	 * 16 bit array, so we need to take care about endianness.
+	 */
+	encoder(codec_data->frame_size_bits,
+		codec_data->number_of_regions,
+		mlt_coefs,
+		mag_shift,
+		(Word16*)out_bits);
+
+	/* Encoder output are in native host byte order, while ITU says
+	 * it must be in network byte order (MSB first).
+	 */
+	swap_bytes((pj_uint16_t*)out_bits, codec_data->frame_size/2);
+
+	processed += codec_data->samples_per_frame;
+	output->size += codec_data->frame_size;
+    }
 
     output->type = PJMEDIA_FRAME_TYPE_AUDIO;
-    output->size = codec_data->frame_size;
     output->timestamp = input->timestamp;
 
Index: /pjproject/trunk/pjsip/src/pjsip/sip_transaction.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip/sip_transaction.c	(revision 4000)
+++ /pjproject/trunk/pjsip/src/pjsip/sip_transaction.c	(revision 4001)
@@ -3240,5 +3240,11 @@
 {
     pj_assert(tsx->state == PJSIP_TSX_STATE_TERMINATED);
-    pj_assert(event->type == PJSIP_EVENT_TIMER);
+
+    /* Ignore events other than timer. This used to be an assertion but
+     * events may genuinely arrive at this state.
+     */
+    if (event->type != PJSIP_EVENT_TIMER) {
+	return PJ_EIGNORED;
+    }
 
     /* Destroy this transaction */
Index: /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 4000)
+++ /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 4001)
@@ -1361,4 +1361,8 @@
     int i;  /* Must be signed */
 
+    if (pjsua_var.endpt) {
+	PJ_LOG(4,(THIS_FILE, "Shutting down, flags=%d...", flags));
+    }
+
     if (pjsua_var.state > PJSUA_STATE_NULL &&
 	pjsua_var.state < PJSUA_STATE_CLOSING)
@@ -1373,5 +1377,10 @@
     for (i=0; i<(int)pjsua_var.ua_cfg.thread_cnt; ++i) {
 	if (pjsua_var.thread[i]) {
-	    pj_thread_join(pjsua_var.thread[i]);
+	    pj_status_t status;
+	    status = pj_thread_join(pjsua_var.thread[i]);
+	    if (status != PJ_SUCCESS) {
+		PJ_PERROR(4,(THIS_FILE, status, "Error joining worker thread"));
+		pj_thread_sleep(1000);
+	    }
 	    pj_thread_destroy(pjsua_var.thread[i]);
 	    pjsua_var.thread[i] = NULL;
@@ -1381,6 +1390,4 @@
     if (pjsua_var.endpt) {
 	unsigned max_wait;
-
-	PJ_LOG(4,(THIS_FILE, "Shutting down, flags=%d...", flags));
 
 	pj_log_push_indent();
