diff --git a/gst/mpegtsdemux/tsdemux.c b/gst/mpegtsdemux/tsdemux.c
index 8a41f90..6ac304d 100644
--- a/gst/mpegtsdemux/tsdemux.c
+++ b/gst/mpegtsdemux/tsdemux.c
@@ -212,6 +212,7 @@ struct _TSDemuxStream
     "video/x-h265,stream-format=(string)byte-stream," \
       "alignment=(string)nal;" \
     "video/x-dirac;" \
+    "image/x-jpc;" \
     "video/x-cavs;" \
     "video/x-wmv," \
       "wmvversion = (int) 3, " \
@@ -1206,6 +1207,10 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
           is_audio = TRUE;
           caps = gst_caps_new_empty_simple ("audio/x-smpte-302m");
           break;
+        case DRF_ID_JP2K:
+        is_video = TRUE;
+        caps = gst_caps_new_empty_simple ("image/x-jpc");
+        break;
         case DRF_ID_OPUS:
           desc = mpegts_get_descriptor_from_stream (bstream,
               GST_MTS_DESC_DVB_EXTENSION);
@@ -1447,6 +1452,68 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
           "stream-format", G_TYPE_STRING, "byte-stream",
           "alignment", G_TYPE_STRING, "nal", NULL);
       break;
+    case GST_MPEGTS_STREAM_TYPE_VIDEO_JP2K:
+      is_video = TRUE;
+      printf("Creating caps for image/x-jpc\n");
+
+      //GST_MTS_DESC_J2K_VIDEO
+      // desc = mpegts_get_descriptor_from_stream (bstream, GST_MTS_DESC_REGISTRATION);
+      // if(desc == NULL)
+      // {
+      //   caps = gst_caps_new_empty_simple ("image/x-jpc");
+      //   break;
+      // }
+
+      // GstByteReader br;
+
+      // /* skip tag, length and tag_extension */
+      // gst_byte_reader_init (&br, desc->data + 6, desc->length - 1);
+            
+      //     printf("Header: ");
+      //     for(int i = 0; i < 27; i++)
+      //     {
+      //       printf("%x ", desc->data[i]);
+      //     }
+      //     printf("\n");
+
+      // // Framerate box
+      //TODO: remove just for testing
+      guint16 den  = 1;
+      guint16 num  = 24;
+      // // Maximum bitrate box
+      // guint32 MaxBr = gst_byte_reader_get_uint32_be_unchecked (&br);
+      // guint32 AUF1  = gst_byte_reader_get_uint32_be_unchecked (&br);
+      // guint32 AUF2  = gst_byte_reader_get_uint32_be_unchecked (&br);
+      // // Time Code box
+      // guint32 HHMMSSFF = gst_byte_reader_get_uint32_be_unchecked (&br);
+      // // Broadcast color box
+      // guint8 CollC = gst_byte_reader_get_uint8_unchecked (&br);
+
+      //TODO: remove just for testing
+      const gchar * colorspace = "sRGB";
+      // switch(CollC)
+      // {
+      //   case 1:
+      //   colorspace = "sRGB";
+      //   break;
+
+      //   case 2:
+      //   case 3:
+      //   case 4:
+      //   colorspace = "sYUV";
+      //   break;
+
+      //   // case 6:
+      //   // colorspace = "GRAY";
+      //   // break;
+      //   default:
+      //   colorspace = "";
+      // }
+
+        caps = gst_caps_new_simple ("image/x-jpc",
+                                    "framerate", GST_TYPE_FRACTION, num, den,
+                                    "colorspace", G_TYPE_STRING, colorspace, NULL);
+      break; 
     case ST_VIDEO_DIRAC:
       if (bstream->registration_id == 0x64726163) {
         GST_LOG ("dirac");
@@ -2458,6 +2525,128 @@ error:
   }
 }
 
