diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/Meeting.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/Meeting.java
index 9a932c938b3d6ba9fcb029610b6d147bb0fad2a9..45e568d758468f393997ff6f685d44a16984b18b 100755
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/Meeting.java
+++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/Meeting.java
@@ -2,8 +2,12 @@ package org.bigbluebutton.app.screenshare;
 
 import java.util.HashMap;
 import java.util.Map;
+import org.red5.logging.Red5LoggerFactory;
+import org.slf4j.Logger;
 
 public class Meeting {
+    private static Logger log = Red5LoggerFactory.getLogger(Meeting.class, "screenshare");
+
     public final String id;
 
     private Map<String, VideoStream> videoStreams = new HashMap<String, VideoStream>();
@@ -13,17 +17,21 @@ public class Meeting {
     }
 
     public synchronized void addStream(VideoStream stream) {
-        videoStreams.put(stream.getStreamId(), stream);
+			log.debug("Adding VideoStream {} to meeting {}", stream.getStreamId(), id);
+			videoStreams.put(stream.getStreamId(), stream);
     }
 
     public synchronized void removeStream(String streamId) {
-        VideoStream vs = videoStreams.remove(streamId);
+			log.debug("Removing VideoStream {} to meeting {}", streamId, id);
+			VideoStream vs = videoStreams.remove(streamId);
     }
 
     public synchronized void streamBroadcastClose(String streamId) {
-        VideoStream vs = videoStreams.remove(streamId);
+			log.debug("streamBroadcastClose VideoStream {} to meeting {}", streamId, id);
+			VideoStream vs = videoStreams.remove(streamId);
         if (vs != null) {
-            vs.streamBroadcastClose();
+					log.debug("Closing VideoStream {} to meeting {}", streamId, id);
+					vs.streamBroadcastClose();
         }
     }
 
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/MeetingManager.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/MeetingManager.java
index 76861013ed9c7767457fc484986129263e08ce49..2698ad89d8f65d4d4ea3f22795519a761703a6ab 100755
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/MeetingManager.java
+++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/MeetingManager.java
@@ -2,8 +2,11 @@ package org.bigbluebutton.app.screenshare;
 
 import java.util.HashMap;
 import java.util.Map;
+import org.red5.logging.Red5LoggerFactory;
+import org.slf4j.Logger;
 
 public class MeetingManager {
+    private static Logger log = Red5LoggerFactory.getLogger(MeetingManager.class, "screenshare");
 
     private Map<String, Meeting> meetings = new HashMap<String, Meeting>();
 
@@ -16,6 +19,8 @@ public class MeetingManager {
     }
 
     public void addStream(String meetingId, VideoStream vs) {
+        log.debug("Adding VideoStream {} to meeting {}", vs.getStreamId(), meetingId);
+
         Meeting m = meetings.get(meetingId);
         if (m != null) {
             m.addStream(vs);
@@ -27,16 +32,22 @@ public class MeetingManager {
     }
 
     public void removeStream(String meetingId, String streamId) {
+			log.debug("Removing VideoStream {} to meeting {}", streamId, meetingId);
         Meeting m = meetings.get(meetingId);
         if (m != null) {
+					log.debug("Removed VideoStream {} to meeting {}", streamId, meetingId);
             m.removeStream(streamId);
         }
     }
 
     public void streamBroadcastClose(String meetingId, String streamId) {
-        Meeting m = meetings.get(meetingId);
+			log.debug("streamBroadcastClose VideoStream {} to meeting {}", streamId, meetingId);
+
+			Meeting m = meetings.get(meetingId);
         if (m != null) {
-            m.streamBroadcastClose(streamId);
+					log.debug("streamBroadcastClose 2 VideoStream {} to meeting {}", streamId, meetingId);
+
+					m.streamBroadcastClose(streamId);
             if (!m.hasVideoStreams()) {
                 remove(m.id);
             }
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/VideoStream.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/VideoStream.java
index 0ff5b30d93b538347494354f922b100d841a16cf..3a3239b2cf3920fe318d9309d981b13b1e9946a9 100755
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/VideoStream.java
+++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/VideoStream.java
@@ -7,6 +7,9 @@ import org.red5.server.api.scope.IScope;
 import org.red5.server.api.stream.IBroadcastStream;
 import org.red5.server.stream.ClientBroadcastStream;
 import org.slf4j.Logger;
+import java.util.HashMap;
+import java.util.Map;
+import com.google.gson.Gson;
 
 public class VideoStream {
     private static Logger log = Red5LoggerFactory.getLogger(VideoStream.class, "screenshare");
@@ -26,7 +29,7 @@ public class VideoStream {
     }
 
     public String getStreamId() {
-        return streamId;
+        return stream.getPublishedName();
     }
 
     public synchronized void startRecording() {
@@ -36,19 +39,38 @@ public class VideoStream {
             log.info("Recording stream " + recordingStreamName);
             videoStreamListener.setStreamId(recordingStreamName);
             cstream.saveAs(recordingStreamName, false);
+
+						Map<String, Object> logData2 = new HashMap<String, Object>();
+						logData2.put("broadcastStream", stream.getPublishedName());
+						logData2.put("recordStreamId", recordingStreamName);
+						logData2.put("recording", cstream.isRecording());
+						logData2.put("event", "start_recording_stream");
+						logData2.put("description", "Start recording stream.");
+
+						Gson gson2 = new Gson();
+						String logStr2 =  gson2.toJson(logData2);
+						log.info(logStr2);
         } catch (Exception e) {
             log.error("ERROR while recording stream " + e.getMessage());
             e.printStackTrace();
         }
     }
 
-    public synchronized void stopRecording() {
-        if (cstream.isRecording()) {
-            cstream.stopRecording();
-            videoStreamListener.stopRecording();
-            videoStreamListener.reset();
-        }
-    }
+		public synchronized void stopRecording() {
+			log.debug("STOP RECORDING STREAM {} recording {}", stream.getPublishedName(), cstream.isRecording());
+			Map<String, Object> logData2 = new HashMap<String, Object>();
+			logData2.put("broadcastStream", stream.getPublishedName());
+			logData2.put("recordStreamId", recordingStreamName);
+			logData2.put("event", "stop_recording_stream");
+			logData2.put("description", "Stop recording stream.");
+			Gson gson2 = new Gson();
+			String logStr2 =  gson2.toJson(logData2);
+			log.info(logStr2);
+			cstream.stopRecording();
+			videoStreamListener.stopRecording();
+			videoStreamListener.reset();
+
+		}
 
     public synchronized void stopStartRecording() {
         stopRecording();
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/VideoStreamListener.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/VideoStreamListener.java
index 49d461c4241d1ac2d81e47c2bd978c3ebe2f4ea2..41468e7ed845331d4706df0ab30a711a6d70f35a 100755
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/VideoStreamListener.java
+++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/VideoStreamListener.java
@@ -34,6 +34,7 @@ import org.slf4j.Logger;
 import org.red5.logging.Red5LoggerFactory;
 
 import com.google.gson.Gson;
+import java.text.SimpleDateFormat;
 
 /**
  * Class to listen for the first video packet of the webcam.
@@ -51,7 +52,7 @@ import com.google.gson.Gson;
  *
  */
 public class VideoStreamListener implements IStreamListener {
-  private static final Logger log = Red5LoggerFactory.getLogger(VideoStreamListener.class, "video");
+  private static final Logger log = Red5LoggerFactory.getLogger(VideoStreamListener.class, "screenshare");
 
   private EventRecordingService recordingService;
   private volatile boolean firstPacketReceived = false;
@@ -60,6 +61,7 @@ public class VideoStreamListener implements IStreamListener {
   private int videoTimeout = 10000;
   private long firstPacketTime = 0L;
   private long packetCount = 0L;
+  private int keyFrameCount = 0;
 
   // Last time video was received, not video timestamp
   private long lastVideoTime;
@@ -81,12 +83,16 @@ public class VideoStreamListener implements IStreamListener {
   private volatile boolean publishing = false;
 
   private volatile boolean streamPaused = false;
+  private volatile boolean streamStarted = false;
 
   private String meetingId;
 
   private long recordingStartTime;
   private String filename;
 
+  private final String DATE = "date";
+  private final String TIMESTAMP_UTC = "timestampUTC";
+
   public VideoStreamListener(String meetingId, String streamId, Boolean record,
                              String recordingDir, int packetTimeout,
                              QuartzSchedulingService scheduler,
@@ -98,6 +104,9 @@ public class VideoStreamListener implements IStreamListener {
     this.recordingDir = recordingDir;
     this.scheduler = scheduler;
     this.recordingService = recordingService;
+
+    // start the worker to monitor if we are still receiving video packets
+    timeoutJobName = scheduler.addScheduledJob(videoTimeout, new TimeoutJob());
   }
 
   private Long genTimestamp() {
@@ -106,81 +115,112 @@ public class VideoStreamListener implements IStreamListener {
 
   public void reset() {
     firstPacketReceived = false;
+    keyFrameCount = 0;
   }
 
   public void setStreamId(String streamId) {
     this.streamId = streamId;
   }
 
-  @Override
-  public void packetReceived(IBroadcastStream stream, IStreamPacket packet) {
-    IoBuffer buf = packet.getData();
-    if (buf != null)
-      buf.rewind();
-
-    if (buf == null || buf.remaining() == 0) {
-      return;
-    }
-
-    if (packet instanceof VideoData) {
-      // keep track of last time video was received
-      lastVideoTime = System.currentTimeMillis();
-      packetCount++;
-
-      if (!firstPacketReceived) {
-        firstPacketReceived = true;
-        publishing = true;
-        firstPacketTime = lastVideoTime;
-
-        // start the worker to monitor if we are still receiving video packets
-        timeoutJobName = scheduler.addScheduledJob(videoTimeout, new TimeoutJob());
-
-        if (record) {
-          recordingStartTime = System.currentTimeMillis();
-          filename = recordingDir;
-          if (!filename.endsWith("/")) {
-            filename.concat("/");
-          }
-
-          filename = filename.concat(meetingId).concat("/").concat(streamId).concat(".flv");
-          recordingStartTime = System.currentTimeMillis();
-          Map<String, String> event = new HashMap<String, String>();
-          event.put("module", "Deskshare");
-          event.put("timestamp", genTimestamp().toString());
-          event.put("meetingId", meetingId);
-          event.put("file", filename);
-          event.put("stream", streamId);
-          event.put("eventName", "DeskshareStartedEvent");
-
-          recordingService.record(meetingId, event);
-        }
-      }
-
-
-      if (streamPaused) {
-        streamPaused = false;
-        long now = System.currentTimeMillis();
-        long numSeconds = (now - lastVideoTime) / 1000;
+	@Override
+	public void packetReceived(IBroadcastStream stream, IStreamPacket packet) {
+		IoBuffer buf = packet.getData();
+		if (buf != null)
+			buf.rewind();
+
+		if (buf == null || buf.remaining() == 0) {
+			return;
+		}
+
+		if (packet instanceof VideoData) {
+			// keep track of last time video was received
+			lastVideoTime = System.currentTimeMillis();
+			packetCount++;
+
+			VideoData vidPkt = (VideoData) packet;
+
+			if (!firstPacketReceived && vidPkt.getFrameType() == VideoData.FrameType.KEYFRAME) {
+				log.info("******* Receiving first screenshare KEYFRAME packet");
+				firstPacketReceived = true;
+				publishing = true;
+				firstPacketTime = lastVideoTime;
+				streamStarted = true;
+
+				if (record) {
+					recordingStartTime = System.currentTimeMillis();
+					filename = recordingDir;
+					if (!filename.endsWith("/")) {
+						filename.concat("/");
+					}
+
+					filename = filename.concat(meetingId).concat("/").concat(streamId).concat(".flv");
+					recordingStartTime = System.currentTimeMillis();
+					Map<String, String> event = new HashMap<String, String>();
+					event.put("module", "Deskshare");
+					event.put("timestamp", genTimestamp().toString());
+					event.put("meetingId", meetingId);
+					event.put("file", filename);
+					event.put("stream", streamId);
+					event.put(TIMESTAMP_UTC, Long.toString(recordingStartTime));
+					SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
+					event.put(DATE, sdf.format(recordingStartTime));
+					event.put("eventName", "DeskshareStartedEvent");
+
+					recordingService.record(meetingId, event);
+
+
+					Gson gson = new Gson();
+					String logStr = gson.toJson(event);
+					log.info("StartScreenShareEvent data={} timeoutJobName={}", logStr, timeoutJobName);
+				}
+			}
+
+
+			if (streamPaused) {
+				streamPaused = false;
+				long now = System.currentTimeMillis();
+				long numSeconds = (now - lastVideoTime) / 1000;
+
+				Map<String, Object> logData = new HashMap<String, Object>();
+				logData.put("meetingId", meetingId);
+				logData.put("stream", streamId);
+				logData.put("packetCount", packetCount);
+				logData.put("publishing", publishing);
+				logData.put("pausedFor (sec)", numSeconds);
+
+				Gson gson = new Gson();
+				String logStr = gson.toJson(logData);
+
+				log.warn("Screenshare stream restarted. data={}", logStr);
+			}
+
+			if (vidPkt.getFrameType() == VideoData.FrameType.KEYFRAME && keyFrameCount < 3) {
+				// Log first 3 keyframe packets to allow us to see interval between key frames. Helps
+				// to debug if there are any synch issues with recording playback. (ralam feb 12, 2018)
+				keyFrameCount++;
+				long now = System.currentTimeMillis();
+				Map<String, Object> logData = new HashMap<String, Object>();
+				logData.put("meetingId", meetingId);
+				logData.put("stream", stream.getPublishedName());
+				logData.put("packetCount", packetCount);
+				logData.put("keyFrameCount", keyFrameCount);
+				logData.put("publishing", publishing);
+				logData.put(TIMESTAMP_UTC, Long.toString(now));
+				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
+				logData.put(DATE, sdf.format(now));
+
+				Gson gson = new Gson();
+				String logStr = gson.toJson(logData);
+				log.warn("Video stream keyframe. data={}", logStr);
+			}
+		}
+	}
 
-        Map<String, Object> logData = new HashMap<String, Object>();
-        logData.put("meetingId", meetingId);
-        logData.put("stream", streamId);
-        logData.put("packetCount", packetCount);
-        logData.put("publishing", publishing);
-        logData.put("pausedFor (sec)", numSeconds);
-
-        Gson gson = new Gson();
-        String logStr = gson.toJson(logData);
-
-        log.warn("Screenshare stream restarted. data={}", logStr);
-      }
-
-    }
-  }
 
   public void stopRecording() {
     if (record) {
-      long publishDuration = (System.currentTimeMillis() - recordingStartTime) / 1000;
+			long now = System.currentTimeMillis();
+      long publishDuration = (now - recordingStartTime) / 1000;
 
       Map<String, String> event = new HashMap<String, String>();
       event.put("module", "Deskshare");
@@ -189,13 +229,34 @@ public class VideoStreamListener implements IStreamListener {
       event.put("stream", streamId);
       event.put("file", filename);
       event.put("duration", new Long(publishDuration).toString());
-      event.put("eventName", "DeskshareStoppedEvent");
+			event.put(TIMESTAMP_UTC, Long.toString(now));
+			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
+			event.put(DATE, sdf.format(now));
+			event.put("eventName", "DeskshareStoppedEvent");
       recordingService.record(meetingId, event);
+
+			Gson gson = new Gson();
+			String logStr = gson.toJson(event);
+			log.info("StopScreenShareEvent data={}", logStr);
     }
   }
 
-  public void streamStopped() {
-    this.publishing = false;
+	public void streamStopped() {
+		this.publishing = false;
+		if (!streamStarted) {
+			Map<String, Object> logData = new HashMap<String, Object>();
+			logData.put("meetingId", meetingId);
+			logData.put("stream", streamId);
+			logData.put("packetCount", packetCount);
+			logData.put("publishing", publishing);
+			logData.put("timeoutJobName", timeoutJobName);
+
+			Gson gson = new Gson();
+			String logStr = gson.toJson(logData);
+			log.warn("Removing scheduled job.as stream hasn't started. data={}", logStr);
+			// remove the scheduled job
+				scheduler.removeScheduledJob(timeoutJobName);
+		}
   }
 
   private class TimeoutJob implements IScheduledJob {
@@ -207,11 +268,12 @@ public class VideoStreamListener implements IStreamListener {
       logData.put("stream", streamId);
       logData.put("packetCount", packetCount);
       logData.put("publishing", publishing);
+			logData.put("timeoutJobName", timeoutJobName);
 
       Gson gson = new Gson();
 
       long now = System.currentTimeMillis();
-      if ((now - lastVideoTime) > videoTimeout && !streamPaused) {
+      if ((now - lastVideoTime) > videoTimeout && !streamPaused && streamStarted) {
         streamPaused = true;
         long numSeconds = (now - lastVideoTime) / 1000;
 
@@ -224,7 +286,7 @@ public class VideoStreamListener implements IStreamListener {
       }
 
       String logStr = gson.toJson(logData);
-      if (!publishing) {
+      if (!publishing && streamStarted) {
         log.warn("Removing scheduled job. data={}", logStr);
         // remove the scheduled job
         scheduler.removeScheduledJob(timeoutJobName);
diff --git a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/Red5AppAdapter.java b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/Red5AppAdapter.java
index b55fb42fc524eb3709a417edf6b74ec83b1c747e..67df6a499085eb8fd0527a18bf64d2c679fb528a 100755
--- a/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/Red5AppAdapter.java
+++ b/bbb-screenshare/app/src/main/java/org/bigbluebutton/app/screenshare/red5/Red5AppAdapter.java
@@ -151,8 +151,24 @@ public class Red5AppAdapter extends MultiThreadedApplicationAdapter {
 
     String connId = conn.getSessionId();
     String scopeName = stream.getScope().getName();
+    String connType = getConnectionType(Red5.getConnectionLocal().getType());
 
     String streamId = stream.getPublishedName();
+
+		Map<String, Object> logData = new HashMap<String, Object>();
+		logData.put("meetingId", getMeetingId());
+		logData.put("userId", getUserId());
+		logData.put("connType", connType);
+		logData.put("connId", connId);
+		logData.put("stream", stream.getPublishedName());
+		logData.put("context", scopeName);
+		logData.put("event", "stream_broadcast_start");
+		logData.put("description", "Stream broadcast start.");
+
+		Gson gson = new Gson();
+		String logStr =  gson.toJson(logData);
+		log.info(logStr);
+
     Matcher matcher = STREAM_ID_PATTERN.matcher(stream.getPublishedName());
     if (matcher.matches()) {
         String meetingId = matcher.group(1).trim();
@@ -162,25 +178,33 @@ public class Red5AppAdapter extends MultiThreadedApplicationAdapter {
       app.authorizeBroadcastStream(meetingId, streamId, connId, scopeName);
 
 	    boolean recordVideoStream = app.recordStream(meetingId, streamId);
-          VideoStreamListener listener = new VideoStreamListener(meetingId, streamId,
-                  recordVideoStream, recordingDirectory, packetTimeout, scheduler, recordingService);
-          ClientBroadcastStream cstream = (ClientBroadcastStream) this.getBroadcastStream(conn.getScope(), stream.getPublishedName());
-          stream.addStreamListener(listener);
-          VideoStream vstream = new VideoStream(stream, listener, cstream);
-          vstream.startRecording();
-
-          meetingManager.addStream(meetingId, vstream);
+	    if (recordVideoStream) {
+				Map<String, Object> logData2 = new HashMap<String, Object>();
+				logData2.put("meetingId", meetingId);
+				logData2.put("connType", connType);
+				logData2.put("connId", connId);
+				logData.put("streamId", streamId);
+				logData.put("url", url);
+				logData.put("recorded", recordVideoStream);
+				logData2.put("context", scopeName);
+				logData2.put("event", "stream_broadcast_record_start");
+				logData2.put("description", "Stream broadcast record start.");
+
+				Gson gson2 = new Gson();
+				String logStr2 =  gson2.toJson(logData2);
+				log.info(logStr2);
+
+				VideoStreamListener listener = new VideoStreamListener(meetingId, streamId,
+								recordVideoStream, recordingDirectory, packetTimeout, scheduler, recordingService);
+				ClientBroadcastStream cstream = (ClientBroadcastStream) this.getBroadcastStream(conn.getScope(), stream.getPublishedName());
+				stream.addStreamListener(listener);
+				VideoStream vstream = new VideoStream(stream, listener, cstream);
+				vstream.startRecording();
+
+				meetingManager.addStream(meetingId, vstream);
+
+			}
 
-      Map<String, Object> logData = new HashMap<String, Object>();
-      logData.put("meetingId", meetingId);
-      logData.put("streamId", streamId);
-      logData.put("url", url);
-      logData.put("recorded", recordVideoStream);
-
-      Gson gson = new Gson();
-      String logStr =  gson.toJson(logData);
-
-      log.info("ScreenShare broadcast started: data={}", logStr);
     } else {
     	log.error("Invalid streamid format [{}]", streamId);
     	conn.close();
@@ -195,8 +219,11 @@ public class Red5AppAdapter extends MultiThreadedApplicationAdapter {
   public void streamBroadcastClose(IBroadcastStream stream) {
     super.streamBroadcastClose(stream);
 
-    log.info("streamBroadcastStop " + stream.getPublishedName() + "]");
-    String streamId = stream.getPublishedName();
+		String connType = getConnectionType(Red5.getConnectionLocal().getType());
+		String connId = Red5.getConnectionLocal().getSessionId();
+		String scopeName = stream.getScope().getName();
+
+		String streamId = stream.getPublishedName();
     Matcher matcher = STREAM_ID_PATTERN.matcher(stream.getPublishedName());
     if (matcher.matches()) {
       String meetingId = matcher.group(1).trim();
@@ -206,15 +233,18 @@ public class Red5AppAdapter extends MultiThreadedApplicationAdapter {
       meetingManager.streamBroadcastClose(meetingId, streamId);
 
 
-      Map<String, Object> logData = new HashMap<String, Object>();
-      logData.put("meetingId", meetingId);
-      logData.put("streamId", streamId);
-      logData.put("recorded", recordVideoStream);
-
-      Gson gson = new Gson();
-      String logStr =  gson.toJson(logData);
+			Map<String, Object> logData2 = new HashMap<String, Object>();
+			logData2.put("meetingId", meetingId);
+			logData2.put("connType", connType);
+			logData2.put("connId", connId);
+			logData2.put("stream", stream.getPublishedName());
+			logData2.put("context", scopeName);
+			logData2.put("event", "stream_broadcast_close");
+			logData2.put("description", "Stream broadcast close.");
 
-      log.info("ScreenShare broadcast stopped: data={}", logStr);
+			Gson gson2 = new Gson();
+			String logStr2 =  gson2.toJson(logData2);
+			log.info(logStr2);
     } else {
     	log.error("Invalid streamid format [{}]", streamId);
     }