static void gst_jpegenc_resync (GstJpegEnc * jpegenc) { gint width, height; gint i, j; GST_DEBUG_OBJECT (jpegenc, "resync"); jpegenc->cinfo.image_width = width = jpegenc->width; jpegenc->cinfo.image_height = height = jpegenc->height; jpegenc->cinfo.input_components = jpegenc->channels; GST_DEBUG_OBJECT (jpegenc, "width %d, height %d", width, height); GST_DEBUG_OBJECT (jpegenc, "format %d", jpegenc->format); if (gst_video_format_is_rgb (jpegenc->format)) { GST_DEBUG_OBJECT (jpegenc, "RGB"); jpegenc->cinfo.in_color_space = JCS_RGB; } else if (gst_video_format_is_gray (jpegenc->format)) { GST_DEBUG_OBJECT (jpegenc, "gray"); jpegenc->cinfo.in_color_space = JCS_GRAYSCALE; } else { GST_DEBUG_OBJECT (jpegenc, "YUV"); jpegenc->cinfo.in_color_space = JCS_YCbCr; } /* input buffer size as max output */ jpegenc->bufsize = gst_video_format_get_size (jpegenc->format, width, height); jpeg_set_defaults (&jpegenc->cinfo); jpegenc->cinfo.raw_data_in = TRUE; /* duh, libjpeg maps RGB to YUV ... and don't expect some conversion */ if (jpegenc->cinfo.in_color_space == JCS_RGB) jpeg_set_colorspace (&jpegenc->cinfo, JCS_RGB); GST_DEBUG_OBJECT (jpegenc, "h_max_samp=%d, v_max_samp=%d", jpegenc->h_max_samp, jpegenc->v_max_samp); /* image dimension info */ for (i = 0; i < jpegenc->channels; i++) { GST_DEBUG_OBJECT (jpegenc, "comp %i: h_samp=%d, v_samp=%d", i, jpegenc->h_samp[i], jpegenc->v_samp[i]); jpegenc->cinfo.comp_info[i].h_samp_factor = jpegenc->h_samp[i]; jpegenc->cinfo.comp_info[i].v_samp_factor = jpegenc->v_samp[i]; jpegenc->line[i] = g_realloc (jpegenc->line[i], jpegenc->v_max_samp * DCTSIZE * sizeof (char *)); if (!jpegenc->planar) { for (j = 0; j < jpegenc->v_max_samp * DCTSIZE; j++) { jpegenc->row[i][j] = g_realloc (jpegenc->row[i][j], width); jpegenc->line[i][j] = jpegenc->row[i][j]; } } } /* guard against a potential error in gst_jpegenc_term_destination which occurs iff bufsize % 4 < free_space_remaining */ jpegenc->bufsize = GST_ROUND_UP_4 (jpegenc->bufsize); jpeg_suppress_tables (&jpegenc->cinfo, TRUE); GST_DEBUG_OBJECT (jpegenc, "resync done"); }
static gboolean gst_jasper_enc_init_encoder (GstJasperEnc * enc) { jas_image_cmptparm_t param[GST_JASPER_ENC_MAX_COMPONENT]; gint i; switch (enc->mode) { case GST_JP2ENC_MODE_J2C: case GST_JP2ENC_MODE_JPC: enc->fmt = jas_image_strtofmt ((char *) "jpc"); break; case GST_JP2ENC_MODE_JP2: enc->fmt = jas_image_strtofmt ((char *) "jp2"); break; } if (gst_video_format_is_rgb (enc->format)) enc->clrspc = JAS_CLRSPC_SRGB; else enc->clrspc = JAS_CLRSPC_SYCBCR; if (enc->buf) { g_free (enc->buf); enc->buf = NULL; } enc->buf = g_new0 (glong, enc->width); if (enc->image) { jas_image_destroy (enc->image); enc->image = NULL; } for (i = 0; i < enc->channels; ++i) { param[i].tlx = 0; param[i].tly = 0; param[i].prec = 8; param[i].sgnd = 0; param[i].height = enc->cheight[i]; param[i].width = enc->cwidth[i]; param[i].hstep = enc->height / param[i].height; param[i].vstep = enc->width / param[i].width; } if (!(enc->image = jas_image_create (enc->channels, param, enc->clrspc))) return FALSE; return TRUE; }
static gboolean gst_jasper_enc_set_src_caps (GstJasperEnc * enc) { GstCaps *caps; guint32 fourcc; gboolean ret; GstCaps *peercaps; peercaps = gst_pad_peer_get_caps (enc->srcpad); if (peercaps) { guint i, n; n = gst_caps_get_size (peercaps); for (i = 0; i < n; i++) { GstStructure *s = gst_caps_get_structure (peercaps, i); const gchar *name = gst_structure_get_name (s); if (!strcmp (name, "image/x-j2c")) { enc->mode = GST_JP2ENC_MODE_J2C; break; } else if (!strcmp (name, "image/x-jpc")) { enc->mode = GST_JP2ENC_MODE_JPC; break; } else if (!strcmp (name, "image/jp2")) { enc->mode = GST_JP2ENC_MODE_JP2; break; } } gst_caps_unref (peercaps); } /* enumerated colourspace */ if (gst_video_format_is_rgb (enc->format)) { fourcc = GST_MAKE_FOURCC ('s', 'R', 'G', 'B'); } else { fourcc = GST_MAKE_FOURCC ('s', 'Y', 'U', 'V'); } switch (enc->mode) { case GST_JP2ENC_MODE_J2C: caps = gst_caps_new_simple ("image/x-j2c", "width", G_TYPE_INT, enc->width, "height", G_TYPE_INT, enc->height, "fourcc", GST_TYPE_FOURCC, fourcc, NULL); break; case GST_JP2ENC_MODE_JPC: caps = gst_caps_new_simple ("image/x-jpc", "width", G_TYPE_INT, enc->width, "height", G_TYPE_INT, enc->height, "fourcc", GST_TYPE_FOURCC, fourcc, NULL); break; case GST_JP2ENC_MODE_JP2: caps = gst_caps_new_simple ("image/jp2", "width", G_TYPE_INT, enc->width, "height", G_TYPE_INT, enc->height, "fourcc", GST_TYPE_FOURCC, fourcc, NULL); break; default: g_assert_not_reached (); } if (enc->fps_den > 0) gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, enc->fps_num, enc->fps_den, NULL); if (enc->par_den > 0) gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION, enc->par_num, enc->par_den, NULL); ret = gst_pad_set_caps (enc->srcpad, caps); gst_caps_unref (caps); return ret; }
static GstFlowReturn gst_jasper_dec_negotiate (GstJasperDec * dec, jas_image_t * image) { GstFlowReturn flow_ret = GST_FLOW_OK; gint width, height, channels; gint i, j; gboolean negotiate = FALSE; jas_clrspc_t clrspc; GstCaps *allowed_caps, *caps; width = jas_image_width (image); height = jas_image_height (image); channels = jas_image_numcmpts (image); GST_LOG_OBJECT (dec, "%d x %d, %d components", width, height, channels); /* jp2c bitstream has no real colour space info (kept in container), * so decoder may only pretend to know, where it really does not */ if (!jas_clrspc_isunknown (dec->clrspc)) { clrspc = dec->clrspc; GST_DEBUG_OBJECT (dec, "forcing container supplied colour space %d", clrspc); jas_image_setclrspc (image, clrspc); } else clrspc = jas_image_clrspc (image); if (!width || !height || !channels || jas_clrspc_isunknown (clrspc)) goto fail_image; if (dec->width != width || dec->height != height || dec->channels != channels || dec->clrspc != clrspc) negotiate = TRUE; if (channels != 3) goto not_supported; for (i = 0; i < channels; i++) { gint cheight, cwidth, depth, sgnd; cheight = jas_image_cmptheight (image, i); cwidth = jas_image_cmptwidth (image, i); depth = jas_image_cmptprec (image, i); sgnd = jas_image_cmptsgnd (image, i); GST_LOG_OBJECT (dec, "image component %d, %dx%d, depth %d, sgnd %d", i, cwidth, cheight, depth, sgnd); if (depth != 8 || sgnd) goto not_supported; if (dec->cheight[i] != cheight || dec->cwidth[i] != cwidth) { dec->cheight[i] = cheight; dec->cwidth[i] = cwidth; negotiate = TRUE; } } if (!negotiate && dec->format != GST_VIDEO_FORMAT_UNKNOWN) goto done; /* clear and refresh to new state */ flow_ret = GST_FLOW_NOT_NEGOTIATED; dec->format = GST_VIDEO_FORMAT_UNKNOWN; dec->width = width; dec->height = height; dec->channels = channels; /* retrieve allowed caps, and find the first one that reasonably maps * to the parameters of the colourspace */ caps = gst_pad_get_allowed_caps (dec->srcpad); if (!caps) { GST_DEBUG_OBJECT (dec, "... but no peer, using template caps"); /* need to copy because get_allowed_caps returns a ref, and get_pad_template_caps doesn't */ caps = gst_caps_copy (gst_pad_get_pad_template_caps (dec->srcpad)); } /* avoid lists of fourcc, etc */ allowed_caps = gst_caps_normalize (caps); caps = NULL; GST_LOG_OBJECT (dec, "allowed source caps %" GST_PTR_FORMAT, allowed_caps); for (i = 0; i < gst_caps_get_size (allowed_caps); i++) { GstVideoFormat format; gboolean ok; if (caps) gst_caps_unref (caps); caps = gst_caps_copy_nth (allowed_caps, i); /* sigh, ds and _parse_caps need fixed caps for parsing, fixate */ gst_pad_fixate_caps (dec->srcpad, caps); GST_LOG_OBJECT (dec, "checking caps %" GST_PTR_FORMAT, caps); if (!gst_video_format_parse_caps (caps, &format, NULL, NULL)) continue; if (gst_video_format_is_rgb (format) && jas_clrspc_fam (clrspc) == JAS_CLRSPC_FAM_RGB) { GST_DEBUG_OBJECT (dec, "trying RGB"); if ((dec->cmpt[0] = jas_image_getcmptbytype (image, JAS_IMAGE_CT_COLOR (JAS_CLRSPC_CHANIND_RGB_R))) < 0 || (dec->cmpt[1] = jas_image_getcmptbytype (image, JAS_IMAGE_CT_COLOR (JAS_CLRSPC_CHANIND_RGB_G))) < 0 || (dec->cmpt[2] = jas_image_getcmptbytype (image, JAS_IMAGE_CT_COLOR (JAS_CLRSPC_CHANIND_RGB_B))) < 0) { GST_DEBUG_OBJECT (dec, "missing RGB color component"); continue; } } else if (gst_video_format_is_yuv (format) && jas_clrspc_fam (clrspc) == JAS_CLRSPC_FAM_YCBCR) { GST_DEBUG_OBJECT (dec, "trying YUV"); if ((dec->cmpt[0] = jas_image_getcmptbytype (image, JAS_IMAGE_CT_COLOR (JAS_CLRSPC_CHANIND_YCBCR_Y))) < 0 || (dec->cmpt[1] = jas_image_getcmptbytype (image, JAS_IMAGE_CT_COLOR (JAS_CLRSPC_CHANIND_YCBCR_CB))) < 0 || (dec->cmpt[2] = jas_image_getcmptbytype (image, JAS_IMAGE_CT_COLOR (JAS_CLRSPC_CHANIND_YCBCR_CR))) < 0) { GST_DEBUG_OBJECT (dec, "missing YUV color component"); continue; } } else continue; /* match format with validity checks */ ok = TRUE; for (j = 0; j < channels; j++) { gint cmpt; cmpt = dec->cmpt[j]; if (dec->cwidth[cmpt] != gst_video_format_get_component_width (format, j, width) || dec->cheight[cmpt] != gst_video_format_get_component_height (format, j, height)) ok = FALSE; } /* commit to this format */ if (ok) { dec->format = format; break; } } if (caps) gst_caps_unref (caps); gst_caps_unref (allowed_caps); if (dec->format != GST_VIDEO_FORMAT_UNKNOWN) { /* cache some video format properties */ for (j = 0; j < channels; ++j) { dec->offset[j] = gst_video_format_get_component_offset (dec->format, j, dec->width, dec->height); dec->inc[j] = gst_video_format_get_pixel_stride (dec->format, j); dec->stride[j] = gst_video_format_get_row_stride (dec->format, j, dec->width); } dec->image_size = gst_video_format_get_size (dec->format, width, height); dec->alpha = gst_video_format_has_alpha (dec->format); if (dec->buf) g_free (dec->buf); dec->buf = g_new0 (glong, dec->width); caps = gst_video_format_new_caps (dec->format, dec->width, dec->height, dec->framerate_numerator, dec->framerate_denominator, 1, 1); GST_DEBUG_OBJECT (dec, "Set format to %d, size to %dx%d", dec->format, dec->width, dec->height); if (!gst_pad_set_caps (dec->srcpad, caps)) flow_ret = GST_FLOW_NOT_NEGOTIATED; else flow_ret = GST_FLOW_OK; gst_caps_unref (caps); } done: return flow_ret; /* ERRORS */ fail_image: { GST_DEBUG_OBJECT (dec, "Failed to process decoded image."); flow_ret = GST_FLOW_NOT_NEGOTIATED; goto done; } not_supported: { GST_DEBUG_OBJECT (dec, "Decoded image has unsupported colour space."); GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("Unsupported colorspace")); flow_ret = GST_FLOW_ERROR; goto done; } }