diff --git a/libavcodec/jpegls.c b/libavcodec/jpegls.c
index 7f9fa8d..2b4f601 100644
--- a/libavcodec/jpegls.c
+++ b/libavcodec/jpegls.c
@@ -45,7 +45,12 @@ void ff_jpegls_init_state(JLSState *state)
     for (i = 0; i < 367; i++) {
         state->A[i] = FFMAX(state->range + 32 >> 6, 2);
         state->N[i] = 1;
+        state->B[i] =
+        state->C[i] = 0;
     }
+    for (i = 0; i < 4; i++) {
+        state->run_index[i] = 0;
+   }
 }
 
 /**
diff --git a/libavcodec/jpegls.h b/libavcodec/jpegls.h
index aac67bb..e9ca664 100644
--- a/libavcodec/jpegls.h
+++ b/libavcodec/jpegls.h
@@ -36,7 +36,7 @@
 
 typedef struct JLSState {
     int T1, T2, T3;
-    int A[367], B[367], C[365], N[367];
+    int A[367], B[367], C[367], N[367];
     int limit, reset, bpp, qbpp, maxval, range;
     int near, twonear;
     int run_index[4];
diff --git a/libavcodec/jpeglsdec.c b/libavcodec/jpeglsdec.c
index 69980ea..6d4b53e 100644
--- a/libavcodec/jpeglsdec.c
+++ b/libavcodec/jpeglsdec.c
@@ -25,6 +25,7 @@
  * JPEG-LS decoder.
  */
 
+#include "libavutil/opt.h"
 #include "avcodec.h"
 #include "get_bits.h"
 #include "golomb.h"
