diff --git a/gst/mpegtsmux/Makefile.am b/gst/mpegtsmux/Makefile.am
index 0fa78d7..5f1c38e 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 67c2b72..16ff52e 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
@@ -149,7 +150,8 @@ static GstStaticPadTemplate mpegtsmux_sink_factory =
         "audio/x-opus, "
         "channels = (int) [1, 8], "
         "channel-mapping-family = (int) {0, 1};"
-        "subpicture/x-dvb; application/x-teletext; meta/x-klv, parsed=true"));
+        "subpicture/x-dvb; application/x-teletext; meta/x-klv, parsed=true;"
+        "image/x-jpc;"));
 
 static GstStaticPadTemplate mpegtsmux_src_factory =
 GST_STATIC_PAD_TEMPLATE ("src",
@@ -739,6 +741,87 @@ mpegtsmux_create_stream (MpegTsMux * mux, MpegTsPadData * ts_data)
     ts_data->prepare_func = mpegtsmux_prepare_opus;
   } else if (strcmp (mt, "meta/x-klv") == 0) {
     st = TSMUX_ST_PS_KLV;
+  } else if (strcmp (mt, "image/x-jpc") == 0) {
+
+    GstMapInfo map_info;
+    GstMemory * private_data = gst_allocator_alloc(NULL, sizeof(j2k_private_data), NULL);
+
+    if(!gst_memory_map(private_data, &map_info, GST_MAP_WRITE))
+    {
+      GST_ERROR_OBJECT (pad, "Unable to map memory");
+      // Free prepare data memory object
+      GstAllocator * default_allocator = gst_allocator_find (GST_ALLOCATOR_SYSMEM);
+      gst_allocator_free( default_allocator, private_data);
+      gst_object_unref(default_allocator);
+      
+      goto not_negotiated;
+    }
+
+    j2k_private_data * map_data_p = (j2k_private_data*) map_info.data;
+
+    map_data_p->interlace = FALSE; // will be set later, //TODO: interlace video mode doesn't work yet
+    map_data_p->den = 0;           // will be set later
+    map_data_p->num = 0;           // will be set later
+    map_data_p->MaxBr = 160000000; //TODO: add bitrate property to mpegtsmux
+    map_data_p->Fic = 1;           //TODO: get from caps
+    map_data_p->Fio = 0;           //TODO: get from caps
+    map_data_p->CollC = 1;         // will be set later
+
+    // Get Framerate
+    const GValue * vFramerate = gst_structure_get_value(s,"framerate");
+    if(vFramerate != NULL)
+    {
+      // Data for ELSM header
+      map_data_p->num = gst_value_get_fraction_numerator(vFramerate);
+      map_data_p->den = gst_value_get_fraction_denominator(vFramerate);
+    }
+
+    // Get Interlace-mode
+    const GValue * vInterlace = gst_structure_get_value(s,"interlace-mode");
+    if(vInterlace)
+    {
+      const char * interlace_mode = g_value_get_string(vInterlace);
+      if(g_str_equal(interlace_mode, "interleaved")) {
+         // Data for ELSM header
+        map_data_p->interlace = TRUE;
+      } else if(g_str_equal(interlace_mode, "progressive")) {
+         // Data for ELSM header
+        map_data_p->interlace = FALSE;
+      } else {
+        map_data_p->interlace = FALSE;
+      }
+    }
+
+    // Get Colorimetry
+    const GValue * vColorimetry = gst_structure_get_value(s,"colorimetry");
+    if(vColorimetry)
+    {
+      const char * colorimetry = g_value_get_string(vColorimetry);
+
+      if(g_str_equal(colorimetry, "bt601")) {
+        map_data_p->CollC = 2;
+      } else {
+       if(g_str_equal(colorimetry, "bt709") || g_str_equal(colorimetry, "smpte240m")) {
+        map_data_p->CollC = 3;
+       } else {
+        map_data_p->CollC = 1; // RGB as default
+       }
+      }
+    } else {
+      GST_ERROR_OBJECT (pad, "Colorimetry not present in caps");
+      // release memory for private_data
+      GstAllocator * default_allocator = gst_allocator_find (GST_ALLOCATOR_SYSMEM);
+      gst_allocator_free( default_allocator, private_data);
+      gst_object_unref(default_allocator);
+      goto not_negotiated;
+    }
+
+    gst_memory_unmap(private_data, &map_info);
+
+    st = TSMUX_ST_VIDEO_JP2K;
+    ts_data->prepare_func = mpegtsmux_prepare_jpeg2000;
+    ts_data->prepare_data = private_data;
+    ts_data->free_func = mpegtsmux_free_jpeg2000;
   }
 
   if (st != TSMUX_ST_RESERVED) {
diff --git a/gst/mpegtsmux/tsmux/tsmuxstream.c b/gst/mpegtsmux/tsmux/tsmuxstream.c
index f719d8f..56b6241 100644
--- a/gst/mpegtsmux/tsmux/tsmuxstream.c
+++ b/gst/mpegtsmux/tsmux/tsmuxstream.c
@@ -84,7 +84,8 @@
 #include <string.h>
 
 #include <gst/mpegts/mpegts.h>
-
+#include <gst/base/gstbytewriter.h>
+ 
 #include "tsmuxcommon.h"
 #include "tsmuxstream.h"
 
@@ -144,6 +145,11 @@ 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->pi.flags |= TSMUX_PACKET_FLAG_PES_FULL_HEADER;
+      stream->is_video_stream = TRUE;
+    break;
     case TSMUX_ST_AUDIO_AAC:
     case TSMUX_ST_AUDIO_MPEG1:
     case TSMUX_ST_AUDIO_MPEG2:
@@ -768,6 +774,53 @@ tsmux_stream_get_es_descrs (TsMuxStream * stream,
       descriptor = gst_mpegts_descriptor_from_registration ("drac", NULL, 0);
       g_ptr_array_add (pmt_stream->descriptors, descriptor);
       break;
+      case TSMUX_ST_VIDEO_JP2K:
+    {
+      /* J2K video descriptor
+       * descriptor_tag             8 uimsbf
+       * descriptor_length          8 uimsbf
+       * profile_and_level         16 uimsbf
+       * horizontal_size           32 uimsbf
+       * vertical_size             32 uimsbf
+       * max_bit_rate              32 uimsbf
+       * max_buffer_size           32 uimsbf
+       * DEN_frame_rate            16 uimsbf
+       * NUM_frame_rate            16 uimsbf
+       * color_specification        8 bslbf
+       * still_mode                 1 bslbf
+       * interlace_video            1 bslbf
+       * reserved                   6 bslbf
+       * private_data_byte          8 bslbf
+       */
+
+      GstByteWriter * writer = gst_byte_writer_new();
+
+      gst_byte_writer_put_uint16_be(writer, 0x0102);    //TODO: get the profile form caps, set as default Profile 2
+      gst_byte_writer_put_uint32_be(writer, stream->horizontal_size);
+      gst_byte_writer_put_uint32_be(writer, stream->vertical_size);
+      gst_byte_writer_put_uint32_be(writer, 0x9896800); //TODO: get the bitrate from caps 160 Mbit/s
+      gst_byte_writer_put_uint32_be(writer, 0x1312d0);  //TODO: set the max buffer size according to the Profile viz. 
+      gst_byte_writer_put_uint16_be(writer, stream->den);
+      gst_byte_writer_put_uint16_be(writer, stream->num);
+
+      gst_byte_writer_put_uint8(writer, stream->CollC);
+
+      gint8 remaining = 0x00;
+      if(stream->interlace_mode)
+        remaining |= 0x40;
+
+      gst_byte_writer_put_uint8(writer, remaining); // TODO: 1 bit, 1 bit, 6 bits
+      gst_byte_writer_put_uint8(writer, 0x00);
+
+      int wr_size = gst_byte_writer_get_size(writer);
+      guint8 * add_info = gst_byte_writer_reset_and_get_data(writer);
+
+      descriptor = gst_mpegts_descriptor_from_custom(GST_MTS_DESC_J2K_VIDEO, add_info, wr_size);
+      gst_byte_writer_free(writer);
+
+      g_ptr_array_add (pmt_stream->descriptors, descriptor);
+    }
+    break;
     case TSMUX_ST_PS_AUDIO_AC3:
     {
       guint8 add_info[6];
diff --git a/gst/mpegtsmux/tsmux/tsmuxstream.h b/gst/mpegtsmux/tsmux/tsmuxstream.h
index 2766718..e06b9b7 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,
@@ -216,6 +217,14 @@ struct TsMuxStream {
   /* Opus */
   gboolean is_opus;
   guint8 opus_channel_config_code;
+
+  /* Jpeg2000 */
+  gint32 horizontal_size;
+  gint32 vertical_size;
+  gint32 den;
+  gint32 num;
+  gboolean interlace_mode;
+  guint8 CollC;
 };
 
 /* stream management */
