250129bbd746c8d71147bf9fafe94cd6abcfd768
[platform/upstream/gstreamer.git] / ext / openjpeg / gstopenjpegenc.c
1 /* 
2  * Copyright (C) 2012 Collabora Ltd.
3  *     Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
4  * Copyright (C) 2013 Sebastian Dröge <slomo@circular-chaos.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "gstopenjpegenc.h"
28 #include <gst/codecparsers/gstjpeg2000sampling.h>
29
30 #include <string.h>
31 #include <math.h>
32
33 GST_DEBUG_CATEGORY_STATIC (gst_openjpeg_enc_debug);
34 #define GST_CAT_DEFAULT gst_openjpeg_enc_debug
35
36 #define GST_OPENJPEG_ENC_TYPE_PROGRESSION_ORDER (gst_openjpeg_enc_progression_order_get_type())
37 static GType
38 gst_openjpeg_enc_progression_order_get_type (void)
39 {
40   static const GEnumValue values[] = {
41     {OPJ_LRCP, "LRCP", "lrcp"},
42     {OPJ_RLCP, "RLCP", "rlcp"},
43     {OPJ_RPCL, "RPCL", "rpcl"},
44     {OPJ_PCRL, "PCRL", "pcrl"},
45     {OPJ_CPRL, "CPRL", "crpl"},
46     {0, NULL, NULL}
47   };
48   static volatile GType id = 0;
49
50   if (g_once_init_enter ((gsize *) & id)) {
51     GType _id;
52
53     _id = g_enum_register_static ("GstOpenJPEGEncProgressionOrder", values);
54
55     g_once_init_leave ((gsize *) & id, _id);
56   }
57
58   return id;
59 }
60
61 enum
62 {
63   PROP_0,
64   PROP_NUM_LAYERS,
65   PROP_NUM_RESOLUTIONS,
66   PROP_PROGRESSION_ORDER,
67   PROP_TILE_OFFSET_X,
68   PROP_TILE_OFFSET_Y,
69   PROP_TILE_WIDTH,
70   PROP_TILE_HEIGHT,
71   PROP_NUM_STRIPES,
72   PROP_LAST
73 };
74
75 #define DEFAULT_NUM_LAYERS 1
76 #define DEFAULT_NUM_RESOLUTIONS 6
77 #define DEFAULT_PROGRESSION_ORDER OPJ_LRCP
78 #define DEFAULT_TILE_OFFSET_X 0
79 #define DEFAULT_TILE_OFFSET_Y 0
80 #define DEFAULT_TILE_WIDTH 0
81 #define DEFAULT_TILE_HEIGHT 0
82 #define GST_OPENJPEG_ENC_DEFAULT_NUM_STRIPES  1
83
84 static void gst_openjpeg_enc_set_property (GObject * object, guint prop_id,
85     const GValue * value, GParamSpec * pspec);
86 static void gst_openjpeg_enc_get_property (GObject * object, guint prop_id,
87     GValue * value, GParamSpec * pspec);
88
89 static gboolean gst_openjpeg_enc_start (GstVideoEncoder * encoder);
90 static gboolean gst_openjpeg_enc_stop (GstVideoEncoder * encoder);
91 static gboolean gst_openjpeg_enc_set_format (GstVideoEncoder * encoder,
92     GstVideoCodecState * state);
93 static GstFlowReturn gst_openjpeg_enc_handle_frame (GstVideoEncoder * encoder,
94     GstVideoCodecFrame * frame);
95 static gboolean gst_openjpeg_enc_propose_allocation (GstVideoEncoder * encoder,
96     GstQuery * query);
97
98 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
99 #define GRAY16 "GRAY16_LE"
100 #define YUV10 "Y444_10LE, I422_10LE, I420_10LE"
101 #else
102 #define GRAY16 "GRAY16_BE"
103 #define YUV10 "Y444_10BE, I422_10BE, I420_10BE"
104 #endif
105
106 static GstStaticPadTemplate gst_openjpeg_enc_sink_template =
107 GST_STATIC_PAD_TEMPLATE ("sink",
108     GST_PAD_SINK,
109     GST_PAD_ALWAYS,
110     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ ARGB64, ARGB, xRGB, "
111             "AYUV64, " YUV10 ", "
112             "AYUV, Y444, Y42B, I420, Y41B, YUV9, " "GRAY8, " GRAY16 " }"))
113     );
114
115 static GstStaticPadTemplate gst_openjpeg_enc_src_template =
116     GST_STATIC_PAD_TEMPLATE ("src",
117     GST_PAD_SRC,
118     GST_PAD_ALWAYS,
119     GST_STATIC_CAPS ("image/x-j2c, "
120         "width = (int) [1, MAX], "
121         "height = (int) [1, MAX], "
122         "num-components = (int) [1, 4], "
123         "num-stripes = (int) [1, MAX], "
124         GST_JPEG2000_SAMPLING_LIST ","
125         GST_JPEG2000_COLORSPACE_LIST "; "
126         "image/x-jpc, "
127         "width = (int) [1, MAX], "
128         "height = (int) [1, MAX], "
129         "num-components = (int) [1, 4], "
130         GST_JPEG2000_SAMPLING_LIST ","
131         GST_JPEG2000_COLORSPACE_LIST "; "
132         "image/jp2, " "width = (int) [1, MAX], " "height = (int) [1, MAX]")
133     );
134
135 #define parent_class gst_openjpeg_enc_parent_class
136 G_DEFINE_TYPE (GstOpenJPEGEnc, gst_openjpeg_enc, GST_TYPE_VIDEO_ENCODER);
137
138 static void
139 gst_openjpeg_enc_class_init (GstOpenJPEGEncClass * klass)
140 {
141   GObjectClass *gobject_class;
142   GstElementClass *element_class;
143   GstVideoEncoderClass *video_encoder_class;
144
145   gobject_class = (GObjectClass *) klass;
146   element_class = (GstElementClass *) klass;
147   video_encoder_class = (GstVideoEncoderClass *) klass;
148
149   gobject_class->set_property = gst_openjpeg_enc_set_property;
150   gobject_class->get_property = gst_openjpeg_enc_get_property;
151
152   g_object_class_install_property (gobject_class, PROP_NUM_LAYERS,
153       g_param_spec_int ("num-layers", "Number of layers",
154           "Number of layers", 1, 10, DEFAULT_NUM_LAYERS,
155           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
156
157   g_object_class_install_property (gobject_class, PROP_NUM_RESOLUTIONS,
158       g_param_spec_int ("num-resolutions", "Number of resolutions",
159           "Number of resolutions", 1, 10, DEFAULT_NUM_RESOLUTIONS,
160           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
161
162   g_object_class_install_property (gobject_class, PROP_PROGRESSION_ORDER,
163       g_param_spec_enum ("progression-order", "Progression Order",
164           "Progression order", GST_OPENJPEG_ENC_TYPE_PROGRESSION_ORDER,
165           DEFAULT_PROGRESSION_ORDER,
166           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
167
168   g_object_class_install_property (gobject_class, PROP_TILE_OFFSET_X,
169       g_param_spec_int ("tile-offset-x", "Tile Offset X",
170           "Tile Offset X", G_MININT, G_MAXINT, DEFAULT_TILE_OFFSET_X,
171           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
172
173   g_object_class_install_property (gobject_class, PROP_TILE_OFFSET_Y,
174       g_param_spec_int ("tile-offset-y", "Tile Offset Y",
175           "Tile Offset Y", G_MININT, G_MAXINT, DEFAULT_TILE_OFFSET_Y,
176           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
177
178   g_object_class_install_property (gobject_class, PROP_TILE_WIDTH,
179       g_param_spec_int ("tile-width", "Tile Width",
180           "Tile Width", 0, G_MAXINT, DEFAULT_TILE_WIDTH,
181           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
182
183   g_object_class_install_property (gobject_class, PROP_TILE_HEIGHT,
184       g_param_spec_int ("tile-height", "Tile Height",
185           "Tile Height", 0, G_MAXINT, DEFAULT_TILE_HEIGHT,
186           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
187
188   /**
189    * GstOpenJPEGEnc:num-stripes:
190    *
191    * Number of stripes to use for low latency encoding . (1 = low latency disabled)
192    *
193    * Since: 1.18
194    */
195   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NUM_STRIPES,
196       g_param_spec_int ("num-stripes", "Number of stripes",
197           "Number of stripes for low latency encoding. (1 = low latency disabled)",
198           1, G_MAXINT, GST_OPENJPEG_ENC_DEFAULT_NUM_STRIPES,
199           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
200
201   gst_element_class_add_static_pad_template (element_class,
202       &gst_openjpeg_enc_src_template);
203   gst_element_class_add_static_pad_template (element_class,
204       &gst_openjpeg_enc_sink_template);
205
206   gst_element_class_set_static_metadata (element_class,
207       "OpenJPEG JPEG2000 encoder",
208       "Codec/Encoder/Video",
209       "Encode JPEG2000 streams",
210       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
211
212   video_encoder_class->start = GST_DEBUG_FUNCPTR (gst_openjpeg_enc_start);
213   video_encoder_class->stop = GST_DEBUG_FUNCPTR (gst_openjpeg_enc_stop);
214   video_encoder_class->set_format =
215       GST_DEBUG_FUNCPTR (gst_openjpeg_enc_set_format);
216   video_encoder_class->handle_frame =
217       GST_DEBUG_FUNCPTR (gst_openjpeg_enc_handle_frame);
218   video_encoder_class->propose_allocation = gst_openjpeg_enc_propose_allocation;
219
220   GST_DEBUG_CATEGORY_INIT (gst_openjpeg_enc_debug, "openjpegenc", 0,
221       "OpenJPEG Encoder");
222
223   gst_type_mark_as_plugin_api (GST_OPENJPEG_ENC_TYPE_PROGRESSION_ORDER, 0);
224 }
225
226 static void
227 gst_openjpeg_enc_init (GstOpenJPEGEnc * self)
228 {
229   GST_PAD_SET_ACCEPT_TEMPLATE (GST_VIDEO_ENCODER_SINK_PAD (self));
230
231   opj_set_default_encoder_parameters (&self->params);
232
233   self->params.cp_fixed_quality = 1;
234   self->params.cp_disto_alloc = 0;
235   self->params.cp_fixed_alloc = 0;
236
237   /*
238    * TODO: Add properties / caps fields for these
239    *
240    * self->params.csty;
241    * self->params.tcp_rates;
242    * self->params.tcp_distoratio;
243    * self->params.mode;
244    * self->params.irreversible;
245    * self->params.cp_cinema;
246    * self->params.cp_rsiz;
247    */
248
249   self->params.tcp_numlayers = DEFAULT_NUM_LAYERS;
250   self->params.numresolution = DEFAULT_NUM_RESOLUTIONS;
251   self->params.prog_order = DEFAULT_PROGRESSION_ORDER;
252   self->params.cp_tx0 = DEFAULT_TILE_OFFSET_X;
253   self->params.cp_ty0 = DEFAULT_TILE_OFFSET_Y;
254   self->params.cp_tdx = DEFAULT_TILE_WIDTH;
255   self->params.cp_tdy = DEFAULT_TILE_HEIGHT;
256   self->params.tile_size_on = (self->params.cp_tdx != 0
257       && self->params.cp_tdy != 0);
258
259   self->num_stripes = GST_OPENJPEG_ENC_DEFAULT_NUM_STRIPES;
260 }
261
262 static void
263 gst_openjpeg_enc_set_property (GObject * object, guint prop_id,
264     const GValue * value, GParamSpec * pspec)
265 {
266   GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (object);
267
268   switch (prop_id) {
269     case PROP_NUM_LAYERS:
270       self->params.tcp_numlayers = g_value_get_int (value);
271       break;
272     case PROP_NUM_RESOLUTIONS:
273       self->params.numresolution = g_value_get_int (value);
274       break;
275     case PROP_PROGRESSION_ORDER:
276       self->params.prog_order = g_value_get_enum (value);
277       break;
278     case PROP_TILE_OFFSET_X:
279       self->params.cp_tx0 = g_value_get_int (value);
280       break;
281     case PROP_TILE_OFFSET_Y:
282       self->params.cp_ty0 = g_value_get_int (value);
283       break;
284     case PROP_TILE_WIDTH:
285       self->params.cp_tdx = g_value_get_int (value);
286       self->params.tile_size_on = (self->params.cp_tdx != 0
287           && self->params.cp_tdy != 0);
288       break;
289     case PROP_TILE_HEIGHT:
290       self->params.cp_tdy = g_value_get_int (value);
291       self->params.tile_size_on = (self->params.cp_tdx != 0
292           && self->params.cp_tdy != 0);
293       break;
294     case PROP_NUM_STRIPES:
295       self->num_stripes = g_value_get_int (value);
296       break;
297     default:
298       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
299       break;
300   }
301 }
302
303 static void
304 gst_openjpeg_enc_get_property (GObject * object, guint prop_id, GValue * value,
305     GParamSpec * pspec)
306 {
307   GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (object);
308
309   switch (prop_id) {
310     case PROP_NUM_LAYERS:
311       g_value_set_int (value, self->params.tcp_numlayers);
312       break;
313     case PROP_NUM_RESOLUTIONS:
314       g_value_set_int (value, self->params.numresolution);
315       break;
316     case PROP_PROGRESSION_ORDER:
317       g_value_set_enum (value, self->params.prog_order);
318       break;
319     case PROP_TILE_OFFSET_X:
320       g_value_set_int (value, self->params.cp_tx0);
321       break;
322     case PROP_TILE_OFFSET_Y:
323       g_value_set_int (value, self->params.cp_ty0);
324       break;
325     case PROP_TILE_WIDTH:
326       g_value_set_int (value, self->params.cp_tdx);
327       break;
328     case PROP_TILE_HEIGHT:
329       g_value_set_int (value, self->params.cp_tdy);
330       break;
331     case PROP_NUM_STRIPES:
332       g_value_set_int (value, self->num_stripes);
333       break;
334     default:
335       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
336       break;
337   }
338 }
339
340 static gboolean
341 gst_openjpeg_enc_start (GstVideoEncoder * encoder)
342 {
343   GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (encoder);
344
345   GST_DEBUG_OBJECT (self, "Starting");
346
347   return TRUE;
348 }
349
350 static gboolean
351 gst_openjpeg_enc_stop (GstVideoEncoder * video_encoder)
352 {
353   GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (video_encoder);
354
355   GST_DEBUG_OBJECT (self, "Stopping");
356
357   if (self->output_state) {
358     gst_video_codec_state_unref (self->output_state);
359     self->output_state = NULL;
360   }
361
362   if (self->input_state) {
363     gst_video_codec_state_unref (self->input_state);
364     self->input_state = NULL;
365   }
366
367   GST_DEBUG_OBJECT (self, "Stopped");
368
369   return TRUE;
370 }
371
372 static guint
373 get_stripe_height (GstOpenJPEGEnc * self, guint slice_num, guint frame_height)
374 {
375   guint nominal_stripe_height = frame_height / self->num_stripes;
376   return (slice_num <
377       self->num_stripes -
378       1) ? nominal_stripe_height : frame_height -
379       (slice_num * nominal_stripe_height);
380 }
381
382 static void
383 fill_image_packed16_4 (opj_image_t * image, GstVideoFrame * frame)
384 {
385   gint x, y, w, h;
386   const guint16 *data_in, *tmp;
387   gint *data_out[4];
388   gint sstride;
389
390   w = GST_VIDEO_FRAME_WIDTH (frame);
391   h = image->y1 - image->y0;
392   sstride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0) / 2;
393   data_in =
394       (guint16 *) GST_VIDEO_FRAME_PLANE_DATA (frame, 0) + image->y0 * sstride;
395
396   data_out[0] = image->comps[0].data;
397   data_out[1] = image->comps[1].data;
398   data_out[2] = image->comps[2].data;
399   data_out[3] = image->comps[3].data;
400
401   for (y = 0; y < h; y++) {
402     tmp = data_in;
403
404     for (x = 0; x < w; x++) {
405       *data_out[3] = tmp[0];
406       *data_out[0] = tmp[1];
407       *data_out[1] = tmp[2];
408       *data_out[2] = tmp[3];
409
410       tmp += 4;
411       data_out[0]++;
412       data_out[1]++;
413       data_out[2]++;
414       data_out[3]++;
415     }
416     data_in += sstride;
417   }
418 }
419
420 static void
421 fill_image_packed8_4 (opj_image_t * image, GstVideoFrame * frame)
422 {
423   gint x, y, w, h;
424   const guint8 *data_in, *tmp;
425   gint *data_out[4];
426   gint sstride;
427
428   w = GST_VIDEO_FRAME_WIDTH (frame);
429   h = image->y1 - image->y0;
430   sstride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0);
431   data_in =
432       (guint8 *) GST_VIDEO_FRAME_PLANE_DATA (frame, 0) + image->y0 * sstride;
433
434   data_out[0] = image->comps[0].data;
435   data_out[1] = image->comps[1].data;
436   data_out[2] = image->comps[2].data;
437   data_out[3] = image->comps[3].data;
438
439   for (y = 0; y < h; y++) {
440     tmp = data_in;
441
442     for (x = 0; x < w; x++) {
443       *data_out[3] = tmp[0];
444       *data_out[0] = tmp[1];
445       *data_out[1] = tmp[2];
446       *data_out[2] = tmp[3];
447
448       tmp += 4;
449       data_out[0]++;
450       data_out[1]++;
451       data_out[2]++;
452       data_out[3]++;
453     }
454     data_in += sstride;
455   }
456 }
457
458 static void
459 fill_image_packed8_3 (opj_image_t * image, GstVideoFrame * frame)
460 {
461   gint x, y, w, h;
462   const guint8 *data_in, *tmp;
463   gint *data_out[3];
464   gint sstride;
465
466   w = GST_VIDEO_FRAME_WIDTH (frame);
467   h = image->y1 - image->y0;
468   sstride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0);
469   data_in =
470       (guint8 *) GST_VIDEO_FRAME_PLANE_DATA (frame, 0) + image->y0 * sstride;
471
472   data_out[0] = image->comps[0].data;
473   data_out[1] = image->comps[1].data;
474   data_out[2] = image->comps[2].data;
475
476   for (y = 0; y < h; y++) {
477     tmp = data_in;
478
479     for (x = 0; x < w; x++) {
480       *data_out[0] = tmp[1];
481       *data_out[1] = tmp[2];
482       *data_out[2] = tmp[3];
483
484       tmp += 4;
485       data_out[0]++;
486       data_out[1]++;
487       data_out[2]++;
488     }
489     data_in += sstride;
490   }
491 }
492
493 static void
494 fill_image_planar16_3 (opj_image_t * image, GstVideoFrame * frame)
495 {
496   gint c, x, y, w, h;
497   const guint16 *data_in, *tmp;
498   gint *data_out;
499   gint sstride;
500
501   for (c = 0; c < 3; c++) {
502     opj_image_comp_t *comp = image->comps + c;
503
504     w = GST_VIDEO_FRAME_COMP_WIDTH (frame, c);
505     h = comp->h;
506     sstride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, c) / 2;
507     data_in =
508         (guint16 *) GST_VIDEO_FRAME_COMP_DATA (frame,
509         c) + (image->y0 / comp->dy) * sstride;
510     data_out = comp->data;
511
512     for (y = 0; y < h; y++) {
513       tmp = data_in;
514       for (x = 0; x < w; x++) {
515         *data_out = *tmp;
516         data_out++;
517         tmp++;
518       }
519       data_in += sstride;
520     }
521   }
522 }
523
524 static void
525 fill_image_planar8_3 (opj_image_t * image, GstVideoFrame * frame)
526 {
527   gint c, x, y, w, h;
528   const guint8 *data_in, *tmp;
529   gint *data_out;
530   gint sstride;
531
532   for (c = 0; c < 3; c++) {
533     opj_image_comp_t *comp = image->comps + c;
534
535     w = GST_VIDEO_FRAME_COMP_WIDTH (frame, c);
536     h = comp->h;
537     sstride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, c);
538     data_in =
539         (guint8 *) GST_VIDEO_FRAME_COMP_DATA (frame,
540         c) + (image->y0 / comp->dy) * sstride;
541     data_out = comp->data;
542
543     for (y = 0; y < h; y++) {
544       tmp = data_in;
545       for (x = 0; x < w; x++) {
546         *data_out = *tmp;
547         data_out++;
548         tmp++;
549       }
550       data_in += sstride;
551     }
552   }
553 }
554
555 static void
556 fill_image_planar8_1 (opj_image_t * image, GstVideoFrame * frame)
557 {
558   gint x, y, w, h;
559   const guint8 *data_in, *tmp;
560   gint *data_out;
561   gint sstride;
562   opj_image_comp_t *comp = image->comps;
563
564   w = GST_VIDEO_FRAME_COMP_WIDTH (frame, 0);
565   h = comp->h;
566   sstride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0);
567   data_in =
568       (guint8 *) GST_VIDEO_FRAME_COMP_DATA (frame,
569       0) + (image->y0 / comp->dy) * sstride;
570   data_out = image->comps[0].data;
571
572   for (y = 0; y < h; y++) {
573     tmp = data_in;
574     for (x = 0; x < w; x++) {
575       *data_out = *tmp;
576       data_out++;
577       tmp++;
578     }
579     data_in += sstride;
580   }
581 }
582
583 static void
584 fill_image_planar16_1 (opj_image_t * image, GstVideoFrame * frame)
585 {
586   gint x, y, w, h;
587   const guint16 *data_in, *tmp;
588   gint *data_out;
589   gint sstride;
590   opj_image_comp_t *comp = image->comps;
591
592   w = GST_VIDEO_FRAME_COMP_WIDTH (frame, 0);
593   h = comp->h;
594   sstride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0) / 2;
595   data_in =
596       (guint16 *) GST_VIDEO_FRAME_COMP_DATA (frame,
597       0) + (image->y0 / comp->dy) * sstride;
598   data_out = comp->data;
599
600   for (y = 0; y < h; y++) {
601     tmp = data_in;
602     for (x = 0; x < w; x++) {
603       *data_out = *tmp;
604       data_out++;
605       tmp++;
606     }
607     data_in += sstride;
608   }
609 }
610
611 static gboolean
612 gst_openjpeg_enc_set_format (GstVideoEncoder * encoder,
613     GstVideoCodecState * state)
614 {
615   GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (encoder);
616   GstCaps *allowed_caps, *caps;
617   GstStructure *s;
618   const gchar *colorspace = NULL;
619   GstJPEG2000Sampling sampling = GST_JPEG2000_SAMPLING_NONE;
620   gint ncomps;
621   gboolean stripe_mode =
622       self->num_stripes != GST_OPENJPEG_ENC_DEFAULT_NUM_STRIPES;
623
624   GST_DEBUG_OBJECT (self, "Setting format: %" GST_PTR_FORMAT, state->caps);
625
626   if (self->input_state)
627     gst_video_codec_state_unref (self->input_state);
628   self->input_state = gst_video_codec_state_ref (state);
629
630   allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
631   allowed_caps = gst_caps_truncate (allowed_caps);
632   s = gst_caps_get_structure (allowed_caps, 0);
633   if (gst_structure_has_name (s, "image/jp2")) {
634     self->codec_format = OPJ_CODEC_JP2;
635     self->is_jp2c = FALSE;
636   } else if (gst_structure_has_name (s, "image/x-j2c")) {
637     self->codec_format = OPJ_CODEC_J2K;
638     self->is_jp2c = TRUE;
639   } else if (gst_structure_has_name (s, "image/x-jpc")) {
640     self->codec_format = OPJ_CODEC_J2K;
641     self->is_jp2c = FALSE;
642   } else {
643     g_return_val_if_reached (FALSE);
644   }
645
646   switch (state->info.finfo->format) {
647     case GST_VIDEO_FORMAT_ARGB64:
648       self->fill_image = fill_image_packed16_4;
649       ncomps = 4;
650       break;
651     case GST_VIDEO_FORMAT_ARGB:
652     case GST_VIDEO_FORMAT_AYUV:
653       self->fill_image = fill_image_packed8_4;
654       ncomps = 4;
655       break;
656     case GST_VIDEO_FORMAT_xRGB:
657       self->fill_image = fill_image_packed8_3;
658       ncomps = 3;
659       break;
660     case GST_VIDEO_FORMAT_AYUV64:
661       self->fill_image = fill_image_packed16_4;
662       ncomps = 4;
663       break;
664     case GST_VIDEO_FORMAT_Y444_10LE:
665     case GST_VIDEO_FORMAT_Y444_10BE:
666     case GST_VIDEO_FORMAT_I422_10LE:
667     case GST_VIDEO_FORMAT_I422_10BE:
668     case GST_VIDEO_FORMAT_I420_10LE:
669     case GST_VIDEO_FORMAT_I420_10BE:
670       self->fill_image = fill_image_planar16_3;
671       ncomps = 3;
672       break;
673     case GST_VIDEO_FORMAT_Y444:
674     case GST_VIDEO_FORMAT_Y42B:
675     case GST_VIDEO_FORMAT_I420:
676     case GST_VIDEO_FORMAT_Y41B:
677     case GST_VIDEO_FORMAT_YUV9:
678       self->fill_image = fill_image_planar8_3;
679       ncomps = 3;
680       break;
681     case GST_VIDEO_FORMAT_GRAY8:
682       self->fill_image = fill_image_planar8_1;
683       ncomps = 1;
684       break;
685     case GST_VIDEO_FORMAT_GRAY16_LE:
686     case GST_VIDEO_FORMAT_GRAY16_BE:
687       self->fill_image = fill_image_planar16_1;
688       ncomps = 1;
689       break;
690     default:
691       g_assert_not_reached ();
692   }
693
694
695   /* sampling */
696   /* note: encoder re-orders channels so that alpha channel is encoded as the last channel */
697   switch (state->info.finfo->format) {
698     case GST_VIDEO_FORMAT_ARGB64:
699     case GST_VIDEO_FORMAT_ARGB:
700       sampling = GST_JPEG2000_SAMPLING_RGBA;
701       break;
702     case GST_VIDEO_FORMAT_AYUV64:
703     case GST_VIDEO_FORMAT_AYUV:
704       sampling = GST_JPEG2000_SAMPLING_YBRA4444_EXT;
705       break;
706     case GST_VIDEO_FORMAT_xRGB:
707       sampling = GST_JPEG2000_SAMPLING_RGB;
708       break;
709     case GST_VIDEO_FORMAT_Y444_10LE:
710     case GST_VIDEO_FORMAT_Y444_10BE:
711     case GST_VIDEO_FORMAT_Y444:
712       sampling = GST_JPEG2000_SAMPLING_YBR444;
713       break;
714
715     case GST_VIDEO_FORMAT_I422_10LE:
716     case GST_VIDEO_FORMAT_I422_10BE:
717     case GST_VIDEO_FORMAT_Y42B:
718       sampling = GST_JPEG2000_SAMPLING_YBR422;
719       break;
720     case GST_VIDEO_FORMAT_YUV9:
721       sampling = GST_JPEG2000_SAMPLING_YBR410;
722       break;
723     case GST_VIDEO_FORMAT_I420_10LE:
724     case GST_VIDEO_FORMAT_I420_10BE:
725     case GST_VIDEO_FORMAT_I420:
726       sampling = GST_JPEG2000_SAMPLING_YBR420;
727       break;
728     case GST_VIDEO_FORMAT_GRAY8:
729     case GST_VIDEO_FORMAT_GRAY16_LE:
730     case GST_VIDEO_FORMAT_GRAY16_BE:
731       sampling = GST_JPEG2000_SAMPLING_GRAYSCALE;
732       break;
733     default:
734       break;
735   }
736
737   if ((state->info.finfo->flags & GST_VIDEO_FORMAT_FLAG_YUV)) {
738     colorspace = "sYUV";
739   } else if ((state->info.finfo->flags & GST_VIDEO_FORMAT_FLAG_RGB)) {
740     colorspace = "sRGB";
741   } else if ((state->info.finfo->flags & GST_VIDEO_FORMAT_FLAG_GRAY)) {
742     colorspace = "GRAY";
743   } else
744     g_return_val_if_reached (FALSE);
745
746   if (sampling != GST_JPEG2000_SAMPLING_NONE) {
747     caps = gst_caps_new_simple (gst_structure_get_name (s),
748         "colorspace", G_TYPE_STRING, colorspace,
749         "sampling", G_TYPE_STRING, gst_jpeg2000_sampling_to_string (sampling),
750         "num-components", G_TYPE_INT, ncomps,
751         "alignment", G_TYPE_STRING,
752         stripe_mode ? "stripe" : "frame",
753         "num-stripes", G_TYPE_INT, self->num_stripes, NULL);
754   } else {
755     caps = gst_caps_new_simple (gst_structure_get_name (s),
756         "colorspace", G_TYPE_STRING, colorspace,
757         "num-components", G_TYPE_INT, ncomps,
758         "alignment", G_TYPE_STRING,
759         stripe_mode ? "stripe" : "frame",
760         "num-stripes", G_TYPE_INT, self->num_stripes, NULL);
761   }
762   gst_caps_unref (allowed_caps);
763
764   if (self->output_state)
765     gst_video_codec_state_unref (self->output_state);
766   self->output_state =
767       gst_video_encoder_set_output_state (encoder, caps, state);
768
769   gst_video_encoder_negotiate (GST_VIDEO_ENCODER (encoder));
770
771   return TRUE;
772 }
773
774 static opj_image_t *
775 gst_openjpeg_enc_fill_image (GstOpenJPEGEnc * self, GstVideoFrame * frame,
776     guint slice_num)
777 {
778   gint i, ncomps, temp, min_height = INT_MAX;
779   opj_image_cmptparm_t *comps;
780   OPJ_COLOR_SPACE colorspace;
781   opj_image_t *image;
782
783   ncomps = GST_VIDEO_FRAME_N_COMPONENTS (frame);
784   comps = g_new0 (opj_image_cmptparm_t, ncomps);
785
786   for (i = 0; i < ncomps; i++) {
787     comps[i].prec = GST_VIDEO_FRAME_COMP_DEPTH (frame, i);
788     comps[i].bpp = GST_VIDEO_FRAME_COMP_DEPTH (frame, i);
789     comps[i].sgnd = 0;
790     comps[i].w = GST_VIDEO_FRAME_COMP_WIDTH (frame, i);
791     comps[i].dx =
792         (guint) ((float) GST_VIDEO_FRAME_WIDTH (frame) /
793         GST_VIDEO_FRAME_COMP_WIDTH (frame, i) + 0.5f);
794     comps[i].dy =
795         (guint) ((float) GST_VIDEO_FRAME_HEIGHT (frame) /
796         GST_VIDEO_FRAME_COMP_HEIGHT (frame, i) + 0.5f);
797     temp =
798         (GST_VIDEO_FRAME_COMP_HEIGHT (frame,
799             i) / self->num_stripes) * comps[i].dy;
800     if (temp < min_height)
801       min_height = temp;
802   }
803
804   for (i = 0; i < ncomps; i++) {
805     gint nominal_height = min_height / comps[i].dy;
806
807     comps[i].h = (slice_num < self->num_stripes - 1) ?
808         nominal_height
809         : GST_VIDEO_FRAME_COMP_HEIGHT (frame,
810         i) - (self->num_stripes - 1) * nominal_height;
811
812   }
813
814   if ((frame->info.finfo->flags & GST_VIDEO_FORMAT_FLAG_YUV))
815     colorspace = OPJ_CLRSPC_SYCC;
816   else if ((frame->info.finfo->flags & GST_VIDEO_FORMAT_FLAG_RGB))
817     colorspace = OPJ_CLRSPC_SRGB;
818   else if ((frame->info.finfo->flags & GST_VIDEO_FORMAT_FLAG_GRAY))
819     colorspace = OPJ_CLRSPC_GRAY;
820   else
821     g_return_val_if_reached (NULL);
822
823   image = opj_image_create (ncomps, comps, colorspace);
824   if (!image) {
825     GST_WARNING_OBJECT (self,
826         "Unable to create a JPEG image. first component height=%d",
827         ncomps ? comps[0].h : 0);
828     return NULL;
829   }
830
831   g_free (comps);
832
833   image->x0 = 0;
834   image->x1 = GST_VIDEO_FRAME_WIDTH (frame);
835   image->y0 = slice_num * min_height;
836   image->y1 =
837       (slice_num <
838       self->num_stripes - 1) ? image->y0 +
839       min_height : GST_VIDEO_FRAME_HEIGHT (frame);
840   self->fill_image (image, frame);
841
842   return image;
843 }
844
845 static void
846 gst_openjpeg_enc_opj_error (const char *msg, void *userdata)
847 {
848   GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (userdata);
849   gchar *trimmed = g_strchomp (g_strdup (msg));
850   GST_TRACE_OBJECT (self, "openjpeg error: %s", trimmed);
851   g_free (trimmed);
852 }
853
854 static void
855 gst_openjpeg_enc_opj_warning (const char *msg, void *userdata)
856 {
857   GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (userdata);
858   gchar *trimmed = g_strchomp (g_strdup (msg));
859   GST_TRACE_OBJECT (self, "openjpeg warning: %s", trimmed);
860   g_free (trimmed);
861 }
862
863 static void
864 gst_openjpeg_enc_opj_info (const char *msg, void *userdata)
865 {
866   GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (userdata);
867   gchar *trimmed = g_strchomp (g_strdup (msg));
868   GST_TRACE_OBJECT (self, "openjpeg info: %s", trimmed);
869   g_free (trimmed);
870 }
871
872 typedef struct
873 {
874   guint8 *data;
875   guint allocsize;
876   guint offset;
877   guint size;
878 } MemStream;
879
880 static OPJ_SIZE_T
881 read_fn (void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data)
882 {
883   g_return_val_if_reached (-1);
884 }
885
886 static OPJ_SIZE_T
887 write_fn (void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data)
888 {
889   MemStream *mstream = p_user_data;
890
891   if (mstream->offset + p_nb_bytes > mstream->allocsize) {
892     while (mstream->offset + p_nb_bytes > mstream->allocsize)
893       mstream->allocsize *= 2;
894     mstream->data = g_realloc (mstream->data, mstream->allocsize);
895   }
896
897   memcpy (mstream->data + mstream->offset, p_buffer, p_nb_bytes);
898
899   if (mstream->offset + p_nb_bytes > mstream->size)
900     mstream->size = mstream->offset + p_nb_bytes;
901   mstream->offset += p_nb_bytes;
902
903   return p_nb_bytes;
904 }
905
906 static OPJ_OFF_T
907 skip_fn (OPJ_OFF_T p_nb_bytes, void *p_user_data)
908 {
909   MemStream *mstream = p_user_data;
910
911   if (mstream->offset + p_nb_bytes > mstream->allocsize) {
912     while (mstream->offset + p_nb_bytes > mstream->allocsize)
913       mstream->allocsize *= 2;
914     mstream->data = g_realloc (mstream->data, mstream->allocsize);
915   }
916
917   if (mstream->offset + p_nb_bytes > mstream->size)
918     mstream->size = mstream->offset + p_nb_bytes;
919
920   mstream->offset += p_nb_bytes;
921
922   return p_nb_bytes;
923 }
924
925 static OPJ_BOOL
926 seek_fn (OPJ_OFF_T p_nb_bytes, void *p_user_data)
927 {
928   MemStream *mstream = p_user_data;
929
930   if (p_nb_bytes > mstream->size)
931     return OPJ_FALSE;
932
933   mstream->offset = p_nb_bytes;
934
935   return OPJ_TRUE;
936 }
937
938 static GstFlowReturn
939 gst_openjpeg_enc_handle_frame (GstVideoEncoder * encoder,
940     GstVideoCodecFrame * frame)
941 {
942   GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (encoder);
943   GstFlowReturn ret = GST_FLOW_OK;
944   opj_codec_t *enc;
945   opj_stream_t *stream;
946   MemStream mstream;
947   opj_image_t *image;
948   GstVideoFrame vframe;
949   guint i;
950   GstCaps *current_caps;
951   GstStructure *s;
952   gboolean stripe_mode =
953       self->num_stripes != GST_OPENJPEG_ENC_DEFAULT_NUM_STRIPES;
954
955   GST_DEBUG_OBJECT (self, "Handling frame");
956
957   current_caps = gst_pad_get_current_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
958   s = gst_caps_get_structure (current_caps, 0);
959
960   if (stripe_mode) {
961     const gchar *str = gst_structure_get_string (s, "alignment");
962     gint min_res;
963
964     if (g_strcmp0 (str, "stripe") != 0) {
965       GST_ERROR_OBJECT (self,
966           "Number of stripes set to %d, but alignment=stripe not supported downstream",
967           self->num_stripes);
968       gst_video_codec_frame_unref (frame);
969       ret = GST_FLOW_NOT_NEGOTIATED;
970       goto done;
971     }
972
973     /* due to limitations in openjpeg library,
974      * number of wavelet resolutions must not exceed floor(log(stripe height)) + 1 */
975     if (!gst_video_frame_map (&vframe, &self->input_state->info,
976             frame->input_buffer, GST_MAP_READ)) {
977       gst_video_codec_frame_unref (frame);
978       GST_ELEMENT_ERROR (self, CORE, FAILED,
979           ("Failed to map input buffer"), (NULL));
980       return GST_FLOW_ERROR;
981     }
982     /* find stripe with least height */
983     min_res =
984         get_stripe_height (self, self->num_stripes - 1,
985         GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 0));
986     min_res = MIN (min_res, get_stripe_height (self, 0,
987             GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 0)));
988     /* take log to find correct number of wavelet resolutions */
989     min_res = min_res > 1 ? (gint) log (min_res) + 1 : 1;
990     self->params.numresolution = MIN (min_res + 1, self->params.numresolution);
991     gst_video_frame_unmap (&vframe);
992   }
993
994
995   for (i = 0; i < self->num_stripes; ++i) {
996     enc = opj_create_compress (self->codec_format);
997     if (!enc)
998       goto initialization_error;
999
1000     if (G_UNLIKELY (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >=
1001             GST_LEVEL_TRACE)) {
1002       opj_set_info_handler (enc, gst_openjpeg_enc_opj_info, self);
1003       opj_set_warning_handler (enc, gst_openjpeg_enc_opj_warning, self);
1004       opj_set_error_handler (enc, gst_openjpeg_enc_opj_error, self);
1005     } else {
1006       opj_set_info_handler (enc, NULL, NULL);
1007       opj_set_warning_handler (enc, NULL, NULL);
1008       opj_set_error_handler (enc, NULL, NULL);
1009     }
1010
1011     if (!gst_video_frame_map (&vframe, &self->input_state->info,
1012             frame->input_buffer, GST_MAP_READ))
1013       goto map_read_error;
1014
1015     image = gst_openjpeg_enc_fill_image (self, &vframe, i);
1016     if (!image)
1017       goto fill_image_error;
1018     gst_video_frame_unmap (&vframe);
1019
1020     if (vframe.info.finfo->flags & GST_VIDEO_FORMAT_FLAG_RGB) {
1021       self->params.tcp_mct = 1;
1022     }
1023     opj_setup_encoder (enc, &self->params, image);
1024     stream = opj_stream_create (4096, OPJ_FALSE);
1025     if (!stream)
1026       goto open_error;
1027
1028     mstream.allocsize = 4096;
1029     mstream.data = g_malloc (mstream.allocsize);
1030     mstream.offset = 0;
1031     mstream.size = 0;
1032
1033     opj_stream_set_read_function (stream, read_fn);
1034     opj_stream_set_write_function (stream, write_fn);
1035     opj_stream_set_skip_function (stream, skip_fn);
1036     opj_stream_set_seek_function (stream, seek_fn);
1037     opj_stream_set_user_data (stream, &mstream, NULL);
1038     opj_stream_set_user_data_length (stream, mstream.size);
1039
1040     if (!opj_start_compress (enc, image, stream))
1041       goto encode_error;
1042
1043     if (!opj_encode (enc, stream))
1044       goto encode_error;
1045
1046     if (!opj_end_compress (enc, stream))
1047       goto encode_error;
1048
1049     opj_image_destroy (image);
1050     opj_stream_destroy (stream);
1051     opj_destroy_codec (enc);
1052
1053     frame->output_buffer = gst_buffer_new ();
1054
1055     if (self->is_jp2c) {
1056       GstMapInfo map;
1057       GstMemory *mem;
1058
1059       mem = gst_allocator_alloc (NULL, 8, NULL);
1060       gst_memory_map (mem, &map, GST_MAP_WRITE);
1061       GST_WRITE_UINT32_BE (map.data, mstream.size + 8);
1062       GST_WRITE_UINT32_BE (map.data + 4, GST_MAKE_FOURCC ('j', 'p', '2', 'c'));
1063       gst_memory_unmap (mem, &map);
1064       gst_buffer_append_memory (frame->output_buffer, mem);
1065     }
1066
1067     gst_buffer_append_memory (frame->output_buffer,
1068         gst_memory_new_wrapped (0, mstream.data, mstream.allocsize, 0,
1069             mstream.size, mstream.data, (GDestroyNotify) g_free));
1070
1071     GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
1072     ret =
1073         (i ==
1074         self->num_stripes -
1075         1) ? gst_video_encoder_finish_frame (encoder,
1076         frame) : gst_video_encoder_finish_subframe (encoder, frame);
1077
1078   }
1079
1080 done:
1081   if (current_caps)
1082     gst_caps_unref (current_caps);
1083   return ret;
1084
1085 initialization_error:
1086   {
1087     gst_video_codec_frame_unref (frame);
1088     GST_ELEMENT_ERROR (self, LIBRARY, INIT,
1089         ("Failed to initialize OpenJPEG encoder"), (NULL));
1090     return GST_FLOW_ERROR;
1091   }
1092 map_read_error:
1093   {
1094     opj_destroy_codec (enc);
1095     gst_video_codec_frame_unref (frame);
1096
1097     GST_ELEMENT_ERROR (self, CORE, FAILED,
1098         ("Failed to map input buffer"), (NULL));
1099     return GST_FLOW_ERROR;
1100   }
1101 fill_image_error:
1102   {
1103     opj_destroy_codec (enc);
1104     gst_video_frame_unmap (&vframe);
1105     gst_video_codec_frame_unref (frame);
1106
1107     GST_ELEMENT_ERROR (self, LIBRARY, INIT,
1108         ("Failed to fill OpenJPEG image"), (NULL));
1109     return GST_FLOW_ERROR;
1110   }
1111 open_error:
1112   {
1113     opj_image_destroy (image);
1114     opj_destroy_codec (enc);
1115     gst_video_codec_frame_unref (frame);
1116
1117     GST_ELEMENT_ERROR (self, LIBRARY, INIT,
1118         ("Failed to open OpenJPEG data"), (NULL));
1119     return GST_FLOW_ERROR;
1120   }
1121 encode_error:
1122   {
1123     opj_stream_destroy (stream);
1124     g_free (mstream.data);
1125     opj_image_destroy (image);
1126     opj_destroy_codec (enc);
1127     gst_video_codec_frame_unref (frame);
1128
1129     GST_ELEMENT_ERROR (self, STREAM, ENCODE,
1130         ("Failed to encode OpenJPEG stream"), (NULL));
1131     return GST_FLOW_ERROR;
1132   }
1133 }
1134
1135 static gboolean
1136 gst_openjpeg_enc_propose_allocation (GstVideoEncoder * encoder,
1137     GstQuery * query)
1138 {
1139   gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
1140
1141   return GST_VIDEO_ENCODER_CLASS (parent_class)->propose_allocation (encoder,
1142       query);
1143 }