diff options
author | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2012-12-14 20:08:27 +0000 |
---|---|---|
committer | Sebastian Dröge <slomo@circular-chaos.org> | 2013-07-29 12:30:22 +0200 |
commit | c7a34979f7d39a7d7a52edc1aa948575ec2eb5df (patch) | |
tree | fcced4072a1bb4966229c0af26313b29d5b97fab | |
parent | ed41e3a14dfbd3fbcdc83cafb76bd6cf0f3cfff5 (diff) | |
download | gstreamer-plugins-bad-c7a34979f7d39a7d7a52edc1aa948575ec2eb5df.tar.gz |
openjpeg: Add JPEG2000 encoder element
-rw-r--r-- | ext/openjpeg/gstopenjpeg.c | 6 | ||||
-rw-r--r-- | ext/openjpeg/gstopenjpegenc.c | 626 | ||||
-rw-r--r-- | ext/openjpeg/gstopenjpegenc.h | 71 |
3 files changed, 699 insertions, 4 deletions
diff --git a/ext/openjpeg/gstopenjpeg.c b/ext/openjpeg/gstopenjpeg.c index 8e699e050..04a970b17 100644 --- a/ext/openjpeg/gstopenjpeg.c +++ b/ext/openjpeg/gstopenjpeg.c @@ -30,14 +30,12 @@ static gboolean plugin_init (GstPlugin * plugin) { - if (!gst_element_register (plugin, "openjpegdec", GST_RANK_MARGINAL, + if (!gst_element_register (plugin, "openjpegdec", GST_RANK_PRIMARY, GST_TYPE_OPENJPEG_DEC)) return FALSE; -#if 0 - if (!gst_element_register (plugin, "openjpegenc", GST_RANK_MARGINAL, + if (!gst_element_register (plugin, "openjpegenc", GST_RANK_PRIMARY, GST_TYPE_OPENJPEG_ENC)) return FALSE; -#endif return TRUE; } diff --git a/ext/openjpeg/gstopenjpegenc.c b/ext/openjpeg/gstopenjpegenc.c index e69de29bb..b17cfbf92 100644 --- a/ext/openjpeg/gstopenjpegenc.c +++ b/ext/openjpeg/gstopenjpegenc.c @@ -0,0 +1,626 @@ +/* + * Copyright (C) 2012 Collabora Ltd. + * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk> + * + * 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. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstopenjpegenc.h" + +GST_DEBUG_CATEGORY_STATIC (gst_openjpeg_enc_debug); +#define GST_CAT_DEFAULT gst_openjpeg_enc_debug + +enum +{ + PROP_0, +}; + +static void gst_openjpeg_enc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_openjpeg_enc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_openjpeg_enc_start (GstVideoEncoder * encoder); +static gboolean gst_openjpeg_enc_stop (GstVideoEncoder * encoder); +static gboolean gst_openjpeg_enc_set_format (GstVideoEncoder * encoder, + GstVideoCodecState * state); +static gboolean gst_openjpeg_enc_reset (GstVideoEncoder * encoder, + gboolean hard); +static GstFlowReturn gst_openjpeg_enc_handle_frame (GstVideoEncoder * encoder, + GstVideoCodecFrame * frame); +static gboolean gst_openjpeg_enc_propose_allocation (GstVideoEncoder * encoder, + GstQuery * query); + +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +#define GRAY16 "GRAY16_LE" +#define YUV10 "Y444_10LE, I422_10LE, I420_10LE" +#else +#define GRAY16 "GRAY16_BE" +#define YUV10 "Y444_10BE, I422_10BE, I420_10BE" +#endif + +static GstStaticPadTemplate gst_openjpeg_enc_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ ARGB64, ARGB, xRGB, " + "AYUV64, " YUV10 ", " + "AYUV, Y444, Y42B, I420, Y41B, YUV9, " "GRAY8, " GRAY16 " }")) + ); + +static GstStaticPadTemplate gst_openjpeg_enc_src_template = + GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("image/x-j2c; image/x-jpc; image/jp2") + ); + +#define parent_class gst_openjpeg_enc_parent_class +G_DEFINE_TYPE (GstOpenJPEGEnc, gst_openjpeg_enc, GST_TYPE_VIDEO_ENCODER); + +static void +gst_openjpeg_enc_class_init (GstOpenJPEGEncClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *element_class; + GstVideoEncoderClass *video_encoder_class; + + gobject_class = (GObjectClass *) klass; + element_class = (GstElementClass *) klass; + video_encoder_class = (GstVideoEncoderClass *) klass; + + gobject_class->set_property = gst_openjpeg_enc_set_property; + gobject_class->get_property = gst_openjpeg_enc_get_property; + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_openjpeg_enc_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_openjpeg_enc_sink_template)); + + gst_element_class_set_static_metadata (element_class, + "OpenJPEG JPEG2000 encoder", + "Codec/Encoder/Video", + "Encode JPEG2000 streams", + "Sebastian Dröge <sebastian.droege@collabora.co.uk>"); + + video_encoder_class->start = GST_DEBUG_FUNCPTR (gst_openjpeg_enc_start); + video_encoder_class->stop = GST_DEBUG_FUNCPTR (gst_openjpeg_enc_stop); + video_encoder_class->reset = GST_DEBUG_FUNCPTR (gst_openjpeg_enc_reset); + video_encoder_class->set_format = + GST_DEBUG_FUNCPTR (gst_openjpeg_enc_set_format); + video_encoder_class->handle_frame = + GST_DEBUG_FUNCPTR (gst_openjpeg_enc_handle_frame); + video_encoder_class->propose_allocation = gst_openjpeg_enc_propose_allocation; + + GST_DEBUG_CATEGORY_INIT (gst_openjpeg_enc_debug, "openjpegenc", 0, + "VP8 Encoder"); +} + +static void +gst_openjpeg_enc_init (GstOpenJPEGEnc * self) +{ + opj_set_default_encoder_parameters (&self->params); + + /* TODO: Add properties for these */ + self->params.cp_fixed_quality = 1; + self->params.tcp_numlayers = 1; +} + +static void +gst_openjpeg_enc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + /* GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (object); */ + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_openjpeg_enc_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + /* GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (object); */ + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +gst_openjpeg_enc_start (GstVideoEncoder * encoder) +{ + GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (encoder); + + GST_DEBUG_OBJECT (self, "Starting"); + + return TRUE; +} + +static gboolean +gst_openjpeg_enc_stop (GstVideoEncoder * video_encoder) +{ + GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (video_encoder); + + GST_DEBUG_OBJECT (self, "Stopping"); + + if (self->output_state) { + gst_video_codec_state_unref (self->output_state); + self->output_state = NULL; + } + + if (self->input_state) { + gst_video_codec_state_unref (self->input_state); + self->input_state = NULL; + } + + GST_DEBUG_OBJECT (self, "Stopped"); + + return TRUE; +} + +static void +fill_image_packed16_4 (opj_image_t * image, GstVideoFrame * frame) +{ + gint x, y, w, h; + guint16 *data; + gint sindex; + + w = GST_VIDEO_FRAME_WIDTH (frame); + h = GST_VIDEO_FRAME_HEIGHT (frame); + data = GST_VIDEO_FRAME_PLANE_DATA (frame, 0); + + sindex = 0; + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++, sindex++) { + image->comps[3].data[sindex] = data[x * 4 + 0]; + image->comps[0].data[sindex] = data[x * 4 + 1]; + image->comps[1].data[sindex] = data[x * 4 + 2]; + image->comps[2].data[sindex] = data[x * 4 + 3]; + } + data += GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0) / 2; + } +} + +static void +fill_image_packed8_4 (opj_image_t * image, GstVideoFrame * frame) +{ + gint x, y, w, h; + guint8 *data; + gint sindex; + + w = GST_VIDEO_FRAME_WIDTH (frame); + h = GST_VIDEO_FRAME_HEIGHT (frame); + data = GST_VIDEO_FRAME_PLANE_DATA (frame, 0); + + sindex = 0; + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++, sindex++) { + image->comps[3].data[sindex] = data[x * 4 + 0]; + image->comps[0].data[sindex] = data[x * 4 + 1]; + image->comps[1].data[sindex] = data[x * 4 + 2]; + image->comps[2].data[sindex] = data[x * 4 + 3]; + } + data += GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0); + } +} + +static void +fill_image_packed8_3 (opj_image_t * image, GstVideoFrame * frame) +{ + gint x, y, w, h; + guint8 *data; + gint sindex; + + w = GST_VIDEO_FRAME_WIDTH (frame); + h = GST_VIDEO_FRAME_HEIGHT (frame); + data = GST_VIDEO_FRAME_PLANE_DATA (frame, 0); + + sindex = 0; + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++, sindex++) { + image->comps[0].data[sindex] = data[x * 4 + 1]; + image->comps[1].data[sindex] = data[x * 4 + 2]; + image->comps[2].data[sindex] = data[x * 4 + 3]; + } + data += GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0); + } +} + +static void +fill_image_planar16_3 (opj_image_t * image, GstVideoFrame * frame) +{ + gint c, x, y, w, h; + guint16 *data; + gint sindex; + + w = GST_VIDEO_FRAME_WIDTH (frame); + h = GST_VIDEO_FRAME_HEIGHT (frame); + data = GST_VIDEO_FRAME_PLANE_DATA (frame, 0); + + for (c = 0; c < 3; c++) { + w = GST_VIDEO_FRAME_COMP_WIDTH (frame, c); + h = GST_VIDEO_FRAME_COMP_HEIGHT (frame, c); + data = (guint16 *) GST_VIDEO_FRAME_COMP_DATA (frame, c); + + sindex = 0; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++, sindex++) { + image->comps[c].data[sindex] = data[x]; + } + data += GST_VIDEO_FRAME_PLANE_STRIDE (frame, c) / 2; + } + } +} + +static void +fill_image_planar8_3 (opj_image_t * image, GstVideoFrame * frame) +{ + gint c, x, y, w, h; + guint8 *data; + gint sindex; + + w = GST_VIDEO_FRAME_WIDTH (frame); + h = GST_VIDEO_FRAME_HEIGHT (frame); + data = GST_VIDEO_FRAME_PLANE_DATA (frame, 0); + + for (c = 0; c < 3; c++) { + w = GST_VIDEO_FRAME_COMP_WIDTH (frame, c); + h = GST_VIDEO_FRAME_COMP_HEIGHT (frame, c); + data = GST_VIDEO_FRAME_COMP_DATA (frame, c); + + sindex = 0; + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++, sindex++) { + image->comps[c].data[sindex] = data[x]; + } + data += GST_VIDEO_FRAME_PLANE_STRIDE (frame, c); + } + } +} + +static void +fill_image_planar8_1 (opj_image_t * image, GstVideoFrame * frame) +{ + gint x, y, w, h; + guint8 *data; + gint sindex; + + w = GST_VIDEO_FRAME_WIDTH (frame); + h = GST_VIDEO_FRAME_HEIGHT (frame); + data = GST_VIDEO_FRAME_PLANE_DATA (frame, 0); + + sindex = 0; + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++, sindex++) { + image->comps[0].data[sindex] = data[x]; + } + data += GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0); + } +} + +static void +fill_image_planar16_1 (opj_image_t * image, GstVideoFrame * frame) +{ + gint x, y, w, h; + guint16 *data; + gint sindex; + + w = GST_VIDEO_FRAME_WIDTH (frame); + h = GST_VIDEO_FRAME_HEIGHT (frame); + data = GST_VIDEO_FRAME_PLANE_DATA (frame, 0); + + sindex = 0; + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++, sindex++) { + image->comps[0].data[sindex] = data[x]; + } + data += GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0) / 2; + } +} + +static gboolean +gst_openjpeg_enc_set_format (GstVideoEncoder * encoder, + GstVideoCodecState * state) +{ + GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (encoder); + GstCaps *allowed_caps, *caps; + GstStructure *s; + + GST_DEBUG_OBJECT (self, "Setting format: %" GST_PTR_FORMAT, state->caps); + + if (self->input_state) + gst_video_codec_state_unref (self->input_state); + self->input_state = gst_video_codec_state_ref (state); + + allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (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->is_jp2c = FALSE; + } else if (gst_structure_has_name (s, "image/x-j2c")) { + self->codec_format = CODEC_J2K; + self->is_jp2c = TRUE; + } else if (gst_structure_has_name (s, "image/x-jpc")) { + self->codec_format = CODEC_J2K; + self->is_jp2c = FALSE; + } else { + g_return_val_if_reached (FALSE); + } + + switch (state->info.finfo->format) { + case GST_VIDEO_FORMAT_ARGB64: + self->fill_image = fill_image_packed16_4; + break; + case GST_VIDEO_FORMAT_ARGB: + self->fill_image = fill_image_packed8_4; + break; + case GST_VIDEO_FORMAT_xRGB: + self->fill_image = fill_image_packed8_3; + break; + case GST_VIDEO_FORMAT_AYUV64: + self->fill_image = fill_image_packed16_4; + break; + case GST_VIDEO_FORMAT_Y444_10LE: + case GST_VIDEO_FORMAT_Y444_10BE: + case GST_VIDEO_FORMAT_I422_10LE: + case GST_VIDEO_FORMAT_I422_10BE: + case GST_VIDEO_FORMAT_I420_10LE: + case GST_VIDEO_FORMAT_I420_10BE: + self->fill_image = fill_image_planar16_3; + break; + case GST_VIDEO_FORMAT_AYUV: + self->fill_image = fill_image_packed8_3; + break; + case GST_VIDEO_FORMAT_Y444: + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_Y41B: + case GST_VIDEO_FORMAT_YUV9: + self->fill_image = fill_image_planar8_3; + break; + case GST_VIDEO_FORMAT_GRAY8: + self->fill_image = fill_image_planar8_1; + break; + case GST_VIDEO_FORMAT_GRAY16_LE: + case GST_VIDEO_FORMAT_GRAY16_BE: + self->fill_image = fill_image_planar16_1; + break; + default: + g_assert_not_reached (); + } + + caps = gst_caps_new_empty_simple (gst_structure_get_name (s)); + gst_caps_unref (allowed_caps); + + if (self->output_state) + gst_video_codec_state_unref (self->output_state); + self->output_state = + gst_video_encoder_set_output_state (encoder, caps, state); + + gst_video_encoder_negotiate (GST_VIDEO_ENCODER (encoder)); + + return TRUE; +} + +static gboolean +gst_openjpeg_enc_reset (GstVideoEncoder * encoder, gboolean hard) +{ + GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (encoder); + + GST_DEBUG_OBJECT (self, "Resetting"); + + if (self->output_state) { + gst_video_codec_state_unref (self->output_state); + self->output_state = NULL; + } + + return TRUE; +} + +static opj_image_t * +gst_openjpeg_enc_fill_image (GstOpenJPEGEnc * self, GstVideoFrame * frame) +{ + gint i, ncomps; + opj_image_cmptparm_t *comps; + OPJ_COLOR_SPACE colorspace; + opj_image_t *image; + + ncomps = GST_VIDEO_FRAME_N_COMPONENTS (frame); + comps = g_new0 (opj_image_cmptparm_t, ncomps); + + for (i = 0; i < ncomps; i++) { + comps[i].prec = GST_VIDEO_FRAME_COMP_DEPTH (frame, i); + comps[i].bpp = GST_VIDEO_FRAME_COMP_DEPTH (frame, i); + comps[i].sgnd = 0; + comps[i].w = GST_VIDEO_FRAME_COMP_WIDTH (frame, i); + comps[i].h = GST_VIDEO_FRAME_COMP_HEIGHT (frame, i); + comps[i].dx = + GST_VIDEO_FRAME_WIDTH (frame) / GST_VIDEO_FRAME_COMP_WIDTH (frame, i); + comps[i].dy = + GST_VIDEO_FRAME_HEIGHT (frame) / GST_VIDEO_FRAME_COMP_HEIGHT (frame, i); + } + + if ((frame->info.finfo->flags & GST_VIDEO_FORMAT_FLAG_YUV)) + colorspace = CLRSPC_SYCC; + else if ((frame->info.finfo->flags & GST_VIDEO_FORMAT_FLAG_RGB)) + colorspace = CLRSPC_SRGB; + else if ((frame->info.finfo->flags & GST_VIDEO_FORMAT_FLAG_GRAY)) + colorspace = CLRSPC_GRAY; + else + g_return_val_if_reached (NULL); + + image = opj_image_create (ncomps, comps, colorspace); + g_free (comps); + + image->x0 = image->y0 = 0; + image->x1 = GST_VIDEO_FRAME_WIDTH (frame); + image->y1 = GST_VIDEO_FRAME_HEIGHT (frame); + + self->fill_image (image, frame); + + return image; +} + +static GstFlowReturn +gst_openjpeg_enc_handle_frame (GstVideoEncoder * encoder, + GstVideoCodecFrame * frame) +{ + GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (encoder); + GstFlowReturn ret = GST_FLOW_OK; + GstMapInfo map; + opj_cinfo_t *enc; + opj_cio_t *io; + opj_image_t *image; + GstVideoFrame vframe; + gint length; + + GST_DEBUG_OBJECT (self, "Handling frame"); + + enc = opj_create_compress (self->codec_format); + if (!enc) + goto initialization_error; + + opj_set_event_mgr ((opj_common_ptr) enc, NULL, NULL); + + if (!gst_video_frame_map (&vframe, &self->input_state->info, + frame->input_buffer, GST_MAP_READ)) + goto map_read_error; + + image = gst_openjpeg_enc_fill_image (self, &vframe); + if (!image) + goto fill_image_error; + gst_video_frame_unmap (&vframe); + + opj_setup_encoder (enc, &self->params, image); + + io = opj_cio_open ((opj_common_ptr) enc, NULL, 0); + if (!io) + goto open_error; + + if (!opj_encode (enc, io, image, NULL)) + goto encode_error; + + opj_image_destroy (image); + + length = cio_tell (io); + + ret = + gst_video_encoder_allocate_output_frame (encoder, frame, + length + (self->is_jp2c ? 8 : 0)); + if (ret != GST_FLOW_OK) + goto allocate_error; + + gst_buffer_fill (frame->output_buffer, self->is_jp2c ? 8 : 0, io->buffer, + length); + if (self->is_jp2c) { + gst_buffer_map (frame->output_buffer, &map, GST_MAP_WRITE); + GST_WRITE_UINT32_BE (map.data, length + 8); + GST_WRITE_UINT32_BE (map.data + 4, GST_MAKE_FOURCC ('j', 'p', '2', 'c')); + gst_buffer_unmap (frame->output_buffer, &map); + } + + opj_cio_close (io); + opj_destroy_compress (enc); + + ret = gst_video_encoder_finish_frame (encoder, frame); + + return ret; + +initialization_error: + { + gst_video_codec_frame_unref (frame); + GST_ELEMENT_ERROR (self, LIBRARY, INIT, + ("Failed to initialize OpenJPEG encoder"), (NULL)); + return GST_FLOW_ERROR; + } +map_read_error: + { + opj_destroy_compress (enc); + gst_video_codec_frame_unref (frame); + + GST_ELEMENT_ERROR (self, CORE, FAILED, + ("Failed to map input buffer"), (NULL)); + return GST_FLOW_ERROR; + } +fill_image_error: + { + opj_destroy_compress (enc); + gst_video_frame_unmap (&vframe); + gst_video_codec_frame_unref (frame); + + GST_ELEMENT_ERROR (self, LIBRARY, INIT, + ("Failed to fill OpenJPEG image"), (NULL)); + return GST_FLOW_ERROR; + } +open_error: + { + opj_image_destroy (image); + opj_destroy_compress (enc); + gst_video_codec_frame_unref (frame); + + GST_ELEMENT_ERROR (self, LIBRARY, INIT, + ("Failed to open OpenJPEG data"), (NULL)); + return GST_FLOW_ERROR; + } +encode_error: + { + opj_cio_close (io); + opj_image_destroy (image); + opj_destroy_compress (enc); + gst_video_codec_frame_unref (frame); + + GST_ELEMENT_ERROR (self, STREAM, ENCODE, + ("Failed to encode OpenJPEG stream"), (NULL)); + return GST_FLOW_ERROR; + } +allocate_error: + { + opj_cio_close (io); + opj_destroy_compress (enc); + gst_video_codec_frame_unref (frame); + + GST_ELEMENT_ERROR (self, CORE, FAILED, + ("Failed to allocate output buffer"), (NULL)); + return ret; + } +} + +static gboolean +gst_openjpeg_enc_propose_allocation (GstVideoEncoder * encoder, + GstQuery * query) +{ + gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); + + return GST_VIDEO_ENCODER_CLASS (parent_class)->propose_allocation (encoder, + query); +} diff --git a/ext/openjpeg/gstopenjpegenc.h b/ext/openjpeg/gstopenjpegenc.h index e69de29bb..d1274b003 100644 --- a/ext/openjpeg/gstopenjpegenc.h +++ b/ext/openjpeg/gstopenjpegenc.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2012 Collabora Ltd. + * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk> + * + * 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_ENC_H__ +#define __GST_OPENJPEG_ENC_H__ + +#include <gst/gst.h> +#include <gst/video/video.h> + +#include <openjpeg.h> + +G_BEGIN_DECLS + +#define GST_TYPE_OPENJPEG_ENC \ + (gst_openjpeg_enc_get_type()) +#define GST_OPENJPEG_ENC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OPENJPEG_ENC,GstOpenJPEGEnc)) +#define GST_OPENJPEG_ENC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OPENJPEG_ENC,GstOpenJPEGEncClass)) +#define GST_IS_OPENJPEG_ENC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OPENJPEG_ENC)) +#define GST_IS_OPENJPEG_ENC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OPENJPEG_ENC)) + +typedef struct _GstOpenJPEGEnc GstOpenJPEGEnc; +typedef struct _GstOpenJPEGEncClass GstOpenJPEGEncClass; + +struct _GstOpenJPEGEnc +{ + GstVideoEncoder parent; + + /* < private > */ + GstVideoCodecState *input_state; + GstVideoCodecState *output_state; + + OPJ_CODEC_FORMAT codec_format; + gboolean is_jp2c; + + void (*fill_image) (opj_image_t * image, GstVideoFrame *frame); + + opj_cparameters_t params; +}; + +struct _GstOpenJPEGEncClass +{ + GstVideoEncoderClass parent_class; +}; + +GType gst_openjpeg_enc_get_type (void); + +G_END_DECLS + +#endif /* __GST_OPENJPEG_ENC_H__ */ |