Index: /pjproject/trunk/pjmedia/src/pjmedia-videodev/colorbar_dev.c
===================================================================
--- /pjproject/trunk/pjmedia/src/pjmedia-videodev/colorbar_dev.c	(revision 5049)
+++ /pjproject/trunk/pjmedia/src/pjmedia-videodev/colorbar_dev.c	(revision 5050)
@@ -18,4 +18,5 @@
  */
 #include <pjmedia-videodev/videodev_imp.h>
+#include <pjmedia/clock.h>
 #include <pj/assert.h>
 #include <pj/log.h>
@@ -28,5 +29,4 @@
     PJMEDIA_VIDEO_DEV_HAS_CBAR_SRC != 0
     
-
 
 #define THIS_FILE		"colorbar_dev.c"
@@ -35,4 +35,5 @@
 #define DEFAULT_HEIGHT		288 //480
 #define DEFAULT_FPS		25
+
 
 /* cbar_ device info */
@@ -100,4 +101,8 @@
     pj_timestamp		     ts;
     unsigned			     ts_inc;
+
+    /* For active capturer only */
+    pjmedia_clock		    *clock;
+    pj_uint8_t			    *clock_buf;
 };
 
@@ -189,9 +194,11 @@
     unsigned i;
 
-    cf->dev_count = 1;
+    cf->dev_count = 2;
+
     cf->dev_info = (struct cbar_dev_info*)
  		   pj_pool_calloc(cf->pool, cf->dev_count,
  				  sizeof(struct cbar_dev_info));
 
+    /* Passive capturer */
     ddi = &cf->dev_info[0];
     pj_bzero(ddi, sizeof(*ddi));
@@ -203,4 +210,24 @@
     ddi->info.dir = PJMEDIA_DIR_CAPTURE;
     ddi->info.has_callback = PJ_FALSE;
+
+    ddi->info.caps = PJMEDIA_VID_DEV_CAP_FORMAT;
+    ddi->info.fmt_cnt = sizeof(cbar_fmts)/sizeof(cbar_fmts[0]);
+    for (i = 0; i < ddi->info.fmt_cnt; i++) {
+        pjmedia_format *fmt = &ddi->info.fmt[i];
+        pjmedia_format_init_video(fmt, cbar_fmts[i].fmt_id,
+				  DEFAULT_WIDTH, DEFAULT_HEIGHT,
+				  DEFAULT_FPS, 1);
+    }
+
+    /* Active capturer */
+    ddi = &cf->dev_info[1];
+    pj_bzero(ddi, sizeof(*ddi));
+    pj_ansi_strncpy(ddi->info.name, "Colorbar-active",
+		    sizeof(ddi->info.name));
+    ddi->info.driver[sizeof(ddi->info.driver)-1] = '\0';
+    pj_ansi_strncpy(ddi->info.driver, "Colorbar", sizeof(ddi->info.driver));
+    ddi->info.driver[sizeof(ddi->info.driver)-1] = '\0';
+    ddi->info.dir = PJMEDIA_DIR_CAPTURE;
+    ddi->info.has_callback = PJ_TRUE;
 
     ddi->info.caps = PJMEDIA_VID_DEV_CAP_FORMAT;
@@ -376,4 +403,23 @@
 }
 
+
+static void clock_cb(const pj_timestamp *ts, void *user_data)
+{
+    struct cbar_stream *stream = (struct cbar_stream*)user_data;
+    pjmedia_frame f;
+    pj_status_t status;
+
+    PJ_UNUSED_ARG(ts);
+
+    pj_bzero(&f, sizeof(f));
+    f.buf = stream->clock_buf;
+    f.size = stream->vafp.framebytes;
+    status = cbar_stream_get_frame(&stream->base, &f);
+    if (status == PJ_SUCCESS) {
+	(*stream->vid_cb.capture_cb)(&stream->base, stream->user_data, &f);
+    }
+}
+
+
 /* API: create stream */
 static pj_status_t cbar_factory_create_stream(
@@ -439,4 +485,27 @@
     }
 */
+
+    /* Active role? */
+    if (param->cap_id == 1 && cb && cb->capture_cb) {
+        pjmedia_clock_param clock_param;
+	pj_status_t status;
+
+	/* Allocate buffer */
+	strm->clock_buf = pj_pool_alloc(pool, strm->vafp.framebytes);
+
+	/* Create clock */
+	pj_bzero(&clock_param, sizeof(clock_param));
+        clock_param.usec_interval = PJMEDIA_PTIME(&vfd->fps);
+        clock_param.clock_rate = param->clock_rate;
+        status = pjmedia_clock_create2(pool, &clock_param,
+                                       PJMEDIA_CLOCK_NO_HIGHEST_PRIO,
+                                       &clock_cb,
+                                       strm, &strm->clock);
+	if (status != PJ_SUCCESS) {
+	    pj_pool_release(pool);
+            return status;
+	}
+    }
+
     /* Done */
     strm->base.op = &stream_op;
@@ -597,7 +666,8 @@
     struct cbar_stream *stream = (struct cbar_stream*)strm;
 
-    PJ_UNUSED_ARG(stream);
-
     PJ_LOG(4, (THIS_FILE, "Starting cbar video stream"));
+
+    if (stream->clock)
+	return pjmedia_clock_start(stream->clock);
 
     return PJ_SUCCESS;
@@ -609,7 +679,8 @@
     struct cbar_stream *stream = (struct cbar_stream*)strm;
 
-    PJ_UNUSED_ARG(stream);
-
     PJ_LOG(4, (THIS_FILE, "Stopping cbar video stream"));
+
+    if (stream->clock)
+	return pjmedia_clock_stop(stream->clock);
 
     return PJ_SUCCESS;
@@ -626,4 +697,8 @@
     cbar_stream_stop(strm);
 
+    if (stream->clock)
+	pjmedia_clock_destroy(stream->clock);
+    stream->clock = NULL;
+
     pj_pool_release(stream->pool);
 
