2 * y4mreader.c - Y4M parser
4 * Copyright (C) 2015 Intel Corporation
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1
9 * of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
22 #include "gst/vaapi/sysdeps.h"
23 #include "y4mreader.h"
25 /* format documentation:
26 * http://wiki.multimedia.cx/index.php?title=YUV4MPEG2 */
28 static inline gboolean
29 parse_int (const gchar * str, guint * out_value_ptr)
43 value = strtol (str, NULL, 0);
46 if (value > 0 && value <= G_MAXUINT)
47 *out_value_ptr = value;
55 parse_header (Y4MReader * file)
58 guint8 header[BUFSIZ];
62 memset (header, 0, BUFSIZ);
63 s = fread (header, 1, 9, file->fp);
67 if (memcmp (header, "YUV4MPEG2", 9) != 0)
70 for (i = 9; i < BUFSIZ - 1; i++) {
84 if ((header[j] != 0x20) && (header[j - 1] == 0x20)) {
87 if (!parse_int ((gchar *) & header[j], &file->width))
91 if (!parse_int ((gchar *) & header[j], &file->height))
95 str = (char *) &header[j + 1];
96 if (strncmp (str, "420", 3) != 0) {
97 g_warning ("Unsupported chroma subsampling.");
98 return FALSE; /* unsupported chroma subsampling */
102 str = (char *) &header[j + 1];
103 if (*str != 'p' && *str != '?') {
104 g_warning ("Interlaced content are not supported.");
105 return FALSE; /* interlaced is unsupported */
108 case 'F': /* frame rate ratio */
112 if (!parse_int ((gchar *) & header[j], &num))
114 while ((header[j] != ':') && (j < i))
116 if (!parse_int ((gchar *) & header[j], &den))
119 if (num <= 0 || den <= 0) {
120 file->fps_n = 30; /* default to 30 fps */
128 case 'A': /* sample aspect ration */
130 case 'X': /* metadata */
143 y4m_reader_open (const gchar * filename)
145 Y4MReader *imagefile;
147 imagefile = g_slice_new0 (Y4MReader);
150 imagefile->fp = fopen (filename, "r");
151 if (!imagefile->fp) {
152 g_warning ("open file %s error", filename);
156 imagefile->fp = stdin;
159 if (!parse_header (imagefile))
165 if (imagefile->fp && imagefile->fp != stdin)
166 fclose (imagefile->fp);
168 g_slice_free (Y4MReader, imagefile);
173 y4m_reader_close (Y4MReader * file)
175 g_return_if_fail (file);
177 if (file->fp && file->fp != stdin)
180 g_slice_free (Y4MReader, file);
184 skip_frame_header (Y4MReader * file)
187 guint8 header[BUFSIZ];
190 memset (header, 0, BUFSIZ);
191 s = fread (header, 1, 5, file->fp);
195 if (memcmp (header, "FRAME", 5) != 0)
198 for (i = 5; i < BUFSIZ - 1; i++) {
199 b = fgetc (file->fp);
207 return (i < BUFSIZ - 1);
211 y4m_reader_load_image (Y4MReader * file, GstVaapiImage * image)
215 guint frame_size, stride, i;
217 g_return_val_if_fail (gst_vaapi_image_is_mapped (image), FALSE);
218 g_return_val_if_fail (file && file->fp, FALSE);
220 /* only valid for I420 */
221 frame_size = file->height * file->width * 3 / 2;
222 if (gst_vaapi_image_get_data_size (image) < frame_size)
224 if (gst_vaapi_image_get_plane_count (image) != 3)
227 if (!skip_frame_header (file))
231 plane = gst_vaapi_image_get_plane (image, 0);
232 stride = gst_vaapi_image_get_pitch (image, 0);
233 for (i = 0; i < file->height; i++) {
234 s = fread (plane, 1, file->width, file->fp);
235 if (s != file->width)
241 plane = gst_vaapi_image_get_plane (image, 1);
242 stride = gst_vaapi_image_get_pitch (image, 1);
243 for (i = 0; i < file->height / 2; i++) {
244 s = fread (plane, 1, file->width / 2, file->fp);
245 if (s != file->width / 2)
251 plane = gst_vaapi_image_get_plane (image, 2);
252 stride = gst_vaapi_image_get_pitch (image, 2);
253 for (i = 0; i < file->height / 2; i++) {
254 s = fread (plane, 1, file->width / 2, file->fp);
255 if (s != file->width / 2)