Index: pjproject/trunk/pjsip-apps/src/samples/pcaputil.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/samples/pcaputil.c	(revision 1766)
+++ pjproject/trunk/pjsip-apps/src/samples/pcaputil.c	(revision 1769)
@@ -58,10 +58,17 @@
 ;
 
-static pj_caching_pool cp;
-static pj_pool_t *pool;
-static pjmedia_endpt *mept;
-static pj_pcap_file *pcap;
-static pjmedia_port *wav;
-static pjmedia_transport *srtp;
+static struct app
+{
+    pj_caching_pool	 cp;
+    pj_pool_t		*pool;
+    pjmedia_endpt	*mept;
+    pj_pcap_file	*pcap;
+    pjmedia_port	*wav;
+    pjmedia_codec	*codec;
+    unsigned		 pt;
+    pjmedia_transport	*srtp;
+    pjmedia_rtp_session	 rtp_sess;
+    pj_bool_t		 rtp_sess_init;
+} app;
 
 static void err_exit(const char *title, pj_status_t status)
@@ -75,10 +82,27 @@
     }
 
-    if (srtp) pjmedia_transport_close(srtp);
-    if (wav) pjmedia_port_destroy(wav);
-    if (pcap) pj_pcap_close(pcap);
-    if (mept) pjmedia_endpt_destroy(mept);
-    if (pool) pj_pool_release(pool);
-    pj_caching_pool_destroy(&cp);
+    if (app.srtp) pjmedia_transport_close(app.srtp);
+    if (app.wav) {
+        pj_ssize_t pos = pjmedia_wav_writer_port_get_pos(app.wav);
+        if (pos >= 0) {
+            unsigned msec;
+            msec = pos / 2 * 1000 / app.wav->info.clock_rate;
+            printf("Written: %dm:%02ds.%03d\n",
+                    msec / 1000 / 60,
+                    (msec / 1000) % 60,
+                    msec % 1000);
+        }
+	pjmedia_port_destroy(app.wav);
+    }
+    if (app.pcap) pj_pcap_close(app.pcap);
+    if (app.codec) {
+	pjmedia_codec_mgr *cmgr;
+	app.codec->op->close(app.codec);
+	cmgr = pjmedia_endpt_get_codec_mgr(app.mept);
+	pjmedia_codec_mgr_dealloc_codec(cmgr, app.codec);
+    }
+    if (app.mept) pjmedia_endpt_destroy(app.mept);
+    if (app.pool) pj_pool_release(app.pool);
+    pj_caching_pool_destroy(&app.cp);
     pj_shutdown();
 
