diff options
author | Sebastian Dröge <slomo@circular-chaos.org> | 2013-10-02 10:55:30 +0200 |
---|---|---|
committer | Sebastian Dröge <slomo@circular-chaos.org> | 2013-10-02 20:07:16 +0200 |
commit | c57be26ed9644713da0ce18e0a78a9594a6d6a30 (patch) | |
tree | 89f4531ca913b011b5f1eba382b32d3305249048 | |
parent | b002490ab24ea6d28eab1d7c6f6af9ec42dece14 (diff) | |
download | gstreamer-plugins-bad-c57be26ed9644713da0ce18e0a78a9594a6d6a30.tar.gz |
openjpeg: Port OpenJPEG plugin to the 2.0 API
-rw-r--r-- | configure.ac | 15 | ||||
-rw-r--r-- | ext/openjpeg/Makefile.am | 3 | ||||
-rw-r--r-- | ext/openjpeg/gstopenjpeg.h | 44 | ||||
-rw-r--r-- | ext/openjpeg/gstopenjpegdec.c | 175 | ||||
-rw-r--r-- | ext/openjpeg/gstopenjpegdec.h | 2 | ||||
-rw-r--r-- | ext/openjpeg/gstopenjpegenc.c | 206 | ||||
-rw-r--r-- | ext/openjpeg/gstopenjpegenc.h | 2 |
7 files changed, 405 insertions, 42 deletions
diff --git a/configure.ac b/configure.ac index e01811857..567e1b38e 100644 --- a/configure.ac +++ b/configure.ac @@ -1761,10 +1761,17 @@ dnl *** OpenJPEG *** translit(dnm, m, l) AM_CONDITIONAL(USE_OPENJPEG, true) AG_GST_CHECK_FEATURE(OPENJPEG, [openjpeg library], openjpeg, [ HAVE_OPENJPEG="no" - PKG_CHECK_MODULES(OPENJPEG, libopenjpeg1, - HAVE_OPENJPEG="yes", - AG_GST_CHECK_LIBHEADER(OPENJPEG, openjpeg, opj_version, , openjpeg.h, OPENJPEG_LIBS="-lopenjpeg") - ) + + AG_GST_CHECK_LIBHEADER(OPENJPEG, openjp2, opj_version, ,openjpeg-2.0/openjpeg.h, OPENJPEG_LIBS="-lopenjp2") + if test x"$HAVE_OPENJPEG" = x"no"; then + PKG_CHECK_MODULES(OPENJPEG, libopenjpeg1, + HAVE_OPENJPEG="yes", + AG_GST_CHECK_LIBHEADER(OPENJPEG, openjpeg, opj_version, , openjpeg.h, OPENJPEG_LIBS="-lopenjpeg") + ) + if test x"$HAVE_OPENJPEG" = x"yes"; then + AC_DEFINE([HAVE_OPENJPEG_1], 1, [Define if OpenJPEG 1 is used]) + fi + fi AC_SUBST(OPENJPEG_CFLAGS) AC_SUBST(OPENJPEG_LIBS) ]) diff --git a/ext/openjpeg/Makefile.am b/ext/openjpeg/Makefile.am index b35dee35b..c3376f177 100644 --- a/ext/openjpeg/Makefile.am +++ b/ext/openjpeg/Makefile.am @@ -11,4 +11,5 @@ libgstopenjpeg_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS) noinst_HEADERS = \ gstopenjpegdec.h \ - gstopenjpegenc.h + gstopenjpegenc.h \ + gstopenjpeg.h diff --git a/ext/openjpeg/gstopenjpeg.h b/ext/openjpeg/gstopenjpeg.h new file mode 100644 index 000000000..ac28ccea9 --- /dev/null +++ b/ext/openjpeg/gstopenjpeg.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2013 Sebastian Dröge <slomo@circular-chaos.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef __GST_OPENJPEG_H__ +#define __GST_OPENJPEG_H__ + +#ifdef HAVE_OPENJPEG_1 +#include <openjpeg.h> +#define OPJ_CLRSPC_UNKNOWN CLRSPC_UNKNOWN +#define OPJ_CLRSPC_SRGB CLRSPC_SRGB +#define OPJ_CLRSPC_GRAY CLRSPC_GRAY +#define OPJ_CLRSPC_SYCC CLRSPC_SYCC + +#define OPJ_CODEC_J2K CODEC_J2K +#define OPJ_CODEC_JP2 CODEC_JP2 + +#define OPJ_LRCP LRCP +#define OPJ_RLCP RLCP +#define OPJ_RPCL RPCL +#define OPJ_PCRL PCRL +#define OPJ_CPRL CPRL +#else +#include <stdio.h> +#include <openjpeg-2.0/openjpeg.h> +#endif + +#endif /* __GST_OPENJPEG_H__ */ diff --git a/ext/openjpeg/gstopenjpegdec.c b/ext/openjpeg/gstopenjpegdec.c index d290e959d..a1c585d4f 100644 --- a/ext/openjpeg/gstopenjpegdec.c +++ b/ext/openjpeg/gstopenjpegdec.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2012 Collabora Ltd. * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk> + * Copyright (C) 2013 Sebastian Dröge <slomo@circular-chaos.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -25,6 +26,8 @@ #include "gstopenjpegdec.h" +#include <string.h> + GST_DEBUG_CATEGORY_STATIC (gst_openjpeg_dec_debug); #define GST_CAT_DEFAULT gst_openjpeg_dec_debug @@ -106,7 +109,9 @@ gst_openjpeg_dec_init (GstOpenJPEGDec * self) gst_video_decoder_set_packetized (decoder, TRUE); opj_set_default_decoder_parameters (&self->params); +#ifdef HAVE_OPENJPEG_1 self->params.cp_limit_decoding = NO_LIMITATION; +#endif } static gboolean @@ -153,16 +158,16 @@ gst_openjpeg_dec_set_format (GstVideoDecoder * decoder, s = gst_caps_get_structure (state->caps, 0); - self->color_space = CLRSPC_UNKNOWN; + self->color_space = OPJ_CLRSPC_UNKNOWN; if (gst_structure_has_name (s, "image/jp2")) { - self->codec_format = CODEC_JP2; + self->codec_format = OPJ_CODEC_JP2; self->is_jp2c = FALSE; } else if (gst_structure_has_name (s, "image/x-j2c")) { - self->codec_format = CODEC_J2K; + self->codec_format = OPJ_CODEC_J2K; self->is_jp2c = TRUE; } else if (gst_structure_has_name (s, "image/x-jpc")) { - self->codec_format = CODEC_J2K; + self->codec_format = OPJ_CODEC_J2K; self->is_jp2c = FALSE; } else { g_return_val_if_reached (FALSE); @@ -170,11 +175,11 @@ gst_openjpeg_dec_set_format (GstVideoDecoder * decoder, if ((color_space = gst_structure_get_string (s, "colorspace"))) { if (g_str_equal (color_space, "sRGB")) - self->color_space = CLRSPC_SRGB; + self->color_space = OPJ_CLRSPC_SRGB; else if (g_str_equal (color_space, "GRAY")) - self->color_space = CLRSPC_GRAY; + self->color_space = OPJ_CLRSPC_GRAY; else if (g_str_equal (color_space, "sYUV")) - self->color_space = CLRSPC_SYCC; + self->color_space = OPJ_CLRSPC_SYCC; } self->ncomps = 0; @@ -650,11 +655,11 @@ gst_openjpeg_dec_negotiate (GstOpenJPEGDec * self, opj_image_t * image) GstVideoFormat format; gint width, height; - if (image->color_space == CLRSPC_UNKNOWN || image->color_space == 0) + if (image->color_space == OPJ_CLRSPC_UNKNOWN || image->color_space == 0) image->color_space = self->color_space; switch (image->color_space) { - case CLRSPC_SRGB: + case OPJ_CLRSPC_SRGB: if (image->numcomps == 4) { if (image->comps[0].dx != 1 || image->comps[0].dy != 1 || image->comps[1].dx != 1 || image->comps[1].dy != 1 || @@ -699,7 +704,7 @@ gst_openjpeg_dec_negotiate (GstOpenJPEGDec * self, opj_image_t * image) return GST_FLOW_NOT_NEGOTIATED; } break; - case CLRSPC_GRAY: + case OPJ_CLRSPC_GRAY: if (image->numcomps == 1) { if (image->comps[0].dx != 1 && image->comps[0].dy != 1) { GST_ERROR_OBJECT (self, "Sub-sampling for GRAY not supported"); @@ -727,7 +732,7 @@ gst_openjpeg_dec_negotiate (GstOpenJPEGDec * self, opj_image_t * image) return GST_FLOW_NOT_NEGOTIATED; } break; - case CLRSPC_SYCC: + case OPJ_CLRSPC_SYCC: if (image->numcomps != 3 && image->numcomps != 4) { GST_ERROR_OBJECT (self, "Unsupported number of YUV components: %d", image->numcomps); @@ -878,6 +883,69 @@ gst_openjpeg_dec_opj_info (const char *msg, void *userdata) g_free (trimmed); } +#ifndef HAVE_OPENJPEG_1 +typedef struct +{ + guint8 *data; + guint offset, size; +} MemStream; + +static OPJ_SIZE_T +read_fn (void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) +{ + MemStream *mstream = p_user_data; + OPJ_SIZE_T read; + + if (mstream->offset == mstream->size) + return -1; + + if (mstream->offset + p_nb_bytes > mstream->size) + read = mstream->size - mstream->offset; + else + read = p_nb_bytes; + + memcpy (p_buffer, mstream->data + mstream->offset, read); + mstream->offset += read; + + return read; +} + +static OPJ_SIZE_T +write_fn (void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) +{ + g_return_val_if_reached (-1); +} + +static OPJ_OFF_T +skip_fn (OPJ_OFF_T p_nb_bytes, void *p_user_data) +{ + MemStream *mstream = p_user_data; + OPJ_OFF_T skip; + + if (mstream->offset + p_nb_bytes > mstream->size) + skip = mstream->size - mstream->offset; + else + skip = p_nb_bytes; + + mstream->offset += skip; + + return skip; +} + +static OPJ_BOOL +seek_fn (OPJ_OFF_T p_nb_bytes, void *p_user_data) +{ + MemStream *mstream = p_user_data; + + if (p_nb_bytes > mstream->size) + return OPJ_FALSE; + + mstream->offset = p_nb_bytes; + + return OPJ_TRUE; +} +#endif + static GstFlowReturn gst_openjpeg_dec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame) @@ -886,9 +954,14 @@ gst_openjpeg_dec_handle_frame (GstVideoDecoder * decoder, GstFlowReturn ret = GST_FLOW_OK; gint64 deadline; GstMapInfo map; +#ifdef HAVE_OPENJPEG_1 opj_dinfo_t *dec; - opj_event_mgr_t callbacks; opj_cio_t *io; +#else + opj_codec_t *dec; + opj_stream_t *stream; + MemStream mstream; +#endif opj_image_t *image; GstVideoFrame vframe; opj_dparameters_t params; @@ -907,8 +980,11 @@ gst_openjpeg_dec_handle_frame (GstVideoDecoder * decoder, if (!dec) goto initialization_error; +#ifdef HAVE_OPENJPEG_1 if (G_UNLIKELY (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= GST_LEVEL_TRACE)) { + opj_event_mgr_t callbacks; + callbacks.error_handler = gst_openjpeg_dec_opj_error; callbacks.warning_handler = gst_openjpeg_dec_opj_warning; callbacks.info_handler = gst_openjpeg_dec_opj_info; @@ -916,6 +992,18 @@ gst_openjpeg_dec_handle_frame (GstVideoDecoder * decoder, } else { opj_set_event_mgr ((opj_common_ptr) dec, NULL, NULL); } +#else + if (G_UNLIKELY (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= + GST_LEVEL_TRACE)) { + opj_set_info_handler (dec, gst_openjpeg_dec_opj_info, self); + opj_set_warning_handler (dec, gst_openjpeg_dec_opj_warning, self); + opj_set_error_handler (dec, gst_openjpeg_dec_opj_error, self); + } else { + opj_set_info_handler (dec, NULL, NULL); + opj_set_warning_handler (dec, NULL, NULL); + opj_set_error_handler (dec, NULL, NULL); + } +#endif params = self->params; if (self->ncomps) @@ -925,6 +1013,7 @@ gst_openjpeg_dec_handle_frame (GstVideoDecoder * decoder, if (!gst_buffer_map (frame->input_buffer, &map, GST_MAP_READ)) goto map_read_error; +#ifdef HAVE_OPENJPEG_1 io = opj_cio_open ((opj_common_ptr) dec, map.data + (self->is_jp2c ? 8 : 0), map.size - (self->is_jp2c ? 8 : 0)); if (!io) @@ -933,6 +1022,29 @@ gst_openjpeg_dec_handle_frame (GstVideoDecoder * decoder, image = opj_decode (dec, io); if (!image) goto decode_error; +#else + stream = opj_stream_create (4096, OPJ_TRUE); + if (!stream) + goto open_error; + + mstream.data = map.data + (self->is_jp2c ? 8 : 0); + mstream.offset = 0; + mstream.size = map.size - (self->is_jp2c ? 8 : 0); + + opj_stream_set_read_function (stream, read_fn); + opj_stream_set_write_function (stream, write_fn); + opj_stream_set_skip_function (stream, skip_fn); + opj_stream_set_seek_function (stream, seek_fn); + opj_stream_set_user_data (stream, &mstream); + opj_stream_set_user_data_length (stream, mstream.size); + + image = NULL; + if (!opj_read_header (stream, dec, &image)) + goto decode_error; + + if (!opj_decode (dec, stream, image)) + goto decode_error; +#endif gst_buffer_unmap (frame->input_buffer, &map); @@ -952,9 +1064,16 @@ gst_openjpeg_dec_handle_frame (GstVideoDecoder * decoder, gst_video_frame_unmap (&vframe); - opj_image_destroy (image); +#ifdef HAVE_OPENJPEG_1 opj_cio_close (io); + opj_image_destroy (image); opj_destroy_decompress (dec); +#else + opj_end_decompress (dec, stream); + opj_stream_destroy (stream); + opj_image_destroy (image); + opj_destroy_codec (dec); +#endif ret = gst_video_decoder_finish_frame (decoder, frame); @@ -969,7 +1088,11 @@ initialization_error: } map_read_error: { +#ifdef HAVE_OPENJPEG_1 opj_destroy_decompress (dec); +#else + opj_destroy_codec (dec); +#endif gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, CORE, FAILED, @@ -978,7 +1101,11 @@ map_read_error: } open_error: { +#ifdef HAVE_OPENJPEG_1 opj_destroy_decompress (dec); +#else + opj_destroy_codec (dec); +#endif gst_buffer_unmap (frame->input_buffer, &map); gst_video_codec_frame_unref (frame); @@ -988,8 +1115,15 @@ open_error: } decode_error: { + if (image) + opj_image_destroy (image); +#ifdef HAVE_OPENJPEG_1 opj_cio_close (io); opj_destroy_decompress (dec); +#else + opj_stream_destroy (stream); + opj_destroy_codec (dec); +#endif gst_buffer_unmap (frame->input_buffer, &map); gst_video_codec_frame_unref (frame); @@ -1000,8 +1134,13 @@ decode_error: negotiate_error: { opj_image_destroy (image); +#ifdef HAVE_OPENJPEG_1 opj_cio_close (io); opj_destroy_decompress (dec); +#else + opj_stream_destroy (stream); + opj_destroy_codec (dec); +#endif gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, CORE, NEGOTIATION, @@ -1011,8 +1150,13 @@ negotiate_error: allocate_error: { opj_image_destroy (image); +#ifdef HAVE_OPENJPEG_1 opj_cio_close (io); opj_destroy_decompress (dec); +#else + opj_stream_destroy (stream); + opj_destroy_codec (dec); +#endif gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, CORE, FAILED, @@ -1022,8 +1166,13 @@ allocate_error: map_write_error: { opj_image_destroy (image); +#ifdef HAVE_OPENJPEG_1 opj_cio_close (io); opj_destroy_decompress (dec); +#else + opj_stream_destroy (stream); + opj_destroy_codec (dec); +#endif gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, CORE, FAILED, diff --git a/ext/openjpeg/gstopenjpegdec.h b/ext/openjpeg/gstopenjpegdec.h index c4a7cd942..0e6e6af1e 100644 --- a/ext/openjpeg/gstopenjpegdec.h +++ b/ext/openjpeg/gstopenjpegdec.h @@ -25,7 +25,7 @@ #include <gst/gst.h> #include <gst/video/video.h> -#include <openjpeg.h> +#include "gstopenjpeg.h" G_BEGIN_DECLS diff --git a/ext/openjpeg/gstopenjpegenc.c b/ext/openjpeg/gstopenjpegenc.c index 325bea06d..7a1943acc 100644 --- a/ext/openjpeg/gstopenjpegenc.c +++ b/ext/openjpeg/gstopenjpegenc.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2012 Collabora Ltd. * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk> + * Copyright (C) 2013 Sebastian Dröge <slomo@circular-chaos.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -25,6 +26,8 @@ #include "gstopenjpegenc.h" +#include <string.h> + GST_DEBUG_CATEGORY_STATIC (gst_openjpeg_enc_debug); #define GST_CAT_DEFAULT gst_openjpeg_enc_debug @@ -33,11 +36,11 @@ static GType gst_openjpeg_enc_progression_order_get_type (void) { static const GEnumValue values[] = { - {LRCP, "LRCP", "lrcp"}, - {RLCP, "RLCP", "rlcp"}, - {RPCL, "RPCL", "rpcl"}, - {PCRL, "PCRL", "pcrl"}, - {CPRL, "CPRL", "crpl"}, + {OPJ_LRCP, "LRCP", "lrcp"}, + {OPJ_RLCP, "RLCP", "rlcp"}, + {OPJ_RPCL, "RPCL", "rpcl"}, + {OPJ_PCRL, "PCRL", "pcrl"}, + {OPJ_CPRL, "CPRL", "crpl"}, {0, NULL, NULL} }; static volatile GType id = 0; @@ -67,7 +70,7 @@ enum #define DEFAULT_NUM_LAYERS 1 #define DEFAULT_NUM_RESOLUTIONS 6 -#define DEFAULT_PROGRESSION_ORDER LRCP +#define DEFAULT_PROGRESSION_ORDER OPJ_LRCP #define DEFAULT_TILE_OFFSET_X 0 #define DEFAULT_TILE_OFFSET_Y 0 #define DEFAULT_TILE_WIDTH 0 @@ -531,7 +534,7 @@ fill_image_planar16_1 (opj_image_t * image, GstVideoFrame * frame) w = GST_VIDEO_FRAME_COMP_WIDTH (frame, 0); h = GST_VIDEO_FRAME_COMP_HEIGHT (frame, 0); data_in = (guint16 *) GST_VIDEO_FRAME_COMP_DATA (frame, 0); - sstride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0); + sstride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0) / 2; data_out = image->comps[0].data; for (y = 0; y < h; y++) { @@ -565,13 +568,13 @@ gst_openjpeg_enc_set_format (GstVideoEncoder * encoder, allowed_caps = gst_caps_truncate (allowed_caps); s = gst_caps_get_structure (allowed_caps, 0); if (gst_structure_has_name (s, "image/jp2")) { - self->codec_format = CODEC_JP2; + self->codec_format = OPJ_CODEC_JP2; self->is_jp2c = FALSE; } else if (gst_structure_has_name (s, "image/x-j2c")) { - self->codec_format = CODEC_J2K; + self->codec_format = OPJ_CODEC_J2K; self->is_jp2c = TRUE; } else if (gst_structure_has_name (s, "image/x-jpc")) { - self->codec_format = CODEC_J2K; + self->codec_format = OPJ_CODEC_J2K; self->is_jp2c = FALSE; } else { g_return_val_if_reached (FALSE); @@ -676,11 +679,11 @@ gst_openjpeg_enc_fill_image (GstOpenJPEGEnc * self, GstVideoFrame * frame) } if ((frame->info.finfo->flags & GST_VIDEO_FORMAT_FLAG_YUV)) - colorspace = CLRSPC_SYCC; + colorspace = OPJ_CLRSPC_SYCC; else if ((frame->info.finfo->flags & GST_VIDEO_FORMAT_FLAG_RGB)) - colorspace = CLRSPC_SRGB; + colorspace = OPJ_CLRSPC_SRGB; else if ((frame->info.finfo->flags & GST_VIDEO_FORMAT_FLAG_GRAY)) - colorspace = CLRSPC_GRAY; + colorspace = OPJ_CLRSPC_GRAY; else g_return_val_if_reached (NULL); @@ -697,7 +700,7 @@ gst_openjpeg_enc_fill_image (GstOpenJPEGEnc * self, GstVideoFrame * frame) } static void -gst_openjpeg_dec_opj_error (const char *msg, void *userdata) +gst_openjpeg_enc_opj_error (const char *msg, void *userdata) { GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (userdata); gchar *trimmed = g_strchomp (g_strdup (msg)); @@ -706,7 +709,7 @@ gst_openjpeg_dec_opj_error (const char *msg, void *userdata) } static void -gst_openjpeg_dec_opj_warning (const char *msg, void *userdata) +gst_openjpeg_enc_opj_warning (const char *msg, void *userdata) { GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (userdata); gchar *trimmed = g_strchomp (g_strdup (msg)); @@ -715,7 +718,7 @@ gst_openjpeg_dec_opj_warning (const char *msg, void *userdata) } static void -gst_openjpeg_dec_opj_info (const char *msg, void *userdata) +gst_openjpeg_enc_opj_info (const char *msg, void *userdata) { GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (userdata); gchar *trimmed = g_strchomp (g_strdup (msg)); @@ -723,19 +726,93 @@ gst_openjpeg_dec_opj_info (const char *msg, void *userdata) g_free (trimmed); } + +#ifndef HAVE_OPENJPEG_1 +typedef struct +{ + guint8 *data; + guint allocsize; + guint offset; + guint size; +} MemStream; + +static OPJ_SIZE_T +read_fn (void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) +{ + g_return_val_if_reached (-1); +} + +static OPJ_SIZE_T +write_fn (void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) +{ + MemStream *mstream = p_user_data; + + if (mstream->offset + p_nb_bytes > mstream->allocsize) { + while (mstream->offset + p_nb_bytes > mstream->allocsize) + mstream->allocsize *= 2; + mstream->data = g_realloc (mstream->data, mstream->allocsize); + } + + memcpy (mstream->data + mstream->offset, p_buffer, p_nb_bytes); + + if (mstream->offset + p_nb_bytes > mstream->size) + mstream->size = mstream->offset + p_nb_bytes; + mstream->offset += p_nb_bytes; + + return p_nb_bytes; +} + +static OPJ_OFF_T +skip_fn (OPJ_OFF_T p_nb_bytes, void *p_user_data) +{ + MemStream *mstream = p_user_data; + + if (mstream->offset + p_nb_bytes > mstream->allocsize) { + while (mstream->offset + p_nb_bytes > mstream->allocsize) + mstream->allocsize *= 2; + mstream->data = g_realloc (mstream->data, mstream->allocsize); + } + + if (mstream->offset + p_nb_bytes > mstream->size) + mstream->size = mstream->offset + p_nb_bytes; + + mstream->offset += p_nb_bytes; + + return p_nb_bytes; +} + +static OPJ_BOOL +seek_fn (OPJ_OFF_T p_nb_bytes, void *p_user_data) +{ + MemStream *mstream = p_user_data; + + if (p_nb_bytes > mstream->size) + return OPJ_FALSE; + + mstream->offset = p_nb_bytes; + + return OPJ_TRUE; +} +#endif + static GstFlowReturn gst_openjpeg_enc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame) { GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (encoder); GstFlowReturn ret = GST_FLOW_OK; - GstMapInfo map; +#ifdef HAVE_OPENJPEG_1 opj_cinfo_t *enc; - opj_event_mgr_t callbacks; + GstMapInfo map; + guint length; opj_cio_t *io; +#else + opj_codec_t *enc; + opj_stream_t *stream; + MemStream mstream; +#endif opj_image_t *image; GstVideoFrame vframe; - gint length; GST_DEBUG_OBJECT (self, "Handling frame"); @@ -743,15 +820,30 @@ gst_openjpeg_enc_handle_frame (GstVideoEncoder * encoder, if (!enc) goto initialization_error; +#ifdef HAVE_OPENJPEG_1 if (G_UNLIKELY (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= GST_LEVEL_TRACE)) { - callbacks.error_handler = gst_openjpeg_dec_opj_error; - callbacks.warning_handler = gst_openjpeg_dec_opj_warning; - callbacks.info_handler = gst_openjpeg_dec_opj_info; + opj_event_mgr_t callbacks; + + callbacks.error_handler = gst_openjpeg_enc_opj_error; + callbacks.warning_handler = gst_openjpeg_enc_opj_warning; + callbacks.info_handler = gst_openjpeg_enc_opj_info; opj_set_event_mgr ((opj_common_ptr) enc, &callbacks, self); } else { opj_set_event_mgr ((opj_common_ptr) enc, NULL, NULL); } +#else + if (G_UNLIKELY (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= + GST_LEVEL_TRACE)) { + opj_set_info_handler (enc, gst_openjpeg_enc_opj_info, self); + opj_set_warning_handler (enc, gst_openjpeg_enc_opj_warning, self); + opj_set_error_handler (enc, gst_openjpeg_enc_opj_error, self); + } else { + opj_set_info_handler (enc, NULL, NULL); + opj_set_warning_handler (enc, NULL, NULL); + opj_set_error_handler (enc, NULL, NULL); + } +#endif if (!gst_video_frame_map (&vframe, &self->input_state->info, frame->input_buffer, GST_MAP_READ)) @@ -764,6 +856,7 @@ gst_openjpeg_enc_handle_frame (GstVideoEncoder * encoder, opj_setup_encoder (enc, &self->params, image); +#ifdef HAVE_OPENJPEG_1 io = opj_cio_open ((opj_common_ptr) enc, NULL, 0); if (!io) goto open_error; @@ -792,6 +885,54 @@ gst_openjpeg_enc_handle_frame (GstVideoEncoder * encoder, opj_cio_close (io); opj_destroy_compress (enc); +#else + stream = opj_stream_create (4096, OPJ_FALSE); + if (!stream) + goto open_error; + + mstream.allocsize = 4096; + mstream.data = g_malloc (mstream.allocsize); + mstream.offset = 0; + mstream.size = 0; + + opj_stream_set_read_function (stream, read_fn); + opj_stream_set_write_function (stream, write_fn); + opj_stream_set_skip_function (stream, skip_fn); + opj_stream_set_seek_function (stream, seek_fn); + opj_stream_set_user_data (stream, &mstream); + opj_stream_set_user_data_length (stream, mstream.size); + + if (!opj_start_compress (enc, image, stream)) + goto encode_error; + + if (!opj_encode (enc, stream)) + goto encode_error; + + if (!opj_end_compress (enc, stream)) + goto encode_error; + + opj_image_destroy (image); + opj_stream_destroy (stream); + opj_destroy_codec (enc); + + frame->output_buffer = gst_buffer_new (); + + if (self->is_jp2c) { + GstMapInfo map; + GstMemory *mem; + + mem = gst_allocator_alloc (NULL, 8, NULL); + gst_memory_map (mem, &map, GST_MAP_WRITE); + GST_WRITE_UINT32_BE (map.data, mstream.size + 8); + GST_WRITE_UINT32_BE (map.data + 4, GST_MAKE_FOURCC ('j', 'p', '2', 'c')); + gst_memory_unmap (mem, &map); + gst_buffer_append_memory (frame->output_buffer, mem); + } + + gst_buffer_append_memory (frame->output_buffer, + gst_memory_new_wrapped (0, mstream.data, mstream.allocsize, 0, + mstream.size, NULL, (GDestroyNotify) g_free)); +#endif ret = gst_video_encoder_finish_frame (encoder, frame); @@ -806,7 +947,11 @@ initialization_error: } map_read_error: { +#ifdef HAVE_OPENJPEG_1 opj_destroy_compress (enc); +#else + opj_destroy_codec (enc); +#endif gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, CORE, FAILED, @@ -815,7 +960,11 @@ map_read_error: } fill_image_error: { +#ifdef HAVE_OPENJPEG_1 opj_destroy_compress (enc); +#else + opj_destroy_codec (enc); +#endif gst_video_frame_unmap (&vframe); gst_video_codec_frame_unref (frame); @@ -826,7 +975,11 @@ fill_image_error: open_error: { opj_image_destroy (image); +#ifdef HAVE_OPENJPEG_1 opj_destroy_compress (enc); +#else + opj_destroy_codec (enc); +#endif gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, LIBRARY, INIT, @@ -835,15 +988,23 @@ open_error: } encode_error: { +#ifdef HAVE_OPENJPEG_1 opj_cio_close (io); opj_image_destroy (image); opj_destroy_compress (enc); +#else + opj_stream_destroy (stream); + g_free (mstream.data); + opj_image_destroy (image); + opj_destroy_codec (enc); +#endif gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, STREAM, ENCODE, ("Failed to encode OpenJPEG stream"), (NULL)); return GST_FLOW_ERROR; } +#ifdef HAVE_OPENJPEG_1 allocate_error: { opj_cio_close (io); @@ -854,6 +1015,7 @@ allocate_error: ("Failed to allocate output buffer"), (NULL)); return ret; } +#endif } static gboolean diff --git a/ext/openjpeg/gstopenjpegenc.h b/ext/openjpeg/gstopenjpegenc.h index d1274b003..97e465a59 100644 --- a/ext/openjpeg/gstopenjpegenc.h +++ b/ext/openjpeg/gstopenjpegenc.h @@ -25,7 +25,7 @@ #include <gst/gst.h> #include <gst/video/video.h> -#include <openjpeg.h> +#include "gstopenjpeg.h" G_BEGIN_DECLS |