pnmenc: Tidy up code, support BE/LE GRAY16 properly

Remove code that dealt with odd strides separately - there's
not really any overhead to just using 1 codepath for both matched
and unmatched stride output.

Add separate codepaths for BE vs LE GRAY16 input so they're
handled properly
This commit is contained in:
Jan Schmidt 2016-05-18 17:19:40 +10:00
parent 30503f07ae
commit fa2d98afe2

View file

@ -189,12 +189,6 @@ gst_pnmenc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame)
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;
@ -253,120 +247,116 @@ gst_pnmenc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame)
ret = GST_FLOW_ERROR;
goto done;
}
memcpy (omap.data, header, strlen (header));
/* Copy out the header first */
head_size = strlen (header);
memcpy (omap.data, header, head_size);
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 */
if (pnmenc->info.type == GST_PNM_TYPE_PIXMAP) {
o_rowstride = 3 * pnmenc->info.width;
} else {
o_rowstride = pnmenc->info.width;
}
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;
}
/* Convert from gstreamer rowstride to PNM rowstride as we go */
if (pnmenc->info.type == GST_PNM_TYPE_PIXMAP) {
o_rowstride = 3 * pnmenc->info.width;
} 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, 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;
}
o_rowstride = pnmenc->info.width;
}
} 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 * bytesize;
} else {
o_rowstride = pnmenc->info.width * bytesize;
}
i_rowstride = GST_VIDEO_FRAME_COMP_STRIDE (pnmenc->input_state, 0);
i_rowstride = GST_VIDEO_FRAME_COMP_STRIDE (pnmenc->input_state, 0);
for (i = 0; i < pnmenc->info.height; i++)
memcpy (omap.data + head_size + o_rowstride * i,
imap.data + i_rowstride * i, o_rowstride);
switch (GST_VIDEO_INFO_FORMAT (info)) {
case GST_VIDEO_FORMAT_RGB:
case GST_VIDEO_FORMAT_GRAY8:
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, imap.data[index]);
head_size += str_len;
omap.data[head_size++] = ' ';
/* Add new line so that file will not end up with single big line */
if (!((bytes + 1) % 20))
omap.data[head_size++] = '\n';
}
}
break;
case GST_VIDEO_FORMAT_GRAY16_BE:
for (i = 0; i < pnmenc->info.height; i++) {
index = i * i_rowstride;
for (j = 0; j < o_rowstride; j++, bytes++, index += 2) {
g_snprintf ((char *) omap.data + head_size, maxbytes_per_pixel,
format_str, GST_READ_UINT16_BE (imap.data + index));
head_size += str_len;
omap.data[head_size++] = ' ';
/* Add new line so that file will not end up with single big line */
if (!((bytes + 1) % 20))
omap.data[head_size++] = '\n';
}
}
break;
case GST_VIDEO_FORMAT_GRAY16_LE:
for (i = 0; i < pnmenc->info.height; i++) {
index = i * i_rowstride;
for (j = 0; j < o_rowstride; j++, bytes++, index += 2) {
g_snprintf ((char *) omap.data + head_size, maxbytes_per_pixel,
format_str, GST_READ_UINT16_LE (imap.data + index));
head_size += str_len;
omap.data[head_size++] = ' ';
/* Add new line so that file will not end up with single 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;
}
gst_buffer_set_size (frame->output_buffer, head_size);
} else {
guint out_index = head_size;
/* Binary output. 8-bit, or 16-bit BE */
if (pnmenc->info.type == GST_PNM_TYPE_PIXMAP) {
o_rowstride = 3 * pnmenc->info.width * bytesize;
} else {
/* size contains complete image size inlcuding header size,
Exclude header size while copying data */
memcpy (omap.data + head_size, imap.data, (size - head_size));
o_rowstride = pnmenc->info.width * bytesize;
}
i_rowstride = GST_VIDEO_FRAME_COMP_STRIDE (pnmenc->input_state, 0);
switch (GST_VIDEO_INFO_FORMAT (info)) {
case GST_VIDEO_FORMAT_GRAY16_BE:
for (i = 0; i < pnmenc->info.height; i++) {
index = i * i_rowstride;
for (j = 0; j < o_rowstride; j += 2, index += 2) {
guint16 val = GST_READ_UINT16_LE (imap.data + index);
GST_WRITE_UINT16_BE (omap.data + out_index, val);
out_index += 2;
}
}
break;
case GST_VIDEO_FORMAT_GRAY16_LE:
for (i = 0; i < pnmenc->info.height; i++) {
index = i * i_rowstride;
for (j = 0; j < o_rowstride; j += 2, index += 2) {
guint16 val = GST_READ_UINT16_LE (imap.data + index);
GST_WRITE_UINT16_BE (omap.data + out_index, val);
out_index += 2;
}
}
break;
default:
for (i = 0; i < pnmenc->info.height; i++) {
memcpy (omap.data + head_size + o_rowstride * i,
imap.data + i_rowstride * i, o_rowstride);
}
}
}
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;