@@ -98,25 +122,89 @@
 		     unsigned *payload_size)
 {
-    pj_size_t sz = bufsize;
     pj_status_t status;
 
-    status = pj_pcap_read_udp(pcap, buf, &sz);
-    if (status != PJ_SUCCESS)
-	err_exit("Error reading PCAP file", status);
-
-    if (sz < sizeof(pjmedia_rtp_hdr) + 10) {
-	err_exit("Invalid RTP packet", PJ_SUCCESS);
-    }
-
-    /* Decrypt SRTP */
-    if (srtp) {
-	int len = sz;
-	T(pjmedia_transport_srtp_decrypt_pkt(srtp, PJ_TRUE, buf, &len));
-	sz = len;
-    }
-
-    *rtp = (pjmedia_rtp_hdr*)buf;
-    *payload = (pj_uint8_t*) (buf + sizeof(pjmedia_rtp_hdr));
-    *payload_size = sz - sizeof(pjmedia_rtp_hdr);
+    /* Init RTP session */
+    if (!app.rtp_sess_init) {
+	T(pjmedia_rtp_session_init(&app.rtp_sess, 0, 0));
+	app.rtp_sess_init = PJ_TRUE;
+    }
+
+    /* Loop reading until we have a good RTP packet */
+    for (;;) {
+	pj_size_t sz = bufsize;
+	const pjmedia_rtp_hdr *r;
+	const void *p;
+	pjmedia_rtp_status seq_st;
+
+	status = pj_pcap_read_udp(app.pcap, NULL, buf, &sz);
+	if (status != PJ_SUCCESS)
+	    err_exit("Error reading PCAP file", status);
+
+	/* Decode RTP packet to make sure that this is an RTP packet.
+	 * We will decode it again to get the payload after we do
+	 * SRTP decoding
+	 */
+	status = pjmedia_rtp_decode_rtp(&app.rtp_sess, buf, sz, &r, 
+					&p, payload_size);
+	if (status != PJ_SUCCESS) {
+	    char errmsg[PJ_ERR_MSG_SIZE];
+	    pj_strerror(status, errmsg, sizeof(errmsg));
+	    printf("Not RTP packet, skipping packet: %s\n", errmsg);
+	    continue;
+	}
+
+	/* Decrypt SRTP */
+	if (app.srtp) {
+	    int len = sz;
+	    status = pjmedia_transport_srtp_decrypt_pkt(app.srtp, PJ_TRUE, 
+						        buf, &len);
+	    if (status != PJ_SUCCESS) {
+		char errmsg[PJ_ERR_MSG_SIZE];
+		pj_strerror(status, errmsg, sizeof(errmsg));
+		printf("SRTP packet decryption failed, skipping packet: %s\n", 
+			errmsg);
+		continue;
+	    }
+	    sz = len;
+
+	    /* Decode RTP packet again */
+	    status = pjmedia_rtp_decode_rtp(&app.rtp_sess, buf, sz, &r,
+					    &p, payload_size);
+	    if (status != PJ_SUCCESS) {
+		char errmsg[PJ_ERR_MSG_SIZE];
+		pj_strerror(status, errmsg, sizeof(errmsg));
+		printf("Not RTP packet, skipping packet: %s\n", errmsg);
+		continue;
+	    }
+	}
+
+	/* Update RTP session */
+	pjmedia_rtp_session_update(&app.rtp_sess, r, &seq_st);
+
+	/* Skip out-of-order packet */
+	if (seq_st.diff == 0) {
+	    printf("Skipping out of order packet\n");
+	    continue;
+	}
+
+	/* Skip if payload type is different */
+	if (r->pt != app.pt) {
+	    printf("Skipping RTP packet with bad payload type\n");
+	    continue;
+	}
+
+	/* Skip bad packet */
+	if (seq_st.status.flag.bad) {
+	    printf("Skipping bad RTP\n");
+	    continue;
+	}
+
+
+	*rtp = (pjmedia_rtp_hdr*)r;
+	*payload = (pj_uint8_t*)p;
+
+	/* We have good packet */
+	break;
+    }
 }
 
@@ -132,7 +220,6 @@
     } pkt0;
     pjmedia_codec_mgr *cmgr;
-    pjmedia_codec_info *ci;
+    const pjmedia_codec_info *ci;
     pjmedia_codec_param param;
-    pjmedia_codec *codec;
     unsigned samples_per_frame;
     pj_status_t status;
@@ -140,21 +227,21 @@
     /* Initialize all codecs */
 #if PJMEDIA_HAS_SPEEX_CODEC
-    T( pjmedia_codec_speex_init(mept, 0, 10, 10) );
+    T( pjmedia_codec_speex_init(app.mept, 0, 10, 10) );
 #endif /* PJMEDIA_HAS_SPEEX_CODEC */
 
 #if PJMEDIA_HAS_ILBC_CODEC
-    T( pjmedia_codec_ilbc_init(mept, 30) );
+    T( pjmedia_codec_ilbc_init(app.mept, 30) );
 #endif /* PJMEDIA_HAS_ILBC_CODEC */
 
 #if PJMEDIA_HAS_GSM_CODEC
-    T( pjmedia_codec_gsm_init(mept) );
+    T( pjmedia_codec_gsm_init(app.mept) );
 #endif /* PJMEDIA_HAS_GSM_CODEC */
 
 #if PJMEDIA_HAS_G711_CODEC
-    T( pjmedia_codec_g711_init(mept) );
+    T( pjmedia_codec_g711_init(app.mept) );
 #endif	/* PJMEDIA_HAS_G711_CODEC */
 
 #if PJMEDIA_HAS_L16_CODEC
-    T( pjmedia_codec_l16_init(mept, 0) );
+    T( pjmedia_codec_l16_init(app.mept, 0) );
 #endif	/* PJMEDIA_HAS_L16_CODEC */
 
@@ -166,6 +253,6 @@
 	crypto.key = *srtp_key;
 	crypto.name = *srtp_crypto;
-	T( pjmedia_transport_srtp_create(mept, NULL, NULL, &srtp) );
-	T( pjmedia_transport_srtp_start(srtp, &crypto, &crypto) );
+	T( pjmedia_transport_srtp_create(app.mept, NULL, NULL, &app.srtp) );
+	T( pjmedia_transport_srtp_start(app.srtp, &crypto, &crypto) );
     }
 
@@ -174,22 +261,23 @@
 	     &pkt0.payload, &pkt0.payload_len);
 
