y4m: share common code among encoder and decoder

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8719>
This commit is contained in:
Víctor Manuel Jáquez Leal 2025-04-07 18:16:22 +02:00 committed by GStreamer Marge Bot
parent 6bcf0e3276
commit 4cf598bcf3
5 changed files with 141 additions and 93 deletions

View File

@ -37,6 +37,7 @@
#include <string.h> #include <string.h>
#include "gsty4mdec.h" #include "gsty4mdec.h"
#include "gsty4mformat.h"
#define MAX_SIZE 32768 #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 par_n = 0, par_d = 0;
gulong width = 0, height = 0; gulong width = 0, height = 0;
GstVideoFormat format = GST_VIDEO_FORMAT_I420; GstVideoFormat format = GST_VIDEO_FORMAT_I420;
GstVideoInterlaceMode interlace_mode;
if (memcmp (header, "YUV4MPEG2 ", 10) != 0) { if (memcmp (header, "YUV4MPEG2 ", 10) != 0) {
GST_ERROR_OBJECT (y4mdec, "y4m start code not found"); GST_ERROR_OBJECT (y4mdec, "y4m start code not found");
@ -458,59 +460,15 @@ gst_y4m_dec_parse_header (GstY4mDec * y4mdec, char *header)
return FALSE; 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) { switch (interlaced_char) {
case 0: case 0:
case '?': case '?':
case 'p': case 'p':
y4mdec->info.interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE; interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
break; break;
case 't': case 't':
case 'b': case 'b':
y4mdec->info.interlace_mode = GST_VIDEO_INTERLACE_MODE_INTERLEAVED; interlace_mode = GST_VIDEO_INTERLACE_MODE_INTERLEAVED;
break; break;
default: default:
GST_ERROR_OBJECT (y4mdec, "Unknown interlaced char '%c'", 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) if (par_d == 0)
par_d = 1; par_d = 1;
y4mdec->info.fps_n = fps_n; gst_video_info_set_interlaced_format (&y4mdec->out_info, format,
y4mdec->info.fps_d = fps_d; interlace_mode, width, height);
y4mdec->info.par_n = par_n;
y4mdec->info.par_d = par_d; 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; return TRUE;
} }

View File

@ -43,6 +43,7 @@
#include <string.h> #include <string.h>
#include "gsty4menc.h" #include "gsty4menc.h"
#include "gsty4mformat.h"
/* Filter signals and args */ /* Filter signals and args */
enum enum
@ -139,69 +140,30 @@ gst_y4m_encode_set_format (GstVideoEncoder * encoder,
GstY4mEncode *y4menc; GstY4mEncode *y4menc;
GstVideoInfo *info, out_info; GstVideoInfo *info, out_info;
GstVideoCodecState *output_state; GstVideoCodecState *output_state;
gint width, height;
GstVideoFormat format;
gsize cr_h;
y4menc = GST_Y4M_ENCODE (encoder); y4menc = GST_Y4M_ENCODE (encoder);
info = &state->info; info = &state->info;
format = GST_VIDEO_INFO_FORMAT (info); switch (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) {
case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_I420:
y4menc->colorspace = "420"; 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; break;
case GST_VIDEO_FORMAT_Y42B: case GST_VIDEO_FORMAT_Y42B:
y4menc->colorspace = "422"; 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; break;
case GST_VIDEO_FORMAT_Y41B: case GST_VIDEO_FORMAT_Y41B:
y4menc->colorspace = "411"; 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; break;
case GST_VIDEO_FORMAT_Y444: case GST_VIDEO_FORMAT_Y444:
y4menc->colorspace = "444"; 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; break;
default: default:
goto invalid_format; goto invalid_format;
} }
if (!gst_y4m_video_unpadded_info (&out_info, info))
goto invalid_format;
y4menc->info = *info; y4menc->info = *info;
y4menc->out_info = out_info; y4menc->out_info = out_info;
y4menc->padded = !gst_video_info_is_equal (info, &out_info); y4menc->padded = !gst_video_info_is_equal (info, &out_info);

View File

@ -0,0 +1,93 @@
/* GStreamer
* Copyright (C) 2025 Igalia, S.L.
* Author: Victor Jaquez <vjaquez@igalia.com>
*
* 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;
}

View File

@ -0,0 +1,27 @@
/* GStreamer
* Copyright (C) 2025 Igalia, S.L.
* Author: Victor Jaquez <vjaquez@igalia.com>
*
* 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 <gst/gst.h>
#include <gst/video/video.h>
gboolean gst_y4m_video_unpadded_info (GstVideoInfo * y4m_info,
const GstVideoInfo * vinfo);

View File

@ -1,5 +1,6 @@
y4m_sources = [ y4m_sources = [
'plugin.c', 'plugin.c',
'gsty4mformat.c',
'gsty4menc.c', 'gsty4menc.c',
'gsty4mdec.c' 'gsty4mdec.c'
] ]