@@ -220,6 +221,33 @@ static inline int ls_get_code_runterm(GetBitContext
*gb, JLSState *state,
 }
 
 /**
+ * Skip bitstream for the next restart marker
+ */
+static int exp_mk = 0;
+static inline int ls_decode_skip_restart_marker(MJpegDecodeContext *s, int
init)
+{
+    int mk = 0, t = 0;
+
+    if (init) exp_mk = 0;
+
+    while (mk != 0xff && t++ < 16) { /* skip 0xFF */
+        mk = (mk<<1) + get_bits1(&s->gb);
+    }
+    mk  &= 0xff;
+    mk <<= 8;
+    mk  += get_bits(&s->gb, 8); /* skip RSTn */
+
+    if (mk != 0xffd0 + (exp_mk % 8)) {
+        av_log(s->avctx, AV_LOG_WARNING, "ERROR: Invalid restart marker
0x%.4X, expected is 0x%.4X\n", mk, 0xffd0 + (exp_mk % 8));
+        return -1;
+    }
+
+    exp_mk++;
+
+    return mk;
+}
+
+/**
  * Decode one line of image
  */
 static inline int ls_decode_line(JLSState *state, MJpegDecodeContext *s,
@@ -348,17 +376,18 @@ static inline int ls_decode_line(JLSState *state,
MJpegDecodeContext *s,
 int ff_jpegls_decode_picture(MJpegDecodeContext *s, int near,
                              int point_transform, int ilv)
 {
-    int i, t = 0;
-    uint8_t *zero, *last, *cur;
+    int i, m, cmp = 0;
+    int Rc[3] = { 0, 0, 0 };
+    int x, w, is_last_cmp;
+
+    uint8_t *zero, *last[3], *cur[3];
     JLSState *state;
-    int off = 0, stride = 1, width, shift, ret = 0;
+    int shift, ret = 0;
     int decoded_height = 0;
 
     zero = av_mallocz(s->picture_ptr->linesize[0]);
     if (!zero)
         return AVERROR(ENOMEM);
-    last = zero;
-    cur  = s->picture_ptr->data[0];
 
     state = av_mallocz(sizeof(JLSState));
     if (!state) {
@@ -376,12 +405,9 @@ int ff_jpegls_decode_picture(MJpegDecodeContext *s, int
near,
     ff_jpegls_reset_coding_parameters(state, 0);
     ff_jpegls_init_state(state);
 
-    if (s->bits <= 8)
-        shift = point_transform + (8 - s->bits);
-    else
-        shift = point_transform + (16 - s->bits);
+    shift = point_transform;
 
-    if (shift >= 16) {
+    if (shift > s->bits) {
         ret = AVERROR_INVALIDDATA;
         goto end;
     }
@@ -400,59 +426,106 @@ int ff_jpegls_decode_picture(MJpegDecodeContext *s,
int near,
         ret = AVERROR_INVALIDDATA;
         goto end;
     }
+
+    s->restart_count = s->restart_interval;
+
     if (ilv == 0) { /* separate planes */
+        int init_RSTn = 1;
         if (s->cur_scan > s->nb_components) {
             ret = AVERROR_INVALIDDATA;
             goto end;
         }
-        stride = (s->nb_components > 1) ? 3 : 1;
-        off    = av_clip(s->cur_scan - 1, 0, stride - 1);
-        width  = s->width * stride;
-        cur   += off;
+        cmp       = av_clip(s->cur_scan - 1, 0, s->nb_components - 1);
+        cur[cmp]  = s->picture_ptr->data[cmp];
+        last[cmp] = zero;
         for (i = 0; i < s->height; i++) {
-            int ret;
-            if (s->bits <= 8) {
-                ret = ls_decode_line(state, s, last, cur, t, width, stride,
off, 8);
-                t = last[0];
-            } else {
-                ret = ls_decode_line(state, s, last, cur, t, width, stride,
off, 16);
-                t = *((uint16_t *)last);
-            }
+            ret     = ls_decode_line(state, s, last[cmp], cur[cmp],
Rc[cmp], s->width, 1, cmp, s->bits);
+            Rc[cmp] = (s->bits <= 8 ? last[cmp][0] : ((uint16_t
*)(last[cmp]))[0]);
             if (ret < 0)
                 break;
-            last = cur;
-            cur += s->picture_ptr->linesize[0];
+            last[cmp] = cur[cmp];
+            cur[cmp] += s->picture_ptr->linesize[cmp];
 
-            if (s->restart_interval && !--s->restart_count) {
-                align_get_bits(&s->gb);
-                skip_bits(&s->gb, 16); /* skip RSTn */
+            if (s->restart_interval && !--s->restart_count && i !=
s->height - 1) {
+                ret = ls_decode_skip_restart_marker(s, init_RSTn);
+                if (ret < 0)
+                    break;
+
+                /* Reset decoder, skip RSTn */
+                s->restart_count = s->restart_interval;
+                ff_jpegls_init_state(state);
+                init_RSTn = 0;
+                last[cmp] = zero;
+                Rc[cmp]   = 0;
             }
         }
         decoded_height = i;
     } else if (ilv == 1) { /* line interleaving */
-        int j;
-        int Rc[3] = { 0, 0, 0 };
-        stride = (s->nb_components > 1) ? 3 : 1;
-        memset(cur, 0, s->picture_ptr->linesize[0]);
-        width = s->width * stride;
-        for (i = 0; i < s->height; i++) {
-            int ret;
-            for (j = 0; j < stride; j++) {
-                ret = ls_decode_line(state, s, last + j, cur + j,
-                               Rc[j], width, stride, j, 8);
+        int init_RSTn = 1;
+        if (s->rgb && s->nb_components == 3 && s->v_max == 1 && s->h_max ==
1) /* RGB 444 */
+        {
+            cur[0]  = s->picture_ptr->data[0];
+            last[0] = zero;
+
+            for (i = 0; i < s->height; i++) {
+                for (cmp = 0; cmp < s->nb_components; cmp++) {
+                    ret = ls_decode_line(state, s, last[0] + cmp, cur[0] +
cmp, Rc[cmp], s->width * s->nb_components, s->nb_components, cmp, s->bits);
+                    if (ret < 0)
+                        break;
+                    Rc[cmp] = (s->bits <= 8 ? last[0][cmp] : ((uint16_t
*)(last[0]))[cmp]);
+                }
+                if (ret < 0)
+                    break;
+                last[0] = cur[0];
+                cur[0] += s->picture_ptr->linesize[0];
+
+                if (s->restart_interval && !--s->restart_count && i !=
s->height - 1) {
+                    ret = ls_decode_skip_restart_marker(s, init_RSTn);
+                    if (ret < 0)
+                        break;
+
+                    /* Reset decoder, skip RSTn */
+                    s->restart_count = s->restart_interval;
+                    ff_jpegls_init_state(state);
+                    init_RSTn = 0;
+                    last[0]   = zero;
+                    Rc[0]     = 0;
+                }
+            }
+        } else { /* YUV 444, 422, 420, 411 */
+            for (cmp = 0; cmp < s->nb_components; cmp++) {
+                cur[cmp]  = s->picture_ptr->data[cmp];
+                last[cmp] = zero;
+            }
+            for (i = 0; i < s->height; i += s->v_max) {
+                for (cmp = 0; cmp < s->nb_components; cmp++) {
+                    for (m = 0; m < (cmp ? 1 : s->v_max) ; m++) {
+                        ret   = ls_decode_line(state, s, last[cmp],
cur[cmp], Rc[cmp], s->width / (cmp ? s->h_max : 1), 1, cmp, s->bits);
+                        Rc[cmp] = (s->bits <= 8 ? last[cmp][0] : ((uint16_t
*)(last[cmp]))[0]);
+                        if (ret < 0)
+                            break;
+                        last[cmp] = cur[cmp];
+                        cur[cmp] += s->picture_ptr->linesize[cmp];
+                    }
+                }
                 if (ret < 0)
                     break;
-                Rc[j] = last[j];
 
-                if (s->restart_interval && !--s->restart_count) {
-                    align_get_bits(&s->gb);
-                    skip_bits(&s->gb, 16); /* skip RSTn */
+                if (s->restart_interval && !--s->restart_count && i !=
s->height - s->v_max) {
+                    ret = ls_decode_skip_restart_marker(s, init_RSTn);
+                    if (ret < 0)
+                        break;
+
+                    /* Reset decoder, skip RSTn */
+                    s->restart_count = s->restart_interval;
+                    ff_jpegls_init_state(state);
+                    init_RSTn = 0;
+                    for (cmp = 0; cmp < s->nb_components; cmp++) {
+                        Rc[cmp]   = 0;
+                        last[cmp] = zero;
+                    }
                 }
             }
-            if (ret < 0)
-                break;
-            last = cur;
-            cur += s->picture_ptr->linesize[0];
         }
         decoded_height = i;
     } else if (ilv == 2) { /* sample interleaving */
@@ -465,73 +538,78 @@ int ff_jpegls_decode_picture(MJpegDecodeContext *s,
int near,
         goto end;
     }
 
-    if (s->xfrm && s->nb_components == 3) {
-        int x, w;
-
-        w = s->width * s->nb_components;
+    w   = s->width;
+    cmp = (ilv == 0 ? av_clip(s->cur_scan, 0, s->nb_components) :
s->nb_components); /* end component */
+    is_last_cmp = (cmp == 3 || s->nb_components == 1 ? 1 : 0);
 
+    if (s->xfrm && s->nb_components == 3 && is_last_cmp) {
         if (s->bits <= 8) {
-            uint8_t *src = s->picture_ptr->data[0];
+            uint8_t *src[3];
+            src[0] = s->picture_ptr->data[0];
+            src[1] = s->picture_ptr->data[1];
+            src[2] = s->picture_ptr->data[2];
 
-            for (i = 0; i < s->height; i++) {
+            for (i = 0; i < decoded_height; i++) {
                 switch(s->xfrm) {
                 case 1:
-                    for (x = off; x < w; x += 3) {
-                        src[x  ] += src[x+1] + 128;
-                        src[x+2] += src[x+1] + 128;
+                    for (x = 0; x < w; x++) {
+                        src[0][x] += src[1][x] + 128;
+                        src[2][x] += src[1][x] + 128;
                     }
                     break;
                 case 2:
-                    for (x = off; x < w; x += 3) {
-                        src[x  ] += src[x+1] + 128;
-                        src[x+2] += ((src[x  ] + src[x+1])>>1) + 128;
+                    for (x = 0; x < w; x++) {
+                        src[0][x] += src[1][x] + 128;
+                        src[2][x] += ((src[0][x] + src[1][x])>>1) + 128;
                     }
                     break;
                 case 3:
-                    for (x = off; x < w; x += 3) {
-                        int g = src[x+0] - ((src[x+2]+src[x+1])>>2) + 64;
-                        src[x+0] = src[x+2] + g + 128;
-                        src[x+2] = src[x+1] + g + 128;
-                        src[x+1] = g;
+                    for (x = 0; x < w; x++) {
+                        int g = src[0][x] - ((src[2][x]+src[1][x])>>2) +
64;
+                        src[0][x] = src[2][x] + g + 128;
+                        src[2][x] = src[1][x] + g + 128;
+                        src[1][x] = g;
                     }
                     break;
                 case 4:
-                    for (x = off; x < w; x += 3) {
-                        int r    = src[x+0] - ((                       359
* (src[x+2]-128) + 490) >> 8);
-                        int g    = src[x+0] - (( 88 * (src[x+1]-128) - 183
* (src[x+2]-128) +  30) >> 8);
-                        int b    = src[x+0] + ((454 * (src[x+1]-128)
+ 574) >> 8);
-                        src[x+0] = av_clip_uint8(r);
-                        src[x+1] = av_clip_uint8(g);
-                        src[x+2] = av_clip_uint8(b);
+                    for (x = 0; x < w; x++) {
+                        int r    = src[0][x] - ((
359 * (src[2][x]-128) + 490) >> 8);
+                        int g    = src[0][x] - (( 88 * (src[1][x]-128) -
183 * (src[2][x]-128) +  30) >> 8);
+                        int b    = src[0][x] + ((454 * (src[1][x]-128)
+ 574) >> 8);
+                        src[0][x] = av_clip_uint8(r);
+                        src[1][x] = av_clip_uint8(g);
+                        src[2][x] = av_clip_uint8(b);
                     }
                     break;
                 }
-                src += s->picture_ptr->linesize[0];
+                src[0] += s->picture_ptr->linesize[0];
+                src[1] += s->picture_ptr->linesize[1];
+                src[2] += s->picture_ptr->linesize[2];
             }
-        }else
+        } else
             avpriv_report_missing_feature(s->avctx, "16bit xfrm");
     }
 
-    if (shift) { /* we need to do point transform or normalize samples */
-        int x, w;
+    if (shift && is_last_cmp) { /* we need to do point transform or
normalize samples */
 
-        w = s->width * s->nb_components;
 
-        if (s->bits <= 8) {
-            uint8_t *src = s->picture_ptr->data[0];
+        for (cmp = 0; cmp < s->nb_components; cmp++) {
+            if (s->bits <= 8) {
+                uint8_t *src = s->picture_ptr->data[cmp];
 
-            for (i = 0; i < decoded_height; i++) {
-                for (x = off; x < w; x += stride)
-                    src[x] <<= shift;
-                src += s->picture_ptr->linesize[0];
-            }
-        } else {
-            uint16_t *src = (uint16_t *)s->picture_ptr->data[0];
+                for (i = 0; i < decoded_height / (cmp ? s->v_max : 1); i++)
{
+                    for (x = 0; x < w / (cmp ? s->h_max : 1); x++)
+                        src[x] <<= shift;
+                    src += s->picture_ptr->linesize[cmp];
+                }
+            } else {
+                uint16_t *src = (uint16_t *)s->picture_ptr->data[cmp];
 
-            for (i = 0; i < decoded_height; i++) {
-                for (x = 0; x < w; x++)
-                    src[x] <<= shift;
-                src += s->picture_ptr->linesize[0] / 2;
+                for (i = 0; i < decoded_height / (cmp ? s->v_max : 1); i++)
{
+                    for (x = 0; x < w / (cmp ? s->h_max : 1); x++)
+                        src[x] <<= shift;
+                    src += s->picture_ptr->linesize[cmp] / 2;
+                }
             }
         }
     }
@@ -543,12 +621,28 @@ end:
     return ret;
 }
 
+#define OFFSET(x) offsetof(MJpegDecodeContext, x)
+#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
+static const AVOption options[] = {
+    { "rgb444", "Are RGB 444 JPEG-LS input images?",
+      OFFSET(rgb), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VD },
+    { NULL },
+};
+
+static const AVClass jpeglsdec_class = {
+    .class_name = "JPEG-LS decoder",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
 AVCodec ff_jpegls_decoder = {
     .name           = "jpegls",
     .long_name      = NULL_IF_CONFIG_SMALL("JPEG-LS"),
     .type           = AVMEDIA_TYPE_VIDEO,
     .id             = AV_CODEC_ID_JPEGLS,
     .priv_data_size = sizeof(MJpegDecodeContext),
+    .priv_class     = &jpeglsdec_class,
     .init           = ff_mjpeg_decode_init,
     .close          = ff_mjpeg_decode_end,
     .receive_frame  = ff_mjpeg_receive_frame,
diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
index f3d9e99..952c5c4 100644
--- a/libavcodec/mjpegdec.c
+++ b/libavcodec/mjpegdec.c
@@ -352,10 +352,9 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
             return AVERROR_INVALIDDATA;
         }
     }
-    if (s->ls && !(bits <= 8 || nb_components == 1)) {
+    if (s->ls && (bits < 8 || bits > 16)) {
         avpriv_report_missing_feature(s->avctx,
-                                      "JPEG-LS that is not <= 8 "
-                                      "bits/component or 16-bit gray");
+                                      "JPEG-LS that is < 8 or > 16
bits/component");
         return AVERROR_PATCHWELCOME;
     }
