From 61440e58c1e3197227d2337576586b0d699f2cd4 Mon Sep 17 00:00:00 2001 From: Dimitrios Katsaros Date: Mon, 19 Oct 2015 17:15:30 +0200 Subject: pnmenc: Implementation of GRAY16 handling https://bugzilla.gnome.org/show_bug.cgi?id=757022 --- gst/pnm/gstpnmenc.c | 146 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 117 insertions(+), 29 deletions(-) (limited to 'gst/pnm') diff --git a/gst/pnm/gstpnmenc.c b/gst/pnm/gstpnmenc.c index cba456bf3..8437499d5 100644 --- a/gst/pnm/gstpnmenc.c +++ b/gst/pnm/gstpnmenc.c @@ -53,10 +53,12 @@ enum /* Add here. */ }; + + static GstStaticPadTemplate sink_pad_template = - GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("RGB") "; " - GST_VIDEO_CAPS_MAKE ("GRAY8"))); +GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE + ("{ RGB, GRAY8, GRAY16_BE, GRAY16_LE }"))); static GstStaticPadTemplate src_pad_template = @@ -140,9 +142,16 @@ gst_pnmenc_set_format (GstVideoEncoder * encoder, GstVideoCodecState * state) switch (GST_VIDEO_INFO_FORMAT (info)) { case GST_VIDEO_FORMAT_RGB: + pnmenc->info.max = 255; pnmenc->info.type = GST_PNM_TYPE_PIXMAP; break; case GST_VIDEO_FORMAT_GRAY8: + pnmenc->info.max = 255; + pnmenc->info.type = GST_PNM_TYPE_GRAYMAP; + break; + case GST_VIDEO_FORMAT_GRAY16_BE: + case GST_VIDEO_FORMAT_GRAY16_LE: + pnmenc->info.max = 65535; pnmenc->info.type = GST_PNM_TYPE_GRAYMAP; break; default: @@ -152,8 +161,6 @@ gst_pnmenc_set_format (GstVideoEncoder * encoder, GstVideoCodecState * state) pnmenc->info.width = GST_VIDEO_INFO_WIDTH (info); pnmenc->info.height = GST_VIDEO_INFO_HEIGHT (info); - /* Supported max value is only one, that is 255 */ - pnmenc->info.max = 255; if (pnmenc->input_state) gst_video_codec_state_unref (pnmenc->input_state); @@ -172,7 +179,7 @@ static GstFlowReturn gst_pnmenc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame) { GstPnmenc *pnmenc; - guint size, pixels; + guint size, pixels, bytesize; GstMapInfo omap, imap; gchar *header = NULL; GstVideoInfo *info; @@ -180,16 +187,40 @@ gst_pnmenc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame) guint i_rowstride, o_rowstride; guint bytes = 0, index, head_size; guint i, j; - + guint maxbytes_per_pixel, str_len; + gchar format_str[4]; + union + { + guint8 *ui8; + guint16 *ui16; + gpointer ptr; + } data; pnmenc = GST_PNMENC (encoder); info = &pnmenc->input_state->info; switch (GST_VIDEO_INFO_FORMAT (info)) { case GST_VIDEO_FORMAT_RGB: pixels = size = pnmenc->info.width * pnmenc->info.height * 3; + bytesize = 1; + maxbytes_per_pixel = 4; + str_len = 3; + g_strlcpy (format_str, "%3i", 4); break; case GST_VIDEO_FORMAT_GRAY8: pixels = size = pnmenc->info.width * pnmenc->info.height * 1; + bytesize = 1; + maxbytes_per_pixel = 4; + str_len = 3; + g_strlcpy (format_str, "%3i", 4); + break; + case GST_VIDEO_FORMAT_GRAY16_LE: + case GST_VIDEO_FORMAT_GRAY16_BE: + pixels = pnmenc->info.width * pnmenc->info.height * 1; + bytesize = 2; + size = pixels * bytesize; + maxbytes_per_pixel = 6; + str_len = 5; + g_strlcpy (format_str, "%5i", 4); break; default: ret = FALSE; @@ -226,6 +257,7 @@ gst_pnmenc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame) head_size = strlen (header); if (pnmenc->info.encoding == GST_PNM_ENCODING_ASCII) { + data.ptr = imap.data; /* We need to convert to ASCII */ if (pnmenc->info.width % 4 != 0) { /* Convert from gstreamer rowstride to PNM rowstride */ @@ -234,36 +266,91 @@ gst_pnmenc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame) } else { o_rowstride = pnmenc->info.width; } - i_rowstride = GST_VIDEO_FRAME_COMP_STRIDE (pnmenc->input_state, 0); - for (i = 0; i < pnmenc->info.height; i++) { - index = i * i_rowstride; - for (j = 0; j < o_rowstride; j++, bytes++, index++) { - g_snprintf ((char *) omap.data + head_size, 4, "%3i", - imap.data[index]); - head_size += 3; - omap.data[head_size++] = ' '; - /* Add new line so that file will not end up with sinle big line */ - if (!((bytes + 1) % 20)) - omap.data[head_size++] = '\n'; + switch GST_VIDEO_INFO_FORMAT + (info) { + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_GRAY8: + i_rowstride = GST_VIDEO_FRAME_COMP_STRIDE (pnmenc->input_state, 0); + for (i = 0; i < pnmenc->info.height; i++) { + index = i * i_rowstride; + for (j = 0; j < o_rowstride; j++, bytes++, index++) { + g_snprintf ((char *) omap.data + head_size, maxbytes_per_pixel, + format_str, data.ui8[index]); + head_size += str_len; + omap.data[head_size++] = ' '; + /* Add new line so that file will not end up with sinle big line */ + if (!((bytes + 1) % 20)) + omap.data[head_size++] = '\n'; + } + } + break; + case GST_VIDEO_FORMAT_GRAY16_BE: + case GST_VIDEO_FORMAT_GRAY16_LE: + i_rowstride = + GST_VIDEO_FRAME_COMP_STRIDE (pnmenc->input_state, 0) / 2; + for (i = 0; i < pnmenc->info.height; i++) { + index = i * i_rowstride; + for (j = 0; j < o_rowstride; j++, bytes++, index++) { + g_snprintf ((char *) omap.data + head_size, maxbytes_per_pixel, + format_str, data.ui16[index]); + head_size += str_len; + omap.data[head_size++] = ' '; + /* Add new line so that file will not end up with sinle big line */ + if (!((bytes + 1) % 20)) + omap.data[head_size++] = '\n'; + } + } + break; + default: + GST_ERROR_OBJECT (encoder, "Unhandled format %s", + gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (info))); + gst_buffer_unmap (frame->output_buffer, &omap); + gst_buffer_unmap (frame->input_buffer, &imap); + g_free (header); + return GST_FLOW_ERROR; } - } } else { - for (i = 0; i < pixels; i++) { - g_snprintf ((char *) omap.data + head_size, 4, "%3i", imap.data[i]); - head_size += 3; - omap.data[head_size++] = ' '; - if (!((i + 1) % 20)) - omap.data[head_size++] = '\n'; - } + switch GST_VIDEO_INFO_FORMAT + (info) { + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_GRAY8: + for (i = 0; i < pixels; i++) { + g_snprintf ((char *) omap.data + head_size, maxbytes_per_pixel, + format_str, data.ui8[i]); + head_size += str_len; + omap.data[head_size++] = ' '; + if (!((i + 1) % 20)) + omap.data[head_size++] = '\n'; + } + break; + case GST_VIDEO_FORMAT_GRAY16_BE: + case GST_VIDEO_FORMAT_GRAY16_LE: + for (i = 0; i < pixels; i++) { + g_snprintf ((char *) omap.data + head_size, maxbytes_per_pixel, + format_str, data.ui16[i]); + head_size += str_len; + omap.data[head_size++] = ' '; + if (!((i + 1) % 20)) + omap.data[head_size++] = '\n'; + } + break; + default: + GST_ERROR_OBJECT (encoder, "Unhandled format %s", + gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (info))); + gst_buffer_unmap (frame->output_buffer, &omap); + gst_buffer_unmap (frame->input_buffer, &imap); + g_free (header); + return GST_FLOW_ERROR; + } } } else { /* Need to convert from GStreamer rowstride to PNM rowstride */ if (pnmenc->info.width % 4 != 0) { if (pnmenc->info.type == GST_PNM_TYPE_PIXMAP) { - o_rowstride = 3 * pnmenc->info.width; + o_rowstride = 3 * pnmenc->info.width * bytesize; } else { - o_rowstride = pnmenc->info.width; + o_rowstride = pnmenc->info.width * bytesize; } i_rowstride = GST_VIDEO_FRAME_COMP_STRIDE (pnmenc->input_state, 0); @@ -273,12 +360,13 @@ gst_pnmenc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame) } else { /* size contains complete image size inlcuding header size, Exclude header size while copying data */ - memcpy (omap.data + strlen (header), imap.data, (size - head_size)); + memcpy (omap.data + head_size, imap.data, (size - head_size)); } } gst_buffer_unmap (frame->output_buffer, &omap); gst_buffer_unmap (frame->input_buffer, &imap); + g_free (header); if ((ret = gst_video_encoder_finish_frame (encoder, frame)) != GST_FLOW_OK) goto done; -- cgit v1.2.1