+static GstBufferList *
+parse_jp2k_access_unit (TSDemuxStream * stream)
+{
+  GstByteReader reader;
+  GstBufferList *buffer_list = NULL;
+
+  buffer_list = gst_buffer_list_new ();
+  gst_byte_reader_init (&reader, stream->data, stream->current_size);
+
+
+  do {
+    // header tag
+    guint32 header_tag;
+
+    GstBuffer *buffer;
+    // Framerate box
+    guint16 den  = 0;
+    guint16 num  = 0;
+    // Maximum bitrate box
+    guint32 MaxBr = 0;
+    guint32 AUF1  = 0;
+    guint32 AUF2  = 0;
+    // Field Coding Box
+    guint8 Fic = 1;
+    guint8 Fio = 0;
+    // Time Code box
+    guint32 HHMMSSFF = 0;
+    // Broadcast color box
+    guint8 CollC = 0;
+    guint au_size = 0;
+    guint8 b;
+
+    guint8 *packet_data;
+    guint packet_size;
+
+    // Elementary stream header box
+    if (!gst_byte_reader_get_uint32_be(&reader, &header_tag))
+      goto error;
+
+  if(header_tag == "elsm")
+  {
+    // Framerate box 0x66726174
+    if (!gst_byte_reader_get_uint32_be(&reader, &header_tag))
+      goto error;
+
+    if(header_tag == "frat")
+    {
+    if (!gst_byte_reader_get_uint16_be (&reader, &den))
+      goto error;
+
+    if (!gst_byte_reader_get_uint16_be (&reader, &num))
+      goto error;
+
+    }
+
+    // Maximum bitrate box 0x62726174
+    if (!gst_byte_reader_get_uint32_be(&reader, &header_tag))
+      goto error;
+
+    if(header_tag == "brat")
+    {
+    if (!gst_byte_reader_get_uint32_be (&reader, &MaxBr))
+      goto error;
+    if (!gst_byte_reader_get_uint32_be (&reader, &AUF1))
+      goto error;
+    if (!gst_byte_reader_get_uint32_be (&reader, &AUF2))
+      goto error;
+    }
+
+    // Field Coding Box OR Time Code Box
+    if (!gst_byte_reader_get_uint32_be(&reader, &header_tag))
+      goto error;
+    
+    if(header_tag == "fiel")
+    {
+      //TODO: interlance video
+    }
+
+    if(header_tag == "tcod")
+    {
+      if (!gst_byte_reader_get_uint32_be (&reader, &HHMMSSFF))
+        goto error;
+    }
+    
+    // Broadcast Color Box
+    if (!gst_byte_reader_get_uint32_be(&reader, &header_tag))
+      goto error;
+
+    if(header_tag == "bcol")
+    {
+      if (!gst_byte_reader_get_uint8 (&reader, &CollC))
+        goto error;
+    }
+  }
+
+    packet_size = gst_byte_reader_get_remaining(&reader);
+
+    if (!gst_byte_reader_dup_data (&reader, packet_size, &packet_data))
+      goto error;
+
+    buffer = gst_buffer_new_wrapped (packet_data, packet_size);
+
+    gst_buffer_list_add (buffer_list, buffer);
+  } while (gst_byte_reader_get_remaining (&reader) > 0);
+
+  g_free (stream->data);
+  stream->data = NULL;
+  stream->current_size = 0;
+
+  return buffer_list;
+
+error:
+  {
+    GST_ERROR ("Failed to parse JP2K access unit");
+    g_free (stream->data);
+    stream->data = NULL;
+    stream->current_size = 0;
+    gst_buffer_list_unref (buffer_list);
+    return NULL;
+  }
+}
+
 static GstFlowReturn
 gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream)
 {
@@ -2514,7 +2703,22 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream)
           buffer_list = NULL;
         }
       } else {
-        buffer = gst_buffer_new_wrapped (stream->data, stream->current_size);
+        if (bs->stream_type == GST_MPEGTS_STREAM_TYPE_VIDEO_JP2K &&
+            bs->registration_id == DRF_ID_JP2K) {
+          buffer_list = parse_jp2k_access_unit (stream);
+          if (!buffer_list) {
+           res = GST_FLOW_ERROR;
+            goto beach;
+          }
+
+          if (gst_buffer_list_length (buffer_list) == 1) {
+            buffer = gst_buffer_ref (gst_buffer_list_get (buffer_list, 0));
+            gst_buffer_list_unref (buffer_list);
+            buffer_list = NULL;
+          }
+        } else {
+          buffer = gst_buffer_new_wrapped (stream->data, stream->current_size);
+          }
       }
 
       stream->seeked_pts = stream->pts;
