From 4cf598bcf339ebb6a98dc34abd5970753b9d096d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Mon, 7 Apr 2025 18:16:22 +0200 Subject: [PATCH] y4m: share common code among encoder and decoder Part-of: --- .../gst-plugins-good/gst/y4m/gsty4mdec.c | 65 +++---------- .../gst-plugins-good/gst/y4m/gsty4menc.c | 48 +--------- .../gst-plugins-good/gst/y4m/gsty4mformat.c | 93 +++++++++++++++++++ .../gst-plugins-good/gst/y4m/gsty4mformat.h | 27 ++++++ .../gst-plugins-good/gst/y4m/meson.build | 1 + 5 files changed, 141 insertions(+), 93 deletions(-) create mode 100644 subprojects/gst-plugins-good/gst/y4m/gsty4mformat.c create mode 100644 subprojects/gst-plugins-good/gst/y4m/gsty4mformat.h diff --git a/subprojects/gst-plugins-good/gst/y4m/gsty4mdec.c b/subprojects/gst-plugins-good/gst/y4m/gsty4mdec.c index 06b35e8cbb..d447897e05 100644 --- a/subprojects/gst-plugins-good/gst/y4m/gsty4mdec.c +++ b/subprojects/gst-plugins-good/gst/y4m/gsty4mdec.c @@ -37,6 +37,7 @@ #include #include "gsty4mdec.h" +#include "gsty4mformat.h" #define MAX_SIZE 32768 @@ -387,6 +388,7 @@ gst_y4m_dec_parse_header (GstY4mDec * y4mdec, char *header) gulong par_n = 0, par_d = 0; gulong width = 0, height = 0; GstVideoFormat format = GST_VIDEO_FORMAT_I420; + GstVideoInterlaceMode interlace_mode; if (memcmp (header, "YUV4MPEG2 ", 10) != 0) { GST_ERROR_OBJECT (y4mdec, "y4m start code not found"); @@ -458,59 +460,15 @@ gst_y4m_dec_parse_header (GstY4mDec * y4mdec, char *header) return FALSE; } - gst_video_info_init (&y4mdec->info); - gst_video_info_set_format (&y4mdec->out_info, format, width, height); - y4mdec->info = y4mdec->out_info; - - switch (y4mdec->info.finfo->format) { - case GST_VIDEO_FORMAT_I420: - y4mdec->info.offset[0] = 0; - y4mdec->info.stride[0] = width; - y4mdec->info.offset[1] = y4mdec->info.stride[0] * height; - y4mdec->info.stride[1] = GST_ROUND_UP_2 (width) / 2; - y4mdec->info.offset[2] = - y4mdec->info.offset[1] + - y4mdec->info.stride[1] * (GST_ROUND_UP_2 (height) / 2); - y4mdec->info.stride[2] = GST_ROUND_UP_2 (width) / 2; - y4mdec->info.size = - y4mdec->info.offset[2] + - y4mdec->info.stride[2] * (GST_ROUND_UP_2 (height) / 2); - break; - case GST_VIDEO_FORMAT_Y42B: - y4mdec->info.offset[0] = 0; - y4mdec->info.stride[0] = width; - y4mdec->info.offset[1] = y4mdec->info.stride[0] * height; - y4mdec->info.stride[1] = GST_ROUND_UP_2 (width) / 2; - y4mdec->info.offset[2] = - y4mdec->info.offset[1] + y4mdec->info.stride[1] * height; - y4mdec->info.stride[2] = GST_ROUND_UP_2 (width) / 2; - y4mdec->info.size = - y4mdec->info.offset[2] + y4mdec->info.stride[2] * height; - break; - case GST_VIDEO_FORMAT_Y444: - y4mdec->info.offset[0] = 0; - y4mdec->info.stride[0] = width; - y4mdec->info.offset[1] = y4mdec->info.stride[0] * height; - y4mdec->info.stride[1] = width; - y4mdec->info.offset[2] = - y4mdec->info.offset[1] + y4mdec->info.stride[1] * height; - y4mdec->info.stride[2] = width; - y4mdec->info.size = - y4mdec->info.offset[2] + y4mdec->info.stride[2] * height; - break; - default: - break; - } - switch (interlaced_char) { case 0: case '?': case 'p': - y4mdec->info.interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE; + interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE; break; case 't': case 'b': - y4mdec->info.interlace_mode = GST_VIDEO_INTERLACE_MODE_INTERLEAVED; + interlace_mode = GST_VIDEO_INTERLACE_MODE_INTERLEAVED; break; default: GST_ERROR_OBJECT (y4mdec, "Unknown interlaced char '%c'", @@ -528,10 +486,17 @@ gst_y4m_dec_parse_header (GstY4mDec * y4mdec, char *header) if (par_d == 0) par_d = 1; - y4mdec->info.fps_n = fps_n; - y4mdec->info.fps_d = fps_d; - y4mdec->info.par_n = par_n; - y4mdec->info.par_d = par_d; + gst_video_info_set_interlaced_format (&y4mdec->out_info, format, + interlace_mode, width, height); + + GST_VIDEO_INFO_FPS_N (&y4mdec->out_info) = fps_n; + GST_VIDEO_INFO_FPS_D (&y4mdec->out_info) = fps_d; + GST_VIDEO_INFO_PAR_N (&y4mdec->out_info) = par_n; + GST_VIDEO_INFO_PAR_D (&y4mdec->out_info) = par_d; + + if (!gst_y4m_video_unpadded_info (&y4mdec->info, &y4mdec->out_info)) + return FALSE; + return TRUE; } diff --git a/subprojects/gst-plugins-good/gst/y4m/gsty4menc.c b/subprojects/gst-plugins-good/gst/y4m/gsty4menc.c index 190465a2c4..903268bc75 100644 --- a/subprojects/gst-plugins-good/gst/y4m/gsty4menc.c +++ b/subprojects/gst-plugins-good/gst/y4m/gsty4menc.c @@ -43,6 +43,7 @@ #include #include "gsty4menc.h" +#include "gsty4mformat.h" /* Filter signals and args */ enum @@ -139,69 +140,30 @@ gst_y4m_encode_set_format (GstVideoEncoder * encoder, GstY4mEncode *y4menc; GstVideoInfo *info, out_info; GstVideoCodecState *output_state; - gint width, height; - GstVideoFormat format; - gsize cr_h; y4menc = GST_Y4M_ENCODE (encoder); info = &state->info; - format = GST_VIDEO_INFO_FORMAT (info); - width = GST_VIDEO_INFO_WIDTH (info); - height = GST_VIDEO_INFO_HEIGHT (info); - - gst_video_info_set_format (&out_info, format, width, height); - - switch (format) { + switch (GST_VIDEO_INFO_FORMAT (info)) { case GST_VIDEO_FORMAT_I420: y4menc->colorspace = "420"; - out_info.stride[0] = width; - out_info.stride[1] = GST_ROUND_UP_2 (width) / 2; - out_info.stride[2] = out_info.stride[1]; - out_info.offset[0] = 0; - out_info.offset[1] = out_info.stride[0] * height; - cr_h = GST_ROUND_UP_2 (height) / 2; - if (GST_VIDEO_INFO_IS_INTERLACED (info)) - cr_h = GST_ROUND_UP_2 (height); - out_info.offset[2] = out_info.offset[1] + out_info.stride[1] * cr_h; - out_info.size = out_info.offset[2] + out_info.stride[2] * cr_h; break; case GST_VIDEO_FORMAT_Y42B: y4menc->colorspace = "422"; - out_info.stride[0] = width; - out_info.stride[1] = GST_ROUND_UP_2 (width) / 2; - out_info.stride[2] = out_info.stride[1]; - out_info.offset[0] = 0; - out_info.offset[1] = out_info.stride[0] * height; - out_info.offset[2] = out_info.offset[1] + out_info.stride[1] * height; - /* simplification of ROUNDUP4(w)*h + 2*(ROUNDUP8(w)/2)*h */ - out_info.size = out_info.offset[2] + out_info.stride[2] * height; break; case GST_VIDEO_FORMAT_Y41B: y4menc->colorspace = "411"; - out_info.stride[0] = width; - out_info.stride[1] = GST_ROUND_UP_2 (width) / 4; - out_info.stride[2] = out_info.stride[1]; - out_info.offset[0] = 0; - out_info.offset[1] = out_info.stride[0] * height; - out_info.offset[2] = out_info.offset[1] + out_info.stride[1] * height; - /* simplification of ROUNDUP4(w)*h + 2*((ROUNDUP16(w)/4)*h */ - out_info.size = (width + (GST_ROUND_UP_2 (width) / 2)) * height; break; case GST_VIDEO_FORMAT_Y444: y4menc->colorspace = "444"; - out_info.stride[0] = width; - out_info.stride[1] = out_info.stride[0]; - out_info.stride[2] = out_info.stride[0]; - out_info.offset[0] = 0; - out_info.offset[1] = out_info.stride[0] * height; - out_info.offset[2] = out_info.offset[1] * 2; - out_info.size = out_info.stride[0] * height * 3; break; default: goto invalid_format; } + if (!gst_y4m_video_unpadded_info (&out_info, info)) + goto invalid_format; + y4menc->info = *info; y4menc->out_info = out_info; y4menc->padded = !gst_video_info_is_equal (info, &out_info); diff --git a/subprojects/gst-plugins-good/gst/y4m/gsty4mformat.c b/subprojects/gst-plugins-good/gst/y4m/gsty4mformat.c new file mode 100644 index 0000000000..7f7c4a561f --- /dev/null +++ b/subprojects/gst-plugins-good/gst/y4m/gsty4mformat.c @@ -0,0 +1,93 @@ +/* GStreamer + * Copyright (C) 2025 Igalia, S.L. + * Author: Victor Jaquez + * + * 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 "gsty4mformat.h" + +gboolean +gst_y4m_video_unpadded_info (GstVideoInfo * y4m_info, + const GstVideoInfo * vinfo) +{ + g_return_val_if_fail (y4m_info && vinfo, FALSE); + + gsize cr_h; + guint width, height; + GstVideoFormat format; + GstVideoInfo out_info; + + format = GST_VIDEO_INFO_FORMAT (vinfo); + width = GST_VIDEO_INFO_WIDTH (vinfo); + height = GST_VIDEO_INFO_HEIGHT (vinfo); + + out_info = *vinfo; + + switch (format) { + case GST_VIDEO_FORMAT_I420: + out_info.stride[0] = width; + out_info.stride[1] = GST_ROUND_UP_2 (width) / 2; + out_info.stride[2] = out_info.stride[1]; + out_info.offset[0] = 0; + out_info.offset[1] = out_info.stride[0] * height; + cr_h = GST_ROUND_UP_2 (height) / 2; + if (GST_VIDEO_INFO_IS_INTERLACED (vinfo)) + cr_h = GST_ROUND_UP_2 (height); + out_info.offset[2] = out_info.offset[1] + out_info.stride[1] * cr_h; + out_info.size = out_info.offset[2] + out_info.stride[2] * cr_h; + break; + case GST_VIDEO_FORMAT_Y42B: + out_info.stride[0] = width; + out_info.stride[1] = GST_ROUND_UP_2 (width) / 2; + out_info.stride[2] = out_info.stride[1]; + out_info.offset[0] = 0; + out_info.offset[1] = out_info.stride[0] * height; + out_info.offset[2] = out_info.offset[1] + out_info.stride[1] * height; + /* simplification of ROUNDUP4(w)*h + 2*(ROUNDUP8(w)/2)*h */ + out_info.size = out_info.offset[2] + out_info.stride[2] * height; + break; + case GST_VIDEO_FORMAT_Y41B: + out_info.stride[0] = width; + out_info.stride[1] = GST_ROUND_UP_2 (width) / 4; + out_info.stride[2] = out_info.stride[1]; + out_info.offset[0] = 0; + out_info.offset[1] = out_info.stride[0] * height; + out_info.offset[2] = out_info.offset[1] + out_info.stride[1] * height; + /* simplification of ROUNDUP4(w)*h + 2*((ROUNDUP16(w)/4)*h */ + out_info.size = (width + (GST_ROUND_UP_2 (width) / 2)) * height; + break; + case GST_VIDEO_FORMAT_Y444: + out_info.stride[0] = width; + out_info.stride[1] = out_info.stride[0]; + out_info.stride[2] = out_info.stride[0]; + out_info.offset[0] = 0; + out_info.offset[1] = out_info.stride[0] * height; + out_info.offset[2] = out_info.offset[1] * 2; + out_info.size = out_info.stride[0] * height * 3; + break; + default: + GST_FIXME ("%s is not supported", gst_video_format_to_string (format)); + } + + *y4m_info = out_info; + + return TRUE; +} diff --git a/subprojects/gst-plugins-good/gst/y4m/gsty4mformat.h b/subprojects/gst-plugins-good/gst/y4m/gsty4mformat.h new file mode 100644 index 0000000000..f43498a84a --- /dev/null +++ b/subprojects/gst-plugins-good/gst/y4m/gsty4mformat.h @@ -0,0 +1,27 @@ +/* GStreamer + * Copyright (C) 2025 Igalia, S.L. + * Author: Victor Jaquez + * + * 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. + */ + +#pragma once + +#include +#include + +gboolean gst_y4m_video_unpadded_info (GstVideoInfo * y4m_info, + const GstVideoInfo * vinfo); diff --git a/subprojects/gst-plugins-good/gst/y4m/meson.build b/subprojects/gst-plugins-good/gst/y4m/meson.build index 311cdde8b8..a0008ecace 100644 --- a/subprojects/gst-plugins-good/gst/y4m/meson.build +++ b/subprojects/gst-plugins-good/gst/y4m/meson.build @@ -1,5 +1,6 @@ y4m_sources = [ 'plugin.c', + 'gsty4mformat.c', 'gsty4menc.c', 'gsty4mdec.c' ]