FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/yuv4mpegenc.c
Date: 2024-05-03 15:42:48
Exec Total Coverage
Lines: 54 169 32.0%
Functions: 3 3 100.0%
Branches: 19 66 28.8%

Line Branch Exec Source
1 /*
2 * YUV4MPEG muxer
3 * Copyright (c) 2001, 2002, 2003 Fabrice Bellard
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include "libavutil/frame.h"
23 #include "libavutil/pixdesc.h"
24 #include "avformat.h"
25 #include "internal.h"
26 #include "mux.h"
27 #include "yuv4mpeg.h"
28
29 1 static int yuv4_write_header(AVFormatContext *s)
30 {
31 AVStream *st;
32 1 AVIOContext *pb = s->pb;
33 int width, height;
34 int raten, rated, aspectn, aspectd, ret;
35 char inter;
36 1 const char *colorspace = "";
37 1 const char *colorrange = "";
38 int field_order;
39
40 1 st = s->streams[0];
41 1 width = st->codecpar->width;
42 1 height = st->codecpar->height;
43 1 field_order = st->codecpar->field_order;
44
45 // TODO: should be avg_frame_rate
46 1 av_reduce(&raten, &rated, st->time_base.den,
47 1 st->time_base.num, (1UL << 31) - 1);
48
49 1 aspectn = st->sample_aspect_ratio.num;
50 1 aspectd = st->sample_aspect_ratio.den;
51
52
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (aspectn == 0 && aspectd == 1)
53 1 aspectd = 0; // 0:0 means unknown
54
55
1/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch(st->codecpar->color_range) {
56 1 case AVCOL_RANGE_MPEG:
57 1 colorrange = " XCOLORRANGE=LIMITED";
58 1 break;
59 case AVCOL_RANGE_JPEG:
60 colorrange = " XCOLORRANGE=FULL";
61 break;
62 default:
63 break;
64 }
65
66
1/3
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 switch (field_order) {
67 case AV_FIELD_TB:
68 case AV_FIELD_TT: inter = 't'; break;
69 case AV_FIELD_BT:
70 case AV_FIELD_BB: inter = 'b'; break;
71 1 default: inter = 'p'; break;
72 }
73
74
1/29
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
1 switch (st->codecpar->format) {
75 case AV_PIX_FMT_GRAY8:
76 colorspace = " Cmono";
77 break;
78 case AV_PIX_FMT_GRAY9:
79 colorspace = " Cmono9";
80 break;
81 case AV_PIX_FMT_GRAY10:
82 colorspace = " Cmono10";
83 break;
84 case AV_PIX_FMT_GRAY12:
85 colorspace = " Cmono12";
86 break;
87 case AV_PIX_FMT_GRAY16:
88 colorspace = " Cmono16";
89 break;
90 case AV_PIX_FMT_YUV411P:
91 colorspace = " C411 XYSCSS=411";
92 break;
93 case AV_PIX_FMT_YUVJ420P:
94 colorspace = " C420jpeg XYSCSS=420JPEG";
95 colorrange = " XCOLORRANGE=FULL";
96 break;
97 case AV_PIX_FMT_YUVJ422P:
98 colorspace = " C422 XYSCSS=422";
99 colorrange = " XCOLORRANGE=FULL";
100 break;
101 case AV_PIX_FMT_YUVJ444P:
102 colorspace = " C444 XYSCSS=444";
103 colorrange = " XCOLORRANGE=FULL";
104 break;
105 1 case AV_PIX_FMT_YUV420P:
106
1/3
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 switch (st->codecpar->chroma_location) {
107 case AVCHROMA_LOC_TOPLEFT: colorspace = " C420paldv XYSCSS=420PALDV"; break;
108 case AVCHROMA_LOC_LEFT: colorspace = " C420mpeg2 XYSCSS=420MPEG2"; break;
109 1 default: colorspace = " C420jpeg XYSCSS=420JPEG"; break;
110 }
111 1 break;
112 case AV_PIX_FMT_YUV422P:
113 colorspace = " C422 XYSCSS=422";
114 break;
115 case AV_PIX_FMT_YUV444P:
116 colorspace = " C444 XYSCSS=444";
117 break;
118 case AV_PIX_FMT_YUVA444P:
119 colorspace = " C444alpha XYSCSS=444";
120 break;
121 case AV_PIX_FMT_YUV420P9:
122 colorspace = " C420p9 XYSCSS=420P9";
123 break;
124 case AV_PIX_FMT_YUV422P9:
125 colorspace = " C422p9 XYSCSS=422P9";
126 break;
127 case AV_PIX_FMT_YUV444P9:
128 colorspace = " C444p9 XYSCSS=444P9";
129 break;
130 case AV_PIX_FMT_YUV420P10:
131 colorspace = " C420p10 XYSCSS=420P10";
132 break;
133 case AV_PIX_FMT_YUV422P10:
134 colorspace = " C422p10 XYSCSS=422P10";
135 break;
136 case AV_PIX_FMT_YUV444P10:
137 colorspace = " C444p10 XYSCSS=444P10";
138 break;
139 case AV_PIX_FMT_YUV420P12:
140 colorspace = " C420p12 XYSCSS=420P12";
141 break;
142 case AV_PIX_FMT_YUV422P12:
143 colorspace = " C422p12 XYSCSS=422P12";
144 break;
145 case AV_PIX_FMT_YUV444P12:
146 colorspace = " C444p12 XYSCSS=444P12";
147 break;
148 case AV_PIX_FMT_YUV420P14:
149 colorspace = " C420p14 XYSCSS=420P14";
150 break;
151 case AV_PIX_FMT_YUV422P14:
152 colorspace = " C422p14 XYSCSS=422P14";
153 break;
154 case AV_PIX_FMT_YUV444P14:
155 colorspace = " C444p14 XYSCSS=444P14";
156 break;
157 case AV_PIX_FMT_YUV420P16:
158 colorspace = " C420p16 XYSCSS=420P16";
159 break;
160 case AV_PIX_FMT_YUV422P16:
161 colorspace = " C422p16 XYSCSS=422P16";
162 break;
163 case AV_PIX_FMT_YUV444P16:
164 colorspace = " C444p16 XYSCSS=444P16";
165 break;
166 }
167
168 1 ret = avio_printf(pb, Y4M_MAGIC " W%d H%d F%d:%d I%c A%d:%d%s%s\n",
169 width, height, raten, rated, inter,
170 aspectn, aspectd, colorspace, colorrange);
171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0) {
172 av_log(s, AV_LOG_ERROR,
173 "Error. YUV4MPEG stream header write failed.\n");
174 return ret;
175 }
176
177 1 return 0;
178 }
179
180
181 25 static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt)
182 {
183 25 AVStream *st = s->streams[pkt->stream_index];
184 25 AVIOContext *pb = s->pb;
185 25 const AVFrame *frame = (const AVFrame *)pkt->data;
186 int width, height;
187 const AVPixFmtDescriptor *desc;
188
189 /* construct frame header */
190
191 25 avio_printf(s->pb, Y4M_FRAME_MAGIC "\n");
192
193
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (st->codecpar->codec_id == AV_CODEC_ID_RAWVIDEO) {
194 avio_write(pb, pkt->data, pkt->size);
195 return 0;
196 }
197
198 25 width = st->codecpar->width;
199 25 height = st->codecpar->height;
200 25 desc = av_pix_fmt_desc_get(st->codecpar->format);
201
202 /* The following code presumes all planes to be non-interleaved. */
203
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 25 times.
100 for (int k = 0; k < desc->nb_components; k++) {
204 75 int plane_height = height, plane_width = width;
205 75 const uint8_t *ptr = frame->data[k];
206
207
5/6
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 25 times.
✓ Branch 4 taken 25 times.
✓ Branch 5 taken 25 times.
75 if (desc->nb_components >= 3 && (k == 1 || k == 2)) { /* chroma? */
208 50 plane_width = AV_CEIL_RSHIFT(plane_width, desc->log2_chroma_w);
209 50 plane_height = AV_CEIL_RSHIFT(plane_height, desc->log2_chroma_h);
210 }
211 75 plane_width *= desc->comp[k].step;
212
213
2/2
✓ Branch 0 taken 14400 times.
✓ Branch 1 taken 75 times.
14475 for (int i = 0; i < plane_height; i++) {
214 14400 avio_write(pb, ptr, plane_width);
215 14400 ptr += frame->linesize[k];
216 }
217 }
218
219 25 return 0;
220 }
221
222 1 static int yuv4_init(AVFormatContext *s)
223 {
224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (s->streams[0]->codecpar->codec_id != AV_CODEC_ID_WRAPPED_AVFRAME &&
225 s->streams[0]->codecpar->codec_id != AV_CODEC_ID_RAWVIDEO) {
226 av_log(s, AV_LOG_ERROR, "ERROR: Codec not supported.\n");
227 return AVERROR_INVALIDDATA;
228 }
229
230
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 switch (s->streams[0]->codecpar->format) {
231 case AV_PIX_FMT_YUV411P:
232 av_log(s, AV_LOG_WARNING, "Warning: generating rarely used 4:1:1 YUV "
233 "stream, some mjpegtools might not work.\n");
234 break;
235 1 case AV_PIX_FMT_GRAY8:
236 case AV_PIX_FMT_YUV420P:
237 case AV_PIX_FMT_YUV422P:
238 case AV_PIX_FMT_YUV444P:
239 // TODO: remove YUVJ pixel formats when they are completely removed from the codebase.
240 case AV_PIX_FMT_YUVJ420P:
241 case AV_PIX_FMT_YUVJ422P:
242 case AV_PIX_FMT_YUVJ444P:
243 1 break;
244 case AV_PIX_FMT_GRAY9:
245 case AV_PIX_FMT_GRAY10:
246 case AV_PIX_FMT_GRAY12:
247 case AV_PIX_FMT_GRAY16:
248 case AV_PIX_FMT_YUV420P9:
249 case AV_PIX_FMT_YUV422P9:
250 case AV_PIX_FMT_YUV444P9:
251 case AV_PIX_FMT_YUV420P10:
252 case AV_PIX_FMT_YUV422P10:
253 case AV_PIX_FMT_YUV444P10:
254 case AV_PIX_FMT_YUV420P12:
255 case AV_PIX_FMT_YUV422P12:
256 case AV_PIX_FMT_YUV444P12:
257 case AV_PIX_FMT_YUV420P14:
258 case AV_PIX_FMT_YUV422P14:
259 case AV_PIX_FMT_YUV444P14:
260 case AV_PIX_FMT_YUV420P16:
261 case AV_PIX_FMT_YUV422P16:
262 case AV_PIX_FMT_YUV444P16:
263 case AV_PIX_FMT_YUVA444P:
264 if (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {
265 av_log(s, AV_LOG_ERROR, "'%s' is not an official yuv4mpegpipe pixel format. "
266 "Use '-strict -1' to encode to this pixel format.\n",
267 av_get_pix_fmt_name(s->streams[0]->codecpar->format));
268 return AVERROR(EINVAL);
269 }
270 av_log(s, AV_LOG_WARNING, "Warning: generating non standard YUV stream. "
271 "Mjpegtools will not work.\n");
272 break;
273 default:
274 av_log(s, AV_LOG_ERROR, "ERROR: yuv4mpeg can only handle "
275 "yuv444p, yuv422p, yuv420p, yuv411p and gray8 pixel formats. "
276 "And using 'strict -1' also yuv444p9, yuv422p9, yuv420p9, "
277 "yuv444p10, yuv422p10, yuv420p10, "
278 "yuv444p12, yuv422p12, yuv420p12, "
279 "yuv444p14, yuv422p14, yuv420p14, "
280 "yuv444p16, yuv422p16, yuv420p16, "
281 "yuva444p, "
282 "gray9, gray10, gray12 "
283 "and gray16 pixel formats. "
284 "Use -pix_fmt to select one.\n");
285 return AVERROR(EIO);
286 }
287
288 1 return 0;
289 }
290
291 const FFOutputFormat ff_yuv4mpegpipe_muxer = {
292 .p.name = "yuv4mpegpipe",
293 .p.long_name = NULL_IF_CONFIG_SMALL("YUV4MPEG pipe"),
294 .p.extensions = "y4m",
295 .p.audio_codec = AV_CODEC_ID_NONE,
296 .p.video_codec = AV_CODEC_ID_WRAPPED_AVFRAME,
297 .p.subtitle_codec = AV_CODEC_ID_NONE,
298 .init = yuv4_init,
299 .write_header = yuv4_write_header,
300 .write_packet = yuv4_write_packet,
301 .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH,
302 };
303