60b9543322bbbc0d41b880ff1b42d0b4de1cda60
[platform/upstream/gstreamer.git] / ext / openjpeg / gstopenjpegdec.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 "gstopenjpegdec.h"
28
29
30 #include <string.h>
31
32 GST_DEBUG_CATEGORY_STATIC (gst_openjpeg_dec_debug);
33 #define GST_CAT_DEFAULT gst_openjpeg_dec_debug
34
35 static gboolean gst_openjpeg_dec_start (GstVideoDecoder * decoder);
36 static gboolean gst_openjpeg_dec_stop (GstVideoDecoder * decoder);
37 static gboolean gst_openjpeg_dec_set_format (GstVideoDecoder * decoder,
38     GstVideoCodecState * state);
39 static GstFlowReturn gst_openjpeg_dec_handle_frame (GstVideoDecoder * decoder,
40     GstVideoCodecFrame * frame);
41 static gboolean gst_openjpeg_dec_decide_allocation (GstVideoDecoder * decoder,
42     GstQuery * query);
43
44 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
45 #define GRAY16 "GRAY16_LE"
46 #define YUV10 "Y444_10LE, I422_10LE, I420_10LE"
47 #else
48 #define GRAY16 "GRAY16_BE"
49 #define YUV10 "Y444_10BE, I422_10BE, I420_10BE"
50 #endif
51
52 static GstStaticPadTemplate gst_openjpeg_dec_sink_template =
53     GST_STATIC_PAD_TEMPLATE ("sink",
54     GST_PAD_SINK,
55     GST_PAD_ALWAYS,
56     GST_STATIC_CAPS ("image/x-j2c, "
57         GST_JPEG2000_SAMPLING_LIST "; "
58         "image/x-jpc, " GST_JPEG2000_SAMPLING_LIST "; " "image/jp2")
59     );
60
61 static GstStaticPadTemplate gst_openjpeg_dec_src_template =
62 GST_STATIC_PAD_TEMPLATE ("src",
63     GST_PAD_SRC,
64     GST_PAD_ALWAYS,
65     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ ARGB64, ARGB, xRGB, "
66             "AYUV64, " YUV10 ", "
67             "AYUV, Y444, Y42B, I420, Y41B, YUV9, " "GRAY8, " GRAY16 " }"))
68     );
69
70 #define parent_class gst_openjpeg_dec_parent_class
71 G_DEFINE_TYPE (GstOpenJPEGDec, gst_openjpeg_dec, GST_TYPE_VIDEO_DECODER);
72
73 static void
74 gst_openjpeg_dec_class_init (GstOpenJPEGDecClass * klass)
75 {
76   GstElementClass *element_class;
77   GstVideoDecoderClass *video_decoder_class;
78
79   element_class = (GstElementClass *) klass;
80   video_decoder_class = (GstVideoDecoderClass *) klass;
81
82   gst_element_class_add_static_pad_template (element_class,
83       &gst_openjpeg_dec_src_template);
84   gst_element_class_add_static_pad_template (element_class,
85       &gst_openjpeg_dec_sink_template);
86
87   gst_element_class_set_static_metadata (element_class,
88       "OpenJPEG JPEG2000 decoder",
89       "Codec/Decoder/Video",
90       "Decode JPEG2000 streams",
91       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
92
93   video_decoder_class->start = GST_DEBUG_FUNCPTR (gst_openjpeg_dec_start);
94   video_decoder_class->stop = GST_DEBUG_FUNCPTR (gst_openjpeg_dec_stop);
95   video_decoder_class->set_format =
96       GST_DEBUG_FUNCPTR (gst_openjpeg_dec_set_format);
97   video_decoder_class->handle_frame =
98       GST_DEBUG_FUNCPTR (gst_openjpeg_dec_handle_frame);
99   video_decoder_class->decide_allocation = gst_openjpeg_dec_decide_allocation;
100
101   GST_DEBUG_CATEGORY_INIT (gst_openjpeg_dec_debug, "openjpegdec", 0,
102       "OpenJPEG Decoder");
103 }
104
105 static void
106 gst_openjpeg_dec_init (GstOpenJPEGDec * self)
107 {
108   GstVideoDecoder *decoder = (GstVideoDecoder *) self;
109
110   gst_video_decoder_set_packetized (decoder, TRUE);
111   gst_video_decoder_set_needs_format (decoder, TRUE);
112   gst_video_decoder_set_use_default_pad_acceptcaps (GST_VIDEO_DECODER_CAST
113       (self), TRUE);
114   GST_PAD_SET_ACCEPT_TEMPLATE (GST_VIDEO_DECODER_SINK_PAD (self));
115   opj_set_default_decoder_parameters (&self->params);
116 #ifdef HAVE_OPENJPEG_1
117   self->params.cp_limit_decoding = NO_LIMITATION;
118 #endif
119   self->sampling = GST_JPEG2000_SAMPLING_NONE;
120 }
121
122 static gboolean
123 gst_openjpeg_dec_start (GstVideoDecoder * decoder)
124 {
125   GstOpenJPEGDec *self = GST_OPENJPEG_DEC (decoder);
126
127   GST_DEBUG_OBJECT (self, "Starting");
128
129   return TRUE;
130 }
131
132 static gboolean
133 gst_openjpeg_dec_stop (GstVideoDecoder * video_decoder)
134 {
135   GstOpenJPEGDec *self = GST_OPENJPEG_DEC (video_decoder);
136
137   GST_DEBUG_OBJECT (self, "Stopping");
138
139   if (self->output_state) {
140     gst_video_codec_state_unref (self->output_state);
141     self->output_state = NULL;
142   }
143
144   if (self->input_state) {
145     gst_video_codec_state_unref (self->input_state);
146     self->input_state = NULL;
147   }
148
149   GST_DEBUG_OBJECT (self, "Stopped");
150
151   return TRUE;
152 }
153
154 static gboolean
155 gst_openjpeg_dec_set_format (GstVideoDecoder * decoder,
156     GstVideoCodecState * state)
157 {
158   GstOpenJPEGDec *self = GST_OPENJPEG_DEC (decoder);
159   GstStructure *s;
160
161   GST_DEBUG_OBJECT (self, "Setting format: %" GST_PTR_FORMAT, state->caps);
162
163   s = gst_caps_get_structure (state->caps, 0);
164
165   self->color_space = OPJ_CLRSPC_UNKNOWN;
166
167   if (gst_structure_has_name (s, "image/jp2")) {
168     self->codec_format = OPJ_CODEC_JP2;
169     self->is_jp2c = FALSE;
170   } else if (gst_structure_has_name (s, "image/x-j2c")) {
171     self->codec_format = OPJ_CODEC_J2K;
172     self->is_jp2c = TRUE;
173   } else if (gst_structure_has_name (s, "image/x-jpc")) {
174     self->codec_format = OPJ_CODEC_J2K;
175     self->is_jp2c = FALSE;
176   } else {
177     g_return_val_if_reached (FALSE);
178   }
179
180
181   self->sampling =
182       gst_jpeg2000_sampling_from_string (gst_structure_get_string (s,
183           "sampling"));
184   if (gst_jpeg2000_sampling_is_rgb (self->sampling))
185     self->color_space = OPJ_CLRSPC_SRGB;
186   else if (gst_jpeg2000_sampling_is_mono (self->sampling))
187     self->color_space = OPJ_CLRSPC_GRAY;
188   else if (gst_jpeg2000_sampling_is_yuv (self->sampling))
189     self->color_space = OPJ_CLRSPC_SYCC;
190
191   self->ncomps = 0;
192   gst_structure_get_int (s, "num-components", &self->ncomps);
193
194   if (self->input_state)
195     gst_video_codec_state_unref (self->input_state);
196   self->input_state = gst_video_codec_state_ref (state);
197
198   return TRUE;
199 }
200
201 static gboolean
202 reverse_rgb_channels (GstJPEG2000Sampling sampling)
203 {
204   return sampling == GST_JPEG2000_SAMPLING_BGR
205       || sampling == GST_JPEG2000_SAMPLING_BGRA;
206 }
207
208 static void
209 fill_frame_packed8_4 (GstVideoFrame * frame, opj_image_t * image)
210 {
211   gint x, y, w, h, c;
212   guint8 *data_out, *tmp;
213   const gint *data_in[4];
214   gint dstride;
215   gint off[4];
216
217   w = GST_VIDEO_FRAME_WIDTH (frame);
218   h = GST_VIDEO_FRAME_HEIGHT (frame);
219   data_out = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
220   dstride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0);
221
222   for (c = 0; c < 4; c++) {
223     data_in[c] = image->comps[c].data;
224     off[c] = 0x80 * image->comps[c].sgnd;
225   }
226
227   for (y = 0; y < h; y++) {
228     tmp = data_out;
229
230     for (x = 0; x < w; x++) {
231       tmp[0] = off[3] + *data_in[3];
232       tmp[1] = off[0] + *data_in[0];
233       tmp[2] = off[1] + *data_in[1];
234       tmp[3] = off[2] + *data_in[2];
235
236       tmp += 4;
237       data_in[0]++;
238       data_in[1]++;
239       data_in[2]++;
240       data_in[3]++;
241     }
242     data_out += dstride;
243   }
244 }
245
246 static void
247 fill_frame_packed16_4 (GstVideoFrame * frame, opj_image_t * image)
248 {
249   gint x, y, w, h, c;
250   guint16 *data_out, *tmp;
251   const gint *data_in[4];
252   gint dstride;
253   gint shift[4], off[4];
254
255   w = GST_VIDEO_FRAME_WIDTH (frame);
256   h = GST_VIDEO_FRAME_HEIGHT (frame);
257   data_out = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
258   dstride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0) / 2;
259
260   for (c = 0; c < 4; c++) {
261     data_in[c] = image->comps[c].data;
262     off[c] = (1 << (image->comps[c].prec - 1)) * image->comps[c].sgnd;
263     shift[c] =
264         MAX (MIN (GST_VIDEO_FRAME_COMP_DEPTH (frame, c) - image->comps[c].prec,
265             8), 0);
266   }
267
268   for (y = 0; y < h; y++) {
269     tmp = data_out;
270
271     for (x = 0; x < w; x++) {
272       tmp[0] = off[3] + (*data_in[3] << shift[3]);
273       tmp[1] = off[0] + (*data_in[0] << shift[0]);
274       tmp[2] = off[1] + (*data_in[1] << shift[1]);
275       tmp[3] = off[2] + (*data_in[2] << shift[2]);
276
277       tmp += 4;
278       data_in[0]++;
279       data_in[1]++;
280       data_in[2]++;
281       data_in[3]++;
282     }
283     data_out += dstride;
284   }
285 }
286
287 static void
288 fill_frame_packed8_3 (GstVideoFrame * frame, opj_image_t * image)
289 {
290   gint x, y, w, h, c;
291   guint8 *data_out, *tmp;
292   const gint *data_in[3];
293   gint dstride;
294   gint off[3];
295
296   w = GST_VIDEO_FRAME_WIDTH (frame);
297   h = GST_VIDEO_FRAME_HEIGHT (frame);
298   data_out = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
299   dstride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0);
300
301   for (c = 0; c < 3; c++) {
302     data_in[c] = image->comps[c].data;
303     off[c] = 0x80 * image->comps[c].sgnd;
304   };
305
306   for (y = 0; y < h; y++) {
307     tmp = data_out;
308
309     for (x = 0; x < w; x++) {
310       tmp[1] = off[0] + *data_in[0];
311       tmp[2] = off[1] + *data_in[1];
312       tmp[3] = off[2] + *data_in[2];
313
314       tmp += 4;
315       data_in[0]++;
316       data_in[1]++;
317       data_in[2]++;
318     }
319     data_out += dstride;
320   }
321 }
322
323 static void
324 fill_frame_packed16_3 (GstVideoFrame * frame, opj_image_t * image)
325 {
326   gint x, y, w, h, c;
327   guint16 *data_out, *tmp;
328   const gint *data_in[3];
329   gint dstride;
330   gint shift[3], off[3];
331
332   w = GST_VIDEO_FRAME_WIDTH (frame);
333   h = GST_VIDEO_FRAME_HEIGHT (frame);
334   data_out = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
335   dstride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0) / 2;
336
337   for (c = 0; c < 3; c++) {
338     data_in[c] = image->comps[c].data;
339     off[c] = (1 << (image->comps[c].prec - 1)) * image->comps[c].sgnd;
340     shift[c] =
341         MAX (MIN (GST_VIDEO_FRAME_COMP_DEPTH (frame, c) - image->comps[c].prec,
342             8), 0);
343   }
344
345   for (y = 0; y < h; y++) {
346     tmp = data_out;
347
348     for (x = 0; x < w; x++) {
349       tmp[1] = off[0] + (*data_in[0] << shift[0]);
350       tmp[2] = off[1] + (*data_in[1] << shift[1]);
351       tmp[3] = off[2] + (*data_in[2] << shift[2]);
352
353       tmp += 4;
354       data_in[0]++;
355       data_in[1]++;
356       data_in[2]++;
357     }
358     data_out += dstride;
359   }
360 }
361
362 static void
363 fill_frame_planar8_1 (GstVideoFrame * frame, opj_image_t * image)
364 {
365   gint x, y, w, h;
366   guint8 *data_out, *tmp;
367   const gint *data_in;
368   gint dstride;
369   gint off;
370
371   w = GST_VIDEO_FRAME_WIDTH (frame);
372   h = GST_VIDEO_FRAME_HEIGHT (frame);
373   data_out = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
374   dstride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0);
375
376   data_in = image->comps[0].data;
377   off = 0x80 * image->comps[0].sgnd;
378
379   for (y = 0; y < h; y++) {
380     tmp = data_out;
381
382     for (x = 0; x < w; x++) {
383       *tmp = off + *data_in;
384
385       tmp++;
386       data_in++;
387     }
388     data_out += dstride;
389   }
390 }
391
392 static void
393 fill_frame_planar16_1 (GstVideoFrame * frame, opj_image_t * image)
394 {
395   gint x, y, w, h;
396   guint16 *data_out, *tmp;
397   const gint *data_in;
398   gint dstride;
399   gint shift, off;
400
401   w = GST_VIDEO_FRAME_WIDTH (frame);
402   h = GST_VIDEO_FRAME_HEIGHT (frame);
403   data_out = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
404   dstride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0) / 2;
405
406   data_in = image->comps[0].data;
407
408   off = (1 << (image->comps[0].prec - 1)) * image->comps[0].sgnd;
409   shift =
410       MAX (MIN (GST_VIDEO_FRAME_COMP_DEPTH (frame, 0) - image->comps[0].prec,
411           8), 0);
412
413   for (y = 0; y < h; y++) {
414     tmp = data_out;
415
416     for (x = 0; x < w; x++) {
417       *tmp = off + (*data_in << shift);
418
419       tmp++;
420       data_in++;
421     }
422     data_out += dstride;
423   }
424 }
425
426 static void
427 fill_frame_planar8_3 (GstVideoFrame * frame, opj_image_t * image)
428 {
429   gint c, x, y, w, h;
430   guint8 *data_out, *tmp;
431   const gint *data_in;
432   gint dstride, off;
433
434   for (c = 0; c < 3; c++) {
435     w = GST_VIDEO_FRAME_COMP_WIDTH (frame, c);
436     h = GST_VIDEO_FRAME_COMP_HEIGHT (frame, c);
437     dstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, c);
438     data_out = GST_VIDEO_FRAME_COMP_DATA (frame, c);
439     data_in = image->comps[c].data;
440     off = 0x80 * image->comps[c].sgnd;
441
442     for (y = 0; y < h; y++) {
443       tmp = data_out;
444
445       for (x = 0; x < w; x++) {
446         *tmp = off + *data_in;
447         tmp++;
448         data_in++;
449       }
450       data_out += dstride;
451     }
452   }
453 }
454
455 static void
456 fill_frame_planar16_3 (GstVideoFrame * frame, opj_image_t * image)
457 {
458   gint c, x, y, w, h;
459   guint16 *data_out, *tmp;
460   const gint *data_in;
461   gint dstride;
462   gint shift, off;
463
464   for (c = 0; c < 3; c++) {
465     w = GST_VIDEO_FRAME_COMP_WIDTH (frame, c);
466     h = GST_VIDEO_FRAME_COMP_HEIGHT (frame, c);
467     dstride = GST_VIDEO_FRAME_COMP_STRIDE (frame, c) / 2;
468     data_out = (guint16 *) GST_VIDEO_FRAME_COMP_DATA (frame, c);
469     data_in = image->comps[c].data;
470     off = (1 << (image->comps[c].prec - 1)) * image->comps[c].sgnd;
471     shift =
472         MAX (MIN (GST_VIDEO_FRAME_COMP_DEPTH (frame, c) - image->comps[c].prec,
473             8), 0);
474
475     for (y = 0; y < h; y++) {
476       tmp = data_out;
477
478       for (x = 0; x < w; x++) {
479         *tmp = off + (*data_in << shift);
480         tmp++;
481         data_in++;
482       }
483       data_out += dstride;
484     }
485   }
486 }
487
488 static void
489 fill_frame_planar8_3_generic (GstVideoFrame * frame, opj_image_t * image)
490 {
491   gint x, y, w, h, c;
492   guint8 *data_out, *tmp;
493   const gint *data_in[3];
494   gint dstride;
495   gint dx[3], dy[3], off[3];
496
497   w = GST_VIDEO_FRAME_WIDTH (frame);
498   h = GST_VIDEO_FRAME_HEIGHT (frame);
499   data_out = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
500   dstride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0);
501
502   for (c = 0; c < 3; c++) {
503     data_in[c] = image->comps[c].data;
504     dx[c] = image->comps[c].dx;
505     dy[c] = image->comps[c].dy;
506     off[c] = 0x80 * image->comps[c].sgnd;
507   }
508
509   for (y = 0; y < h; y++) {
510     tmp = data_out;
511
512     for (x = 0; x < w; x++) {
513       tmp[0] = 0xff;
514       tmp[1] = off[0] + data_in[0][((y / dy[0]) * w + x) / dx[0]];
515       tmp[2] = off[1] + data_in[1][((y / dy[1]) * w + x) / dx[1]];
516       tmp[3] = off[2] + data_in[2][((y / dy[2]) * w + x) / dx[2]];
517       tmp += 4;
518     }
519     data_out += dstride;
520   }
521 }
522
523 static void
524 fill_frame_planar8_4_generic (GstVideoFrame * frame, opj_image_t * image)
525 {
526   gint x, y, w, h, c;
527   guint8 *data_out, *tmp;
528   const gint *data_in[4];
529   gint dstride;
530   gint dx[4], dy[4], off[4];
531
532   w = GST_VIDEO_FRAME_WIDTH (frame);
533   h = GST_VIDEO_FRAME_HEIGHT (frame);
534   data_out = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
535   dstride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0);
536
537   for (c = 0; c < 4; c++) {
538     data_in[c] = image->comps[c].data;
539     dx[c] = image->comps[c].dx;
540     dy[c] = image->comps[c].dy;
541     off[c] = 0x80 * image->comps[c].sgnd;
542   }
543
544   for (y = 0; y < h; y++) {
545     tmp = data_out;
546
547     for (x = 0; x < w; x++) {
548       tmp[0] = off[3] + data_in[3][((y / dy[3]) * w + x) / dx[3]];
549       tmp[1] = off[0] + data_in[0][((y / dy[0]) * w + x) / dx[0]];
550       tmp[2] = off[1] + data_in[1][((y / dy[1]) * w + x) / dx[1]];
551       tmp[3] = off[2] + data_in[2][((y / dy[2]) * w + x) / dx[2]];
552       tmp += 4;
553     }
554     data_out += dstride;
555   }
556 }
557
558 static void
559 fill_frame_planar16_3_generic (GstVideoFrame * frame, opj_image_t * image)
560 {
561   gint x, y, w, h, c;
562   guint16 *data_out, *tmp;
563   const gint *data_in[3];
564   gint dstride;
565   gint dx[3], dy[3], shift[3], off[3];
566
567   w = GST_VIDEO_FRAME_WIDTH (frame);
568   h = GST_VIDEO_FRAME_HEIGHT (frame);
569   data_out = (guint16 *) GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
570   dstride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0) / 2;
571
572   for (c = 0; c < 3; c++) {
573     dx[c] = image->comps[c].dx;
574     dy[c] = image->comps[c].dy;
575     data_in[c] = image->comps[c].data;
576     off[c] = (1 << (image->comps[c].prec - 1)) * image->comps[c].sgnd;
577     shift[c] =
578         MAX (MIN (GST_VIDEO_FRAME_COMP_DEPTH (frame, c) - image->comps[c].prec,
579             8), 0);
580   }
581
582   for (y = 0; y < h; y++) {
583     tmp = data_out;
584
585     for (x = 0; x < w; x++) {
586       tmp[0] = 0xff;
587       tmp[1] = off[0] + (data_in[0][((y / dy[0]) * w + x) / dx[0]] << shift[0]);
588       tmp[2] = off[1] + (data_in[1][((y / dy[1]) * w + x) / dx[1]] << shift[1]);
589       tmp[3] = off[2] + (data_in[2][((y / dy[2]) * w + x) / dx[2]] << shift[2]);
590       tmp += 4;
591     }
592     data_out += dstride;
593   }
594 }
595
596 static void
597 fill_frame_planar16_4_generic (GstVideoFrame * frame, opj_image_t * image)
598 {
599   gint x, y, w, h, c;
600   guint16 *data_out, *tmp;
601   const gint *data_in[4];
602   gint dstride;
603   gint dx[4], dy[4], shift[4], off[4];
604
605   w = GST_VIDEO_FRAME_WIDTH (frame);
606   h = GST_VIDEO_FRAME_HEIGHT (frame);
607   data_out = (guint16 *) GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
608   dstride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0) / 2;
609
610   for (c = 0; c < 4; c++) {
611     dx[c] = image->comps[c].dx;
612     dy[c] = image->comps[c].dy;
613     data_in[c] = image->comps[c].data;
614     off[c] = (1 << (image->comps[c].prec - 1)) * image->comps[c].sgnd;
615     shift[c] =
616         MAX (MIN (GST_VIDEO_FRAME_COMP_DEPTH (frame, c) - image->comps[c].prec,
617             8), 0);
618   }
619
620   for (y = 0; y < h; y++) {
621     tmp = data_out;
622
623     for (x = 0; x < w; x++) {
624       tmp[0] = off[3] + (data_in[3][((y / dy[3]) * w + x) / dx[3]] << shift[3]);
625       tmp[1] = off[0] + (data_in[0][((y / dy[0]) * w + x) / dx[0]] << shift[0]);
626       tmp[2] = off[1] + (data_in[1][((y / dy[1]) * w + x) / dx[1]] << shift[1]);
627       tmp[3] = off[2] + (data_in[2][((y / dy[2]) * w + x) / dx[2]] << shift[2]);
628       tmp += 4;
629     }
630     data_out += dstride;
631   }
632 }
633
634 static gint
635 get_highest_prec (opj_image_t * image)
636 {
637   gint i;
638   gint ret = 0;
639
640   for (i = 0; i < image->numcomps; i++)
641     ret = MAX (image->comps[i].prec, ret);
642
643   return ret;
644 }
645
646 static GstFlowReturn
647 gst_openjpeg_dec_negotiate (GstOpenJPEGDec * self, opj_image_t * image)
648 {
649   GstVideoFormat format;
650   gint width, height;
651
652   if (image->color_space == OPJ_CLRSPC_UNKNOWN || image->color_space == 0)
653     image->color_space = self->color_space;
654
655   switch (image->color_space) {
656     case OPJ_CLRSPC_SRGB:
657       if (image->numcomps == 4) {
658         if (image->comps[0].dx != 1 || image->comps[0].dy != 1 ||
659             image->comps[1].dx != 1 || image->comps[1].dy != 1 ||
660             image->comps[2].dx != 1 || image->comps[2].dy != 1 ||
661             image->comps[3].dx != 1 || image->comps[3].dy != 1) {
662           GST_ERROR_OBJECT (self, "Sub-sampling for RGB not supported");
663           return GST_FLOW_NOT_NEGOTIATED;
664         }
665
666         if (get_highest_prec (image) == 8) {
667           self->fill_frame = fill_frame_packed8_4;
668           format =
669               reverse_rgb_channels (self->sampling) ? GST_VIDEO_FORMAT_BGRA :
670               GST_VIDEO_FORMAT_RGBA;
671
672         } else if (get_highest_prec (image) <= 16) {
673           self->fill_frame = fill_frame_packed16_4;
674           format = GST_VIDEO_FORMAT_ARGB64;
675         } else {
676           GST_ERROR_OBJECT (self, "Unsupported depth %d", image->comps[3].prec);
677           return GST_FLOW_NOT_NEGOTIATED;
678         }
679       } else if (image->numcomps == 3) {
680         if (image->comps[0].dx != 1 || image->comps[0].dy != 1 ||
681             image->comps[1].dx != 1 || image->comps[1].dy != 1 ||
682             image->comps[2].dx != 1 || image->comps[2].dy != 1) {
683           GST_ERROR_OBJECT (self, "Sub-sampling for RGB not supported");
684           return GST_FLOW_NOT_NEGOTIATED;
685         }
686
687         if (get_highest_prec (image) == 8) {
688           self->fill_frame = fill_frame_packed8_3;
689           format =
690               reverse_rgb_channels (self->sampling) ? GST_VIDEO_FORMAT_BGR :
691               GST_VIDEO_FORMAT_RGB;
692         } else if (get_highest_prec (image) <= 16) {
693           self->fill_frame = fill_frame_packed16_3;
694           format = GST_VIDEO_FORMAT_ARGB64;
695         } else {
696           GST_ERROR_OBJECT (self, "Unsupported depth %d",
697               get_highest_prec (image));
698           return GST_FLOW_NOT_NEGOTIATED;
699         }
700       } else {
701         GST_ERROR_OBJECT (self, "Unsupported number of RGB components: %d",
702             image->numcomps);
703         return GST_FLOW_NOT_NEGOTIATED;
704       }
705       break;
706     case OPJ_CLRSPC_GRAY:
707       if (image->numcomps == 1) {
708         if (image->comps[0].dx != 1 && image->comps[0].dy != 1) {
709           GST_ERROR_OBJECT (self, "Sub-sampling for GRAY not supported");
710           return GST_FLOW_NOT_NEGOTIATED;
711         }
712
713         if (get_highest_prec (image) == 8) {
714           self->fill_frame = fill_frame_planar8_1;
715           format = GST_VIDEO_FORMAT_GRAY8;
716         } else if (get_highest_prec (image) <= 16) {
717           self->fill_frame = fill_frame_planar16_1;
718 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
719           format = GST_VIDEO_FORMAT_GRAY16_LE;
720 #else
721           format = GST_VIDEO_FORMAT_GRAY16_BE;
722 #endif
723         } else {
724           GST_ERROR_OBJECT (self, "Unsupported depth %d",
725               get_highest_prec (image));
726           return GST_FLOW_NOT_NEGOTIATED;
727         }
728       } else {
729         GST_ERROR_OBJECT (self, "Unsupported number of GRAY components: %d",
730             image->numcomps);
731         return GST_FLOW_NOT_NEGOTIATED;
732       }
733       break;
734     case OPJ_CLRSPC_SYCC:
735       if (image->numcomps != 3 && image->numcomps != 4) {
736         GST_ERROR_OBJECT (self, "Unsupported number of YUV components: %d",
737             image->numcomps);
738         return GST_FLOW_NOT_NEGOTIATED;
739       }
740
741       if (image->comps[0].dx != 1 || image->comps[0].dy != 1) {
742         GST_ERROR_OBJECT (self, "Sub-sampling of luma plane not supported");
743         return GST_FLOW_NOT_NEGOTIATED;
744       }
745
746       if (image->comps[1].dx != image->comps[2].dx ||
747           image->comps[1].dy != image->comps[2].dy) {
748         GST_ERROR_OBJECT (self,
749             "Different sub-sampling of chroma planes not supported");
750         return GST_FLOW_ERROR;
751       }
752
753       if (image->numcomps == 4) {
754         if (image->comps[3].dx != 1 || image->comps[3].dy != 1) {
755           GST_ERROR_OBJECT (self, "Sub-sampling of alpha plane not supported");
756           return GST_FLOW_NOT_NEGOTIATED;
757         }
758
759         if (get_highest_prec (image) == 8) {
760           self->fill_frame = fill_frame_planar8_4_generic;
761           format = GST_VIDEO_FORMAT_AYUV;
762         } else if (image->comps[3].prec <= 16) {
763           self->fill_frame = fill_frame_planar16_4_generic;
764           format = GST_VIDEO_FORMAT_AYUV64;
765         } else {
766           GST_ERROR_OBJECT (self, "Unsupported depth %d", image->comps[0].prec);
767           return GST_FLOW_NOT_NEGOTIATED;
768         }
769       } else if (image->numcomps == 3) {
770         if (get_highest_prec (image) == 8) {
771           if (image->comps[1].dx == 1 && image->comps[1].dy == 1) {
772             self->fill_frame = fill_frame_planar8_3;
773             format = GST_VIDEO_FORMAT_Y444;
774           } else if (image->comps[1].dx == 2 && image->comps[1].dy == 1) {
775             self->fill_frame = fill_frame_planar8_3;
776             format = GST_VIDEO_FORMAT_Y42B;
777           } else if (image->comps[1].dx == 2 && image->comps[1].dy == 2) {
778             self->fill_frame = fill_frame_planar8_3;
779             format = GST_VIDEO_FORMAT_I420;
780           } else if (image->comps[1].dx == 4 && image->comps[1].dy == 1) {
781             self->fill_frame = fill_frame_planar8_3;
782             format = GST_VIDEO_FORMAT_Y41B;
783           } else if (image->comps[1].dx == 4 && image->comps[1].dy == 4) {
784             self->fill_frame = fill_frame_planar8_3;
785             format = GST_VIDEO_FORMAT_YUV9;
786           } else {
787             self->fill_frame = fill_frame_planar8_3_generic;
788             format = GST_VIDEO_FORMAT_AYUV;
789           }
790         } else if (get_highest_prec (image) <= 16) {
791           if (image->comps[0].prec == 10 &&
792               image->comps[1].prec == 10 && image->comps[2].prec == 10) {
793             if (image->comps[1].dx == 1 && image->comps[1].dy == 1) {
794               self->fill_frame = fill_frame_planar16_3;
795 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
796               format = GST_VIDEO_FORMAT_Y444_10LE;
797 #else
798               format = GST_VIDEO_FORMAT_Y444_10BE;
799 #endif
800             } else if (image->comps[1].dx == 2 && image->comps[1].dy == 1) {
801               self->fill_frame = fill_frame_planar16_3;
802 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
803               format = GST_VIDEO_FORMAT_I422_10LE;
804 #else
805               format = GST_VIDEO_FORMAT_I422_10BE;
806 #endif
807             } else if (image->comps[1].dx == 2 && image->comps[1].dy == 2) {
808               self->fill_frame = fill_frame_planar16_3;
809 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
810               format = GST_VIDEO_FORMAT_I420_10LE;
811 #else
812               format = GST_VIDEO_FORMAT_I420_10BE;
813 #endif
814             } else {
815               self->fill_frame = fill_frame_planar16_3_generic;
816               format = GST_VIDEO_FORMAT_AYUV64;
817             }
818           } else {
819             self->fill_frame = fill_frame_planar16_3_generic;
820             format = GST_VIDEO_FORMAT_AYUV64;
821           }
822         } else {
823           GST_ERROR_OBJECT (self, "Unsupported depth %d",
824               get_highest_prec (image));
825           return GST_FLOW_NOT_NEGOTIATED;
826         }
827       } else {
828         GST_ERROR_OBJECT (self, "Unsupported number of YUV components: %d",
829             image->numcomps);
830         return GST_FLOW_NOT_NEGOTIATED;
831       }
832       break;
833     default:
834       GST_ERROR_OBJECT (self, "Unsupported colorspace %d", image->color_space);
835       return GST_FLOW_NOT_NEGOTIATED;
836   }
837
838   width = image->x1 - image->x0;
839   height = image->y1 - image->y0;
840
841   if (!self->output_state ||
842       self->output_state->info.finfo->format != format ||
843       self->output_state->info.width != width ||
844       self->output_state->info.height != height) {
845     if (self->output_state)
846       gst_video_codec_state_unref (self->output_state);
847     self->output_state =
848         gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self), format,
849         width, height, self->input_state);
850
851     if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self)))
852       return GST_FLOW_NOT_NEGOTIATED;
853   }
854
855   return GST_FLOW_OK;
856 }
857
858 static void
859 gst_openjpeg_dec_opj_error (const char *msg, void *userdata)
860 {
861   GstOpenJPEGDec *self = GST_OPENJPEG_DEC (userdata);
862   gchar *trimmed = g_strchomp (g_strdup (msg));
863   GST_TRACE_OBJECT (self, "openjpeg error: %s", trimmed);
864   g_free (trimmed);
865 }
866
867 static void
868 gst_openjpeg_dec_opj_warning (const char *msg, void *userdata)
869 {
870   GstOpenJPEGDec *self = GST_OPENJPEG_DEC (userdata);
871   gchar *trimmed = g_strchomp (g_strdup (msg));
872   GST_TRACE_OBJECT (self, "openjpeg warning: %s", trimmed);
873   g_free (trimmed);
874 }
875
876 static void
877 gst_openjpeg_dec_opj_info (const char *msg, void *userdata)
878 {
879   GstOpenJPEGDec *self = GST_OPENJPEG_DEC (userdata);
880   gchar *trimmed = g_strchomp (g_strdup (msg));
881   GST_TRACE_OBJECT (self, "openjpeg info: %s", trimmed);
882   g_free (trimmed);
883 }
884
885 #ifndef HAVE_OPENJPEG_1
886 typedef struct
887 {
888   guint8 *data;
889   guint offset, size;
890 } MemStream;
891
892 static OPJ_SIZE_T
893 read_fn (void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data)
894 {
895   MemStream *mstream = p_user_data;
896   OPJ_SIZE_T read;
897
898   if (mstream->offset == mstream->size)
899     return -1;
900
901   if (mstream->offset + p_nb_bytes > mstream->size)
902     read = mstream->size - mstream->offset;
903   else
904     read = p_nb_bytes;
905
906   memcpy (p_buffer, mstream->data + mstream->offset, read);
907   mstream->offset += read;
908
909   return read;
910 }
911
912 static OPJ_SIZE_T
913 write_fn (void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data)
914 {
915   g_return_val_if_reached (-1);
916 }
917
918 static OPJ_OFF_T
919 skip_fn (OPJ_OFF_T p_nb_bytes, void *p_user_data)
920 {
921   MemStream *mstream = p_user_data;
922   OPJ_OFF_T skip;
923
924   if (mstream->offset + p_nb_bytes > mstream->size)
925     skip = mstream->size - mstream->offset;
926   else
927     skip = p_nb_bytes;
928
929   mstream->offset += skip;
930
931   return skip;
932 }
933
934 static OPJ_BOOL
935 seek_fn (OPJ_OFF_T p_nb_bytes, void *p_user_data)
936 {
937   MemStream *mstream = p_user_data;
938
939   if (p_nb_bytes > mstream->size)
940     return OPJ_FALSE;
941
942   mstream->offset = p_nb_bytes;
943
944   return OPJ_TRUE;
945 }
946 #endif
947
948 static GstFlowReturn
949 gst_openjpeg_dec_handle_frame (GstVideoDecoder * decoder,
950     GstVideoCodecFrame * frame)
951 {
952   GstOpenJPEGDec *self = GST_OPENJPEG_DEC (decoder);
953   GstFlowReturn ret = GST_FLOW_OK;
954   gint64 deadline;
955   GstMapInfo map;
956 #ifdef HAVE_OPENJPEG_1
957   opj_dinfo_t *dec;
958   opj_cio_t *io;
959 #else
960   opj_codec_t *dec;
961   opj_stream_t *stream;
962   MemStream mstream;
963 #endif
964   opj_image_t *image;
965   GstVideoFrame vframe;
966   opj_dparameters_t params;
967
968   GST_DEBUG_OBJECT (self, "Handling frame");
969
970   deadline = gst_video_decoder_get_max_decode_time (decoder, frame);
971   if (deadline < 0) {
972     GST_LOG_OBJECT (self, "Dropping too late frame: deadline %" G_GINT64_FORMAT,
973         deadline);
974     ret = gst_video_decoder_drop_frame (decoder, frame);
975     return ret;
976   }
977
978   dec = opj_create_decompress (self->codec_format);
979   if (!dec)
980     goto initialization_error;
981
982 #ifdef HAVE_OPENJPEG_1
983   if (G_UNLIKELY (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >=
984           GST_LEVEL_TRACE)) {
985     opj_event_mgr_t callbacks;
986
987     callbacks.error_handler = gst_openjpeg_dec_opj_error;
988     callbacks.warning_handler = gst_openjpeg_dec_opj_warning;
989     callbacks.info_handler = gst_openjpeg_dec_opj_info;
990     opj_set_event_mgr ((opj_common_ptr) dec, &callbacks, self);
991   } else {
992     opj_set_event_mgr ((opj_common_ptr) dec, NULL, NULL);
993   }
994 #else
995   if (G_UNLIKELY (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >=
996           GST_LEVEL_TRACE)) {
997     opj_set_info_handler (dec, gst_openjpeg_dec_opj_info, self);
998     opj_set_warning_handler (dec, gst_openjpeg_dec_opj_warning, self);
999     opj_set_error_handler (dec, gst_openjpeg_dec_opj_error, self);
1000   } else {
1001     opj_set_info_handler (dec, NULL, NULL);
1002     opj_set_warning_handler (dec, NULL, NULL);
1003     opj_set_error_handler (dec, NULL, NULL);
1004   }
1005 #endif
1006
1007   params = self->params;
1008   if (self->ncomps)
1009     params.jpwl_exp_comps = self->ncomps;
1010   opj_setup_decoder (dec, &params);
1011
1012   if (!gst_buffer_map (frame->input_buffer, &map, GST_MAP_READ))
1013     goto map_read_error;
1014
1015 #ifdef HAVE_OPENJPEG_1
1016   io = opj_cio_open ((opj_common_ptr) dec, map.data + (self->is_jp2c ? 8 : 0),
1017       map.size - (self->is_jp2c ? 8 : 0));
1018   if (!io)
1019     goto open_error;
1020
1021   image = opj_decode (dec, io);
1022   if (!image)
1023     goto decode_error;
1024 #else
1025   stream = opj_stream_create (4096, OPJ_TRUE);
1026   if (!stream)
1027     goto open_error;
1028
1029   mstream.data = map.data + (self->is_jp2c ? 8 : 0);
1030   mstream.offset = 0;
1031   mstream.size = map.size - (self->is_jp2c ? 8 : 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 #ifdef HAVE_OPENJPEG_2_1
1038   opj_stream_set_user_data (stream, &mstream, NULL);
1039 #else
1040   opj_stream_set_user_data (stream, &mstream);
1041 #endif
1042   opj_stream_set_user_data_length (stream, mstream.size);
1043
1044   image = NULL;
1045   if (!opj_read_header (stream, dec, &image))
1046     goto decode_error;
1047
1048   if (!opj_decode (dec, stream, image))
1049     goto decode_error;
1050 #endif
1051
1052   {
1053     gint i;
1054
1055     for (i = 0; i < image->numcomps; i++) {
1056       if (image->comps[i].data == NULL)
1057         goto decode_error;
1058     }
1059   }
1060
1061   gst_buffer_unmap (frame->input_buffer, &map);
1062
1063   ret = gst_openjpeg_dec_negotiate (self, image);
1064   if (ret != GST_FLOW_OK)
1065     goto negotiate_error;
1066
1067   ret = gst_video_decoder_allocate_output_frame (decoder, frame);
1068   if (ret != GST_FLOW_OK)
1069     goto allocate_error;
1070
1071   if (!gst_video_frame_map (&vframe, &self->output_state->info,
1072           frame->output_buffer, GST_MAP_WRITE))
1073     goto map_write_error;
1074
1075   self->fill_frame (&vframe, image);
1076
1077   gst_video_frame_unmap (&vframe);
1078
1079 #ifdef HAVE_OPENJPEG_1
1080   opj_cio_close (io);
1081   opj_image_destroy (image);
1082   opj_destroy_decompress (dec);
1083 #else
1084   opj_end_decompress (dec, stream);
1085   opj_stream_destroy (stream);
1086   opj_image_destroy (image);
1087   opj_destroy_codec (dec);
1088 #endif
1089
1090   ret = gst_video_decoder_finish_frame (decoder, frame);
1091
1092   return ret;
1093
1094 initialization_error:
1095   {
1096     gst_video_codec_frame_unref (frame);
1097     GST_ELEMENT_ERROR (self, LIBRARY, INIT,
1098         ("Failed to initialize OpenJPEG decoder"), (NULL));
1099     return GST_FLOW_ERROR;
1100   }
1101 map_read_error:
1102   {
1103 #ifdef HAVE_OPENJPEG_1
1104     opj_destroy_decompress (dec);
1105 #else
1106     opj_destroy_codec (dec);
1107 #endif
1108     gst_video_codec_frame_unref (frame);
1109
1110     GST_ELEMENT_ERROR (self, CORE, FAILED,
1111         ("Failed to map input buffer"), (NULL));
1112     return GST_FLOW_ERROR;
1113   }
1114 open_error:
1115   {
1116 #ifdef HAVE_OPENJPEG_1
1117     opj_destroy_decompress (dec);
1118 #else
1119     opj_destroy_codec (dec);
1120 #endif
1121     gst_buffer_unmap (frame->input_buffer, &map);
1122     gst_video_codec_frame_unref (frame);
1123
1124     GST_ELEMENT_ERROR (self, LIBRARY, INIT,
1125         ("Failed to open OpenJPEG stream"), (NULL));
1126     return GST_FLOW_ERROR;
1127   }
1128 decode_error:
1129   {
1130     if (image)
1131       opj_image_destroy (image);
1132 #ifdef HAVE_OPENJPEG_1
1133     opj_cio_close (io);
1134     opj_destroy_decompress (dec);
1135 #else
1136     opj_stream_destroy (stream);
1137     opj_destroy_codec (dec);
1138 #endif
1139     gst_buffer_unmap (frame->input_buffer, &map);
1140     gst_video_codec_frame_unref (frame);
1141
1142     GST_VIDEO_DECODER_ERROR (self, 1, STREAM, DECODE,
1143         ("Failed to decode OpenJPEG stream"), (NULL), ret);
1144     return ret;
1145   }
1146 negotiate_error:
1147   {
1148     opj_image_destroy (image);
1149 #ifdef HAVE_OPENJPEG_1
1150     opj_cio_close (io);
1151     opj_destroy_decompress (dec);
1152 #else
1153     opj_stream_destroy (stream);
1154     opj_destroy_codec (dec);
1155 #endif
1156     gst_video_codec_frame_unref (frame);
1157
1158     GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
1159         ("Failed to negotiate"), (NULL));
1160     return ret;
1161   }
1162 allocate_error:
1163   {
1164     opj_image_destroy (image);
1165 #ifdef HAVE_OPENJPEG_1
1166     opj_cio_close (io);
1167     opj_destroy_decompress (dec);
1168 #else
1169     opj_stream_destroy (stream);
1170     opj_destroy_codec (dec);
1171 #endif
1172     gst_video_codec_frame_unref (frame);
1173
1174     GST_ELEMENT_ERROR (self, CORE, FAILED,
1175         ("Failed to allocate output buffer"), (NULL));
1176     return ret;
1177   }
1178 map_write_error:
1179   {
1180     opj_image_destroy (image);
1181 #ifdef HAVE_OPENJPEG_1
1182     opj_cio_close (io);
1183     opj_destroy_decompress (dec);
1184 #else
1185     opj_stream_destroy (stream);
1186     opj_destroy_codec (dec);
1187 #endif
1188     gst_video_codec_frame_unref (frame);
1189
1190     GST_ELEMENT_ERROR (self, CORE, FAILED,
1191         ("Failed to map output buffer"), (NULL));
1192     return GST_FLOW_ERROR;
1193   }
1194 }
1195
1196 static gboolean
1197 gst_openjpeg_dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query)
1198 {
1199   GstBufferPool *pool;
1200   GstStructure *config;
1201
1202   if (!GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (decoder,
1203           query))
1204     return FALSE;
1205
1206   g_assert (gst_query_get_n_allocation_pools (query) > 0);
1207   gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL);
1208   g_assert (pool != NULL);
1209
1210   config = gst_buffer_pool_get_config (pool);
1211   if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL)) {
1212     gst_buffer_pool_config_add_option (config,
1213         GST_BUFFER_POOL_OPTION_VIDEO_META);
1214   }
1215   gst_buffer_pool_set_config (pool, config);
1216   gst_object_unref (pool);
1217
1218   return TRUE;
1219 }