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>
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.
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.
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.
27 #include "gstopenjpegdec.h"
32 GST_DEBUG_CATEGORY_STATIC (gst_openjpeg_dec_debug);
33 #define GST_CAT_DEFAULT gst_openjpeg_dec_debug
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,
44 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
45 #define GRAY16 "GRAY16_LE"
46 #define YUV10 "Y444_10LE, I422_10LE, I420_10LE"
48 #define GRAY16 "GRAY16_BE"
49 #define YUV10 "Y444_10BE, I422_10BE, I420_10BE"
52 static GstStaticPadTemplate gst_openjpeg_dec_sink_template =
53 GST_STATIC_PAD_TEMPLATE ("sink",
56 GST_STATIC_CAPS ("image/x-j2c, "
57 GST_JPEG2000_SAMPLING_LIST "; "
58 "image/x-jpc, " GST_JPEG2000_SAMPLING_LIST "; " "image/jp2")
61 static GstStaticPadTemplate gst_openjpeg_dec_src_template =
62 GST_STATIC_PAD_TEMPLATE ("src",
65 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ ARGB64, ARGB, xRGB, "
67 "AYUV, Y444, Y42B, I420, Y41B, YUV9, " "GRAY8, " GRAY16 " }"))
70 #define parent_class gst_openjpeg_dec_parent_class
71 G_DEFINE_TYPE (GstOpenJPEGDec, gst_openjpeg_dec, GST_TYPE_VIDEO_DECODER);
74 gst_openjpeg_dec_class_init (GstOpenJPEGDecClass * klass)
76 GstElementClass *element_class;
77 GstVideoDecoderClass *video_decoder_class;
79 element_class = (GstElementClass *) klass;
80 video_decoder_class = (GstVideoDecoderClass *) klass;
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);
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>");
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;
101 GST_DEBUG_CATEGORY_INIT (gst_openjpeg_dec_debug, "openjpegdec", 0,
106 gst_openjpeg_dec_init (GstOpenJPEGDec * self)
108 GstVideoDecoder *decoder = (GstVideoDecoder *) self;
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
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;
119 self->sampling = GST_JPEG2000_SAMPLING_NONE;
123 gst_openjpeg_dec_start (GstVideoDecoder * decoder)
125 GstOpenJPEGDec *self = GST_OPENJPEG_DEC (decoder);
127 GST_DEBUG_OBJECT (self, "Starting");
133 gst_openjpeg_dec_stop (GstVideoDecoder * video_decoder)
135 GstOpenJPEGDec *self = GST_OPENJPEG_DEC (video_decoder);
137 GST_DEBUG_OBJECT (self, "Stopping");
139 if (self->output_state) {
140 gst_video_codec_state_unref (self->output_state);
141 self->output_state = NULL;
144 if (self->input_state) {
145 gst_video_codec_state_unref (self->input_state);
146 self->input_state = NULL;
149 GST_DEBUG_OBJECT (self, "Stopped");
155 gst_openjpeg_dec_set_format (GstVideoDecoder * decoder,
156 GstVideoCodecState * state)
158 GstOpenJPEGDec *self = GST_OPENJPEG_DEC (decoder);
161 GST_DEBUG_OBJECT (self, "Setting format: %" GST_PTR_FORMAT, state->caps);
163 s = gst_caps_get_structure (state->caps, 0);
165 self->color_space = OPJ_CLRSPC_UNKNOWN;
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;
177 g_return_val_if_reached (FALSE);
182 gst_jpeg2000_sampling_from_string (gst_structure_get_string (s,
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;
192 gst_structure_get_int (s, "num-components", &self->ncomps);
194 if (self->input_state)
195 gst_video_codec_state_unref (self->input_state);
196 self->input_state = gst_video_codec_state_ref (state);
202 reverse_rgb_channels (GstJPEG2000Sampling sampling)
204 return sampling == GST_JPEG2000_SAMPLING_BGR
205 || sampling == GST_JPEG2000_SAMPLING_BGRA;
209 fill_frame_packed8_4 (GstVideoFrame * frame, opj_image_t * image)
212 guint8 *data_out, *tmp;
213 const gint *data_in[4];
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);
222 for (c = 0; c < 4; c++) {
223 data_in[c] = image->comps[c].data;
224 off[c] = 0x80 * image->comps[c].sgnd;
227 for (y = 0; y < h; y++) {
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];
247 fill_frame_packed16_4 (GstVideoFrame * frame, opj_image_t * image)
250 guint16 *data_out, *tmp;
251 const gint *data_in[4];
253 gint shift[4], off[4];
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;
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;
264 MAX (MIN (GST_VIDEO_FRAME_COMP_DEPTH (frame, c) - image->comps[c].prec,
268 for (y = 0; y < h; y++) {
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]);
288 fill_frame_packed8_3 (GstVideoFrame * frame, opj_image_t * image)
291 guint8 *data_out, *tmp;
292 const gint *data_in[3];
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);
301 for (c = 0; c < 3; c++) {
302 data_in[c] = image->comps[c].data;
303 off[c] = 0x80 * image->comps[c].sgnd;
306 for (y = 0; y < h; y++) {
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];
324 fill_frame_packed16_3 (GstVideoFrame * frame, opj_image_t * image)
327 guint16 *data_out, *tmp;
328 const gint *data_in[3];
330 gint shift[3], off[3];
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;
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;
341 MAX (MIN (GST_VIDEO_FRAME_COMP_DEPTH (frame, c) - image->comps[c].prec,
345 for (y = 0; y < h; y++) {
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]);
363 fill_frame_planar8_1 (GstVideoFrame * frame, opj_image_t * image)
366 guint8 *data_out, *tmp;
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);
376 data_in = image->comps[0].data;
377 off = 0x80 * image->comps[0].sgnd;
379 for (y = 0; y < h; y++) {
382 for (x = 0; x < w; x++) {
383 *tmp = off + *data_in;
393 fill_frame_planar16_1 (GstVideoFrame * frame, opj_image_t * image)
396 guint16 *data_out, *tmp;
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;
406 data_in = image->comps[0].data;
408 off = (1 << (image->comps[0].prec - 1)) * image->comps[0].sgnd;
410 MAX (MIN (GST_VIDEO_FRAME_COMP_DEPTH (frame, 0) - image->comps[0].prec,
413 for (y = 0; y < h; y++) {
416 for (x = 0; x < w; x++) {
417 *tmp = off + (*data_in << shift);
427 fill_frame_planar8_3 (GstVideoFrame * frame, opj_image_t * image)
430 guint8 *data_out, *tmp;
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;
442 for (y = 0; y < h; y++) {
445 for (x = 0; x < w; x++) {
446 *tmp = off + *data_in;
456 fill_frame_planar16_3 (GstVideoFrame * frame, opj_image_t * image)
459 guint16 *data_out, *tmp;
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;
472 MAX (MIN (GST_VIDEO_FRAME_COMP_DEPTH (frame, c) - image->comps[c].prec,
475 for (y = 0; y < h; y++) {
478 for (x = 0; x < w; x++) {
479 *tmp = off + (*data_in << shift);
489 fill_frame_planar8_3_generic (GstVideoFrame * frame, opj_image_t * image)
492 guint8 *data_out, *tmp;
493 const gint *data_in[3];
495 gint dx[3], dy[3], off[3];
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);
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;
509 for (y = 0; y < h; y++) {
512 for (x = 0; x < w; x++) {
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]];
524 fill_frame_planar8_4_generic (GstVideoFrame * frame, opj_image_t * image)
527 guint8 *data_out, *tmp;
528 const gint *data_in[4];
530 gint dx[4], dy[4], off[4];
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);
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;
544 for (y = 0; y < h; y++) {
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]];
559 fill_frame_planar16_3_generic (GstVideoFrame * frame, opj_image_t * image)
562 guint16 *data_out, *tmp;
563 const gint *data_in[3];
565 gint dx[3], dy[3], shift[3], off[3];
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;
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;
578 MAX (MIN (GST_VIDEO_FRAME_COMP_DEPTH (frame, c) - image->comps[c].prec,
582 for (y = 0; y < h; y++) {
585 for (x = 0; x < w; x++) {
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]);
597 fill_frame_planar16_4_generic (GstVideoFrame * frame, opj_image_t * image)
600 guint16 *data_out, *tmp;
601 const gint *data_in[4];
603 gint dx[4], dy[4], shift[4], off[4];
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;
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;
616 MAX (MIN (GST_VIDEO_FRAME_COMP_DEPTH (frame, c) - image->comps[c].prec,
620 for (y = 0; y < h; y++) {
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]);
635 get_highest_prec (opj_image_t * image)
640 for (i = 0; i < image->numcomps; i++)
641 ret = MAX (image->comps[i].prec, ret);
647 gst_openjpeg_dec_negotiate (GstOpenJPEGDec * self, opj_image_t * image)
649 GstVideoFormat format;
652 if (image->color_space == OPJ_CLRSPC_UNKNOWN || image->color_space == 0)
653 image->color_space = self->color_space;
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;
666 if (get_highest_prec (image) == 8) {
667 self->fill_frame = fill_frame_packed8_4;
669 reverse_rgb_channels (self->sampling) ? GST_VIDEO_FORMAT_BGRA :
670 GST_VIDEO_FORMAT_RGBA;
672 } else if (get_highest_prec (image) <= 16) {
673 self->fill_frame = fill_frame_packed16_4;
674 format = GST_VIDEO_FORMAT_ARGB64;
676 GST_ERROR_OBJECT (self, "Unsupported depth %d", image->comps[3].prec);
677 return GST_FLOW_NOT_NEGOTIATED;
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;
687 if (get_highest_prec (image) == 8) {
688 self->fill_frame = fill_frame_packed8_3;
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;
696 GST_ERROR_OBJECT (self, "Unsupported depth %d",
697 get_highest_prec (image));
698 return GST_FLOW_NOT_NEGOTIATED;
701 GST_ERROR_OBJECT (self, "Unsupported number of RGB components: %d",
703 return GST_FLOW_NOT_NEGOTIATED;
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;
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;
721 format = GST_VIDEO_FORMAT_GRAY16_BE;
724 GST_ERROR_OBJECT (self, "Unsupported depth %d",
725 get_highest_prec (image));
726 return GST_FLOW_NOT_NEGOTIATED;
729 GST_ERROR_OBJECT (self, "Unsupported number of GRAY components: %d",
731 return GST_FLOW_NOT_NEGOTIATED;
734 case OPJ_CLRSPC_SYCC:
735 if (image->numcomps != 3 && image->numcomps != 4) {
736 GST_ERROR_OBJECT (self, "Unsupported number of YUV components: %d",
738 return GST_FLOW_NOT_NEGOTIATED;
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;
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;
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;
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;
766 GST_ERROR_OBJECT (self, "Unsupported depth %d", image->comps[0].prec);
767 return GST_FLOW_NOT_NEGOTIATED;
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;
787 self->fill_frame = fill_frame_planar8_3_generic;
788 format = GST_VIDEO_FORMAT_AYUV;
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;
798 format = GST_VIDEO_FORMAT_Y444_10BE;
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;
805 format = GST_VIDEO_FORMAT_I422_10BE;
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;
812 format = GST_VIDEO_FORMAT_I420_10BE;
815 self->fill_frame = fill_frame_planar16_3_generic;
816 format = GST_VIDEO_FORMAT_AYUV64;
819 self->fill_frame = fill_frame_planar16_3_generic;
820 format = GST_VIDEO_FORMAT_AYUV64;
823 GST_ERROR_OBJECT (self, "Unsupported depth %d",
824 get_highest_prec (image));
825 return GST_FLOW_NOT_NEGOTIATED;
828 GST_ERROR_OBJECT (self, "Unsupported number of YUV components: %d",
830 return GST_FLOW_NOT_NEGOTIATED;
834 GST_ERROR_OBJECT (self, "Unsupported colorspace %d", image->color_space);
835 return GST_FLOW_NOT_NEGOTIATED;
838 width = image->x1 - image->x0;
839 height = image->y1 - image->y0;
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);
848 gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self), format,
849 width, height, self->input_state);
851 if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self)))
852 return GST_FLOW_NOT_NEGOTIATED;
859 gst_openjpeg_dec_opj_error (const char *msg, void *userdata)
861 GstOpenJPEGDec *self = GST_OPENJPEG_DEC (userdata);
862 gchar *trimmed = g_strchomp (g_strdup (msg));
863 GST_TRACE_OBJECT (self, "openjpeg error: %s", trimmed);
868 gst_openjpeg_dec_opj_warning (const char *msg, void *userdata)
870 GstOpenJPEGDec *self = GST_OPENJPEG_DEC (userdata);
871 gchar *trimmed = g_strchomp (g_strdup (msg));
872 GST_TRACE_OBJECT (self, "openjpeg warning: %s", trimmed);
877 gst_openjpeg_dec_opj_info (const char *msg, void *userdata)
879 GstOpenJPEGDec *self = GST_OPENJPEG_DEC (userdata);
880 gchar *trimmed = g_strchomp (g_strdup (msg));
881 GST_TRACE_OBJECT (self, "openjpeg info: %s", trimmed);
885 #ifndef HAVE_OPENJPEG_1
893 read_fn (void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data)
895 MemStream *mstream = p_user_data;
898 if (mstream->offset == mstream->size)
901 if (mstream->offset + p_nb_bytes > mstream->size)
902 read = mstream->size - mstream->offset;
906 memcpy (p_buffer, mstream->data + mstream->offset, read);
907 mstream->offset += read;
913 write_fn (void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data)
915 g_return_val_if_reached (-1);
919 skip_fn (OPJ_OFF_T p_nb_bytes, void *p_user_data)
921 MemStream *mstream = p_user_data;
924 if (mstream->offset + p_nb_bytes > mstream->size)
925 skip = mstream->size - mstream->offset;
929 mstream->offset += skip;
935 seek_fn (OPJ_OFF_T p_nb_bytes, void *p_user_data)
937 MemStream *mstream = p_user_data;
939 if (p_nb_bytes > mstream->size)
942 mstream->offset = p_nb_bytes;
949 gst_openjpeg_dec_handle_frame (GstVideoDecoder * decoder,
950 GstVideoCodecFrame * frame)
952 GstOpenJPEGDec *self = GST_OPENJPEG_DEC (decoder);
953 GstFlowReturn ret = GST_FLOW_OK;
956 #ifdef HAVE_OPENJPEG_1
961 opj_stream_t *stream;
965 GstVideoFrame vframe;
966 opj_dparameters_t params;
968 GST_DEBUG_OBJECT (self, "Handling frame");
970 deadline = gst_video_decoder_get_max_decode_time (decoder, frame);
972 GST_LOG_OBJECT (self, "Dropping too late frame: deadline %" G_GINT64_FORMAT,
974 ret = gst_video_decoder_drop_frame (decoder, frame);
978 dec = opj_create_decompress (self->codec_format);
980 goto initialization_error;
982 #ifdef HAVE_OPENJPEG_1
983 if (G_UNLIKELY (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >=
985 opj_event_mgr_t callbacks;
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);
992 opj_set_event_mgr ((opj_common_ptr) dec, NULL, NULL);
995 if (G_UNLIKELY (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >=
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);
1001 opj_set_info_handler (dec, NULL, NULL);
1002 opj_set_warning_handler (dec, NULL, NULL);
1003 opj_set_error_handler (dec, NULL, NULL);
1007 params = self->params;
1009 params.jpwl_exp_comps = self->ncomps;
1010 opj_setup_decoder (dec, ¶ms);
1012 if (!gst_buffer_map (frame->input_buffer, &map, GST_MAP_READ))
1013 goto map_read_error;
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));
1021 image = opj_decode (dec, io);
1025 stream = opj_stream_create (4096, OPJ_TRUE);
1029 mstream.data = map.data + (self->is_jp2c ? 8 : 0);
1031 mstream.size = map.size - (self->is_jp2c ? 8 : 0);
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);
1040 opj_stream_set_user_data (stream, &mstream);
1042 opj_stream_set_user_data_length (stream, mstream.size);
1045 if (!opj_read_header (stream, dec, &image))
1048 if (!opj_decode (dec, stream, image))
1055 for (i = 0; i < image->numcomps; i++) {
1056 if (image->comps[i].data == NULL)
1061 gst_buffer_unmap (frame->input_buffer, &map);
1063 ret = gst_openjpeg_dec_negotiate (self, image);
1064 if (ret != GST_FLOW_OK)
1065 goto negotiate_error;
1067 ret = gst_video_decoder_allocate_output_frame (decoder, frame);
1068 if (ret != GST_FLOW_OK)
1069 goto allocate_error;
1071 if (!gst_video_frame_map (&vframe, &self->output_state->info,
1072 frame->output_buffer, GST_MAP_WRITE))
1073 goto map_write_error;
1075 self->fill_frame (&vframe, image);
1077 gst_video_frame_unmap (&vframe);
1079 #ifdef HAVE_OPENJPEG_1
1081 opj_image_destroy (image);
1082 opj_destroy_decompress (dec);
1084 opj_end_decompress (dec, stream);
1085 opj_stream_destroy (stream);
1086 opj_image_destroy (image);
1087 opj_destroy_codec (dec);
1090 ret = gst_video_decoder_finish_frame (decoder, frame);
1094 initialization_error:
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;
1103 #ifdef HAVE_OPENJPEG_1
1104 opj_destroy_decompress (dec);
1106 opj_destroy_codec (dec);
1108 gst_video_codec_frame_unref (frame);
1110 GST_ELEMENT_ERROR (self, CORE, FAILED,
1111 ("Failed to map input buffer"), (NULL));
1112 return GST_FLOW_ERROR;
1116 #ifdef HAVE_OPENJPEG_1
1117 opj_destroy_decompress (dec);
1119 opj_destroy_codec (dec);
1121 gst_buffer_unmap (frame->input_buffer, &map);
1122 gst_video_codec_frame_unref (frame);
1124 GST_ELEMENT_ERROR (self, LIBRARY, INIT,
1125 ("Failed to open OpenJPEG stream"), (NULL));
1126 return GST_FLOW_ERROR;
1131 opj_image_destroy (image);
1132 #ifdef HAVE_OPENJPEG_1
1134 opj_destroy_decompress (dec);
1136 opj_stream_destroy (stream);
1137 opj_destroy_codec (dec);
1139 gst_buffer_unmap (frame->input_buffer, &map);
1140 gst_video_codec_frame_unref (frame);
1142 GST_VIDEO_DECODER_ERROR (self, 1, STREAM, DECODE,
1143 ("Failed to decode OpenJPEG stream"), (NULL), ret);
1148 opj_image_destroy (image);
1149 #ifdef HAVE_OPENJPEG_1
1151 opj_destroy_decompress (dec);
1153 opj_stream_destroy (stream);
1154 opj_destroy_codec (dec);
1156 gst_video_codec_frame_unref (frame);
1158 GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
1159 ("Failed to negotiate"), (NULL));
1164 opj_image_destroy (image);
1165 #ifdef HAVE_OPENJPEG_1
1167 opj_destroy_decompress (dec);
1169 opj_stream_destroy (stream);
1170 opj_destroy_codec (dec);
1172 gst_video_codec_frame_unref (frame);
1174 GST_ELEMENT_ERROR (self, CORE, FAILED,
1175 ("Failed to allocate output buffer"), (NULL));
1180 opj_image_destroy (image);
1181 #ifdef HAVE_OPENJPEG_1
1183 opj_destroy_decompress (dec);
1185 opj_stream_destroy (stream);
1186 opj_destroy_codec (dec);
1188 gst_video_codec_frame_unref (frame);
1190 GST_ELEMENT_ERROR (self, CORE, FAILED,
1191 ("Failed to map output buffer"), (NULL));
1192 return GST_FLOW_ERROR;
1197 gst_openjpeg_dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query)
1199 GstBufferPool *pool;
1200 GstStructure *config;
1202 if (!GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (decoder,
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);
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);
1215 gst_buffer_pool_set_config (pool, config);
1216 gst_object_unref (pool);