@@ -2548,9 +2752,23 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream)
         buffer_list = NULL;
       }
     } else {
-      buffer = gst_buffer_new_wrapped (stream->data, stream->current_size);
-    }
+      if(bs->stream_type == GST_MPEGTS_STREAM_TYPE_VIDEO_JP2K && bs->registration_id == DRF_ID_JP2K) {
+        buffer_list = parse_jp2k_access_unit (stream);
+        
+        if (!buffer_list) {
+          res = GST_FLOW_ERROR;
+          goto beach;
+        }
 
+        if (gst_buffer_list_length (buffer_list) == 1) {
+          buffer = gst_buffer_ref (gst_buffer_list_get (buffer_list, 0));
+          gst_buffer_list_unref (buffer_list);
+          buffer_list = NULL;
+        }
+      } else {
+          buffer = gst_buffer_new_wrapped (stream->data, stream->current_size);  
+        }
+    }
     if (G_UNLIKELY (stream->pending_ts && !check_pending_buffers (demux))) {
       if (buffer) {
         PendingBuffer *pend;
diff --git a/gst/mpegtsmux/Makefile.am b/gst/mpegtsmux/Makefile.am
index 0fa78d7..0d7c938 100644
--- a/gst/mpegtsmux/Makefile.am
+++ b/gst/mpegtsmux/Makefile.am
@@ -6,7 +6,8 @@ libgstmpegtsmux_la_SOURCES = \
 	mpegtsmux.c \
 	mpegtsmux_aac.c \
 	mpegtsmux_ttxt.c \
-	mpegtsmux_opus.c
+	mpegtsmux_opus.c \ 
+	mpegtsmux_jpeg2000.c
 
 libgstmpegtsmux_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \
 			    $(GST_BASE_CFLAGS) $(GST_CFLAGS)
@@ -22,4 +23,5 @@ noinst_HEADERS = \
 	mpegtsmux.h \
 	mpegtsmux_aac.h \
 	mpegtsmux_ttxt.h \
-	mpegtsmux_opus.h
+	mpegtsmux_opus.h \ 
+	mpegtsmux_jpeg2000.h
diff --git a/gst/mpegtsmux/mpegtsmux.c b/gst/mpegtsmux/mpegtsmux.c
index af051ca..99a89bf 100644
--- a/gst/mpegtsmux/mpegtsmux.c
+++ b/gst/mpegtsmux/mpegtsmux.c
@@ -98,6 +98,7 @@
 #include "mpegtsmux_aac.h"
 #include "mpegtsmux_ttxt.h"
 #include "mpegtsmux_opus.h"
+#include "mpegtsmux_jpeg2000.h"
 
 GST_DEBUG_CATEGORY (mpegtsmux_debug);
 #define GST_CAT_DEFAULT mpegtsmux_debug
@@ -125,6 +126,7 @@ static GstStaticPadTemplate mpegtsmux_sink_factory =
         "mpegversion = (int) { 1, 2, 4 }, "
         "systemstream = (boolean) false; "
         "video/x-dirac;"
+        "image/x-jpc;"
         "video/x-h264,stream-format=(string)byte-stream,"
         "alignment=(string){au, nal}; "
         "video/x-h265,stream-format=(string)byte-stream,"
@@ -616,6 +618,35 @@ mpegtsmux_create_stream (MpegTsMux * mux, MpegTsPadData * ts_data)
     st = TSMUX_ST_VIDEO_H264;
   } else if (strcmp (mt, "video/x-h265") == 0) {
     st = TSMUX_ST_VIDEO_HEVC;
+  } else if (strcmp (mt, "image/x-jpc") == 0) {
+    GST_DEBUG_OBJECT (pad, "Start of image/x-jpc");
+    
+    gint num, den;
+    const char * colorspace;
+
+    if (!gst_structure_get_fraction (s, "framerate", &num, &den)) {
+      GST_ERROR_OBJECT (pad, "caps missing framerate");
+      goto not_negotiated;
+    }
+
+    colorspace = gst_structure_get_string (s, "colorspace");
+    if (colorspace == NULL) {
+      GST_ERROR_OBJECT (pad, "caps missing colorspace");
+      goto not_negotiated;
+    }
+
+    char * prepare_data =  (char*) malloc(23);
+    if(prepare_data == NULL)
+    {
+      GST_ERROR_OBJECT (pad, "unable to allocate prepare_data for JP2K");
+      goto not_negotiated;
+    }
+
+    st = TSMUX_ST_VIDEO_JP2K;
+    ts_data->prepare_func = mpegtsmux_prepare_jpeg2000;
+    ts_data->prepare_data = (gpointer) prepare_data;
+    //TODO: ts_data->free_func = 
+
   } else if (strcmp (mt, "audio/mpeg") == 0) {
     gint mpegversion;
 
diff --git a/gst/mpegtsmux/tsmux/tsmuxstream.c b/gst/mpegtsmux/tsmux/tsmuxstream.c
index f719d8f..98145d0 100644
--- a/gst/mpegtsmux/tsmux/tsmuxstream.c
+++ b/gst/mpegtsmux/tsmux/tsmuxstream.c
@@ -87,6 +87,7 @@
 
 #include "tsmuxcommon.h"
 #include "tsmuxstream.h"
+#include <gst/base/gstbytewriter.h>
 
 #define GST_CAT_DEFAULT mpegtsmux_debug
 
@@ -144,6 +145,13 @@ tsmux_stream_new (guint16 pid, TsMuxStreamType stream_type)
       stream->pi.flags |= TSMUX_PACKET_FLAG_PES_FULL_HEADER;
       stream->is_video_stream = TRUE;
       break;
+    case TSMUX_ST_VIDEO_JP2K:
+      stream->id = 0xBD;
+      stream->stream_type = TSMUX_ST_VIDEO_JP2K;
+      stream->pi.flags |= TSMUX_PACKET_FLAG_PES_FULL_HEADER;
+      stream->is_video_stream = TRUE;
+      break;
+    break;
     case TSMUX_ST_AUDIO_AAC:
     case TSMUX_ST_AUDIO_MPEG1:
     case TSMUX_ST_AUDIO_MPEG2:
@@ -764,6 +772,12 @@ tsmux_stream_get_es_descrs (TsMuxStream * stream,
       g_ptr_array_add (pmt_stream->descriptors, descriptor);
       break;
     }
+    case TSMUX_ST_VIDEO_JP2K:
+    {
+        descriptor = gst_mpegts_descriptor_from_registration("elsm", NULL, 0);
+        g_ptr_array_add (pmt_stream->descriptors, descriptor);
+      break;
+    }
     case TSMUX_ST_VIDEO_DIRAC:
       descriptor = gst_mpegts_descriptor_from_registration ("drac", NULL, 0);
       g_ptr_array_add (pmt_stream->descriptors, descriptor);
diff --git a/gst/mpegtsmux/tsmux/tsmuxstream.h b/gst/mpegtsmux/tsmux/tsmuxstream.h
index 2766718..8d14e91 100644
--- a/gst/mpegtsmux/tsmux/tsmuxstream.h
+++ b/gst/mpegtsmux/tsmux/tsmuxstream.h
@@ -134,6 +134,7 @@ enum TsMuxStreamType {
   TSMUX_ST_VIDEO_MPEG4                = 0x10,
   TSMUX_ST_VIDEO_H264                 = 0x1b,
   TSMUX_ST_VIDEO_HEVC                 = 0x24,
+  TSMUX_ST_VIDEO_JP2K                 = 0x21,
 
   /* private stream types */
   TSMUX_ST_PS_AUDIO_AC3               = 0x81,
