diff --git a/ring-android/app/src/main/java/cx/ring/services/CameraService.java b/ring-android/app/src/main/java/cx/ring/services/CameraService.java
index b6bce98b6766e2be5a045bcbd9203c0108ce4325..0518d0cf35a7ae1fe1278a3a99b99badda59a28e 100644
--- a/ring-android/app/src/main/java/cx/ring/services/CameraService.java
+++ b/ring-android/app/src/main/java/cx/ring/services/CameraService.java
@@ -58,6 +58,7 @@ import androidx.annotation.RequiresApi;
 import androidx.core.util.Pair;
 
 import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -95,6 +96,9 @@ public class CameraService {
     private MediaProjection currentMediaProjection;
     private VirtualDisplay virtualDisplay;
     private MediaCodec currentCodec;
+    // SPS and PPS NALs (Config Data).
+    private ByteBuffer codecData = null;
+
     private final CameraManager.AvailabilityCallback availabilityCallback = new CameraManager.AvailabilityCallback() {
         @Override
         public void onCameraAvailable(@NonNull String cameraId) {
@@ -455,7 +459,7 @@ public class CameraService {
         }
     }
 
-    public static Pair<MediaCodec, Surface> openEncoder(VideoParams videoParams, String mimeType, Handler handler, int resolution, int bitrate) {
+    public Pair<MediaCodec, Surface> openEncoder(VideoParams videoParams, String mimeType, Handler handler, int resolution, int bitrate) {
         Log.d(TAG, "Video with codec " + mimeType + " resolution: " + videoParams.width + "x" + videoParams.height + " Bitrate: " + bitrate);
         int bitrateValue;
         if(bitrate == 0)
@@ -506,9 +510,36 @@ public class CameraService {
                     public void onOutputBufferAvailable(@NonNull MediaCodec codec, int index, @NonNull MediaCodec.BufferInfo info) {
                         try {
                             if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) == 0) {
-                                ByteBuffer buffer = codec.getOutputBuffer(index);
-                                RingserviceJNI.captureVideoPacket(buffer, info.size, info.offset, (info.flags & MediaCodec.BUFFER_FLAG_KEY_FRAME) != 0, info.presentationTimeUs, videoParams.rotation);
-                                codec.releaseOutputBuffer(index, false);
+                                // Get and cache the codec data (SPS/PPS NALs)
+                                boolean isConfigFrame = (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0;
+                                if (isConfigFrame) {
+                                    ByteBuffer outputBuffer = codec.getOutputBuffer(index);
+                                    outputBuffer.position(info.offset);
+                                    outputBuffer.limit(info.offset + info.size);
+                                    codecData = ByteBuffer.allocateDirect(info.size);
+                                    codecData.put(outputBuffer);
+                                    codecData.rewind();
+                                    StringBuilder cd = new StringBuilder();
+                                    for (int i = 0; i < info.size; i++) {
+                                       cd.append(Integer.toHexString(codecData.get(i) & 0xff));
+                                    }
+                                    Log.i(TAG, "Cache new codec data (SPS/PPS, ...): " + cd.toString());
+                                    // Release the buffer.
+                                    codec.releaseOutputBuffer(index, false);
+                                }
+                                else {
+                                    boolean isKeyFrame = (info.flags & MediaCodec.BUFFER_FLAG_KEY_FRAME) != 0;
+                                    // If it's a key-frame, send the cached SPS/PPS NALs prior to
+                                    // sending key-frame.
+                                    if (isKeyFrame && codecData != null) {
+                                        RingserviceJNI.captureVideoPacket(codecData, codecData.capacity(), 0, false, info.presentationTimeUs, videoParams.rotation);
+                                    }
+
+                                    // Send the encoded frame
+                                    ByteBuffer buffer = codec.getOutputBuffer(index);
+                                    RingserviceJNI.captureVideoPacket(buffer, info.size, info.offset, isKeyFrame, info.presentationTimeUs, videoParams.rotation);
+                                    codec.releaseOutputBuffer(index, false);
+                                }
                             }
                         } catch (IllegalStateException e) {
                             Log.e(TAG, "MediaCodec can't process buffer", e);
@@ -646,7 +677,7 @@ public class CameraService {
         Pair<MediaCodec, Surface> r = null;
         while (screenWidth >= 320) {
             CameraService.VideoParams params = new CameraService.VideoParams(null, 0, screenWidth, screenHeight, 24);
-            r = CameraService.openEncoder(params, MediaFormat.MIMETYPE_VIDEO_AVC, handler, 720, 0);
+            r = openEncoder(params, MediaFormat.MIMETYPE_VIDEO_AVC, handler, 720, 0);
             if (r.first == null) {
                 screenWidth /= 2;
                 screenHeight /= 2;