pnmenc: Implementation of GRAY16 handling

https://bugzilla.gnome.org/show_bug.cgi?id=757022
This commit is contained in:
Dimitrios Katsaros 2015-10-19 17:15:30 +02:00 committed by Jan Schmidt
parent f778a3f19a
commit 61440e58c1

View file

@ -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_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);
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, 4, "%3i",
imap.data[index]);
head_size += 3;
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 {
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, 4, "%3i", imap.data[i]);
head_size += 3;
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;