-    cmgr = pjmedia_endpt_get_codec_mgr(mept);
+    cmgr = pjmedia_endpt_get_codec_mgr(app.mept);
 
     /* Get codec info and param for the specified payload type */
+    app.pt = pkt0.rtp->pt;
     T( pjmedia_codec_mgr_get_codec_info(cmgr, pkt0.rtp->pt, &ci) );
     T( pjmedia_codec_mgr_get_default_param(cmgr, ci, &param) );
 
     /* Alloc and init codec */
-    T( pjmedia_codec_mgr_alloc_codec(cmgr, ci, &codec) );
-    T( codec->op->init(codec, pool) );
-    T( codec->op->open(codec, &param) );
+    T( pjmedia_codec_mgr_alloc_codec(cmgr, ci, &app.codec) );
+    T( app.codec->op->init(app.codec, app.pool) );
+    T( app.codec->op->open(app.codec, &param) );
 
     /* Open WAV file */
     samples_per_frame = ci->clock_rate * param.info.frm_ptime / 1000;
-    T( pjmedia_wav_writer_port_create(pool, wav_filename,
+    T( pjmedia_wav_writer_port_create(app.pool, wav_filename,
 				      ci->clock_rate, ci->channel_cnt,
 				      samples_per_frame,
 				      param.info.pcm_bits_per_sample, 0, 0,
-				      &wav) );
+				      &app.wav) );
 
     /* Loop reading PCAP and writing WAV file */
@@ -207,6 +295,6 @@
 	ts.u64 = 0;
 	frame_cnt = PJ_ARRAY_SIZE(frames);
-	T( codec->op->parse(codec, pkt0.payload, pkt0.payload_len, &ts, 
-			    &frame_cnt, frames) );
+	T( app.codec->op->parse(app.codec, pkt0.payload, pkt0.payload_len, 
+				&ts, &frame_cnt, frames) );
 
 	/* Decode and write to WAV file */
@@ -218,6 +306,7 @@
 	    pcm_frame.size = samples_per_frame * 2;
 
-	    T( codec->op->decode(codec, &frames[i], pcm_frame.size, &pcm_frame) );
-	    T( pjmedia_port_put_frame(wav, &pcm_frame) );
+	    T( app.codec->op->decode(app.codec, &frames[i], pcm_frame.size, 
+				     &pcm_frame) );
+	    T( pjmedia_port_put_frame(app.wav, &pcm_frame) );
 	    samples_cnt += samples_per_frame;
 	}
@@ -235,11 +324,12 @@
 	    pcm_frame.size = samples_per_frame * 2;
 
-	    if (codec->op->recover) {
-		T( codec->op->recover(codec, pcm_frame.size, &pcm_frame) );
+	    if (app.codec->op->recover) {
+		T( app.codec->op->recover(app.codec, pcm_frame.size, 
+					  &pcm_frame) );
 	    } else {
 		pj_bzero(pcm_frame.buf, pcm_frame.size);
 	    }
 
-	    T( pjmedia_port_put_frame(wav, &pcm_frame) );
+	    T( pjmedia_port_put_frame(app.wav, &pcm_frame) );
 	    ts_gap -= samples_per_frame;
 	}
@@ -341,12 +431,12 @@
     T( pj_init() );
 
-    pj_caching_pool_init(&cp, NULL, 0);
-    pool = pj_pool_create(&cp.factory, "pcaputil", 1000, 1000, NULL);
+    pj_caching_pool_init(&app.cp, NULL, 0);
+    app.pool = pj_pool_create(&app.cp.factory, "pcaputil", 1000, 1000, NULL);
 
     T( pjlib_util_init() );
-    T( pjmedia_endpt_create(&cp.factory, NULL, 0, &mept) );
-
-    T( pj_pcap_open(pool, input.ptr, &pcap) );
-    T( pj_pcap_set_filter(pcap, &filter) );
+    T( pjmedia_endpt_create(&app.cp.factory, NULL, 0, &app.mept) );
+
+    T( pj_pcap_open(app.pool, input.ptr, &app.pcap) );
+    T( pj_pcap_set_filter(app.pcap, &filter) );
 
     if (pj_stristr(&output, &wav)) {
@@ -356,7 +446,7 @@
     }
 
-    pjmedia_endpt_destroy(mept);
-    pj_pool_release(pool);
-    pj_caching_pool_destroy(&cp);
+    pjmedia_endpt_destroy(app.mept);
+    pj_pool_release(app.pool);
+    pj_caching_pool_destroy(&app.cp);
     pj_shutdown();
     return 0;
