3 * Copyright (c) 2001, 2002, 2003 Fabrice Bellard
5 * This file is part of FFmpeg.
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.
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.
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
22 #include "libavutil/frame.h"
23 #include "libavutil/pixdesc.h"
29 static int yuv4_write_header(AVFormatContext *s)
32 AVIOContext *pb = s->pb;
34 int raten, rated, aspectn, aspectd, ret;
36 const char *colorspace = "";
37 const char *colorrange = "";
41 width = st->codecpar->width;
42 height = st->codecpar->height;
43 field_order = st->codecpar->field_order;
45 // TODO: should be avg_frame_rate
46 av_reduce(&raten, &rated, st->time_base.den,
47 st->time_base.num, (1UL << 31) - 1);
49 aspectn = st->sample_aspect_ratio.num;
50 aspectd = st->sample_aspect_ratio.den;
52 if (aspectn == 0 && aspectd == 1)
53 aspectd = 0; // 0:0 means unknown
55 switch(st->codecpar->color_range) {
56 case AVCOL_RANGE_MPEG:
57 colorrange = " XCOLORRANGE=LIMITED";
59 case AVCOL_RANGE_JPEG:
60 colorrange = " XCOLORRANGE=FULL";
66 switch (field_order) {
68 case AV_FIELD_TT: inter = 't'; break;
70 case AV_FIELD_BB: inter = 'b'; break;
71 default: inter = 'p'; break;
74 switch (st->codecpar->format) {
75 case AV_PIX_FMT_GRAY8:
76 colorspace = " Cmono";
78 case AV_PIX_FMT_GRAY9:
79 colorspace = " Cmono9";
81 case AV_PIX_FMT_GRAY10:
82 colorspace = " Cmono10";
84 case AV_PIX_FMT_GRAY12:
85 colorspace = " Cmono12";
87 case AV_PIX_FMT_GRAY16:
88 colorspace = " Cmono16";
90 case AV_PIX_FMT_YUV411P:
91 colorspace = " C411 XYSCSS=411";
93 case AV_PIX_FMT_YUVJ420P:
94 colorspace = " C420jpeg XYSCSS=420JPEG";
95 colorrange = " XCOLORRANGE=FULL";
97 case AV_PIX_FMT_YUVJ422P:
98 colorspace = " C422 XYSCSS=422";
99 colorrange = " XCOLORRANGE=FULL";
101 case AV_PIX_FMT_YUVJ444P:
102 colorspace = " C444 XYSCSS=444";
103 colorrange = " XCOLORRANGE=FULL";
105 case AV_PIX_FMT_YUV420P:
106 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 default: colorspace = " C420jpeg XYSCSS=420JPEG"; break;
112 case AV_PIX_FMT_YUV422P:
113 colorspace = " C422 XYSCSS=422";
115 case AV_PIX_FMT_YUV444P:
116 colorspace = " C444 XYSCSS=444";
118 case AV_PIX_FMT_YUVA444P:
119 colorspace = " C444alpha XYSCSS=444";
121 case AV_PIX_FMT_YUV420P9:
122 colorspace = " C420p9 XYSCSS=420P9";
124 case AV_PIX_FMT_YUV422P9:
125 colorspace = " C422p9 XYSCSS=422P9";
127 case AV_PIX_FMT_YUV444P9:
128 colorspace = " C444p9 XYSCSS=444P9";
130 case AV_PIX_FMT_YUV420P10:
131 colorspace = " C420p10 XYSCSS=420P10";
133 case AV_PIX_FMT_YUV422P10:
134 colorspace = " C422p10 XYSCSS=422P10";
136 case AV_PIX_FMT_YUV444P10:
137 colorspace = " C444p10 XYSCSS=444P10";
139 case AV_PIX_FMT_YUV420P12:
140 colorspace = " C420p12 XYSCSS=420P12";
142 case AV_PIX_FMT_YUV422P12:
143 colorspace = " C422p12 XYSCSS=422P12";
145 case AV_PIX_FMT_YUV444P12:
146 colorspace = " C444p12 XYSCSS=444P12";
148 case AV_PIX_FMT_YUV420P14:
149 colorspace = " C420p14 XYSCSS=420P14";
151 case AV_PIX_FMT_YUV422P14:
152 colorspace = " C422p14 XYSCSS=422P14";
154 case AV_PIX_FMT_YUV444P14:
155 colorspace = " C444p14 XYSCSS=444P14";
157 case AV_PIX_FMT_YUV420P16:
158 colorspace = " C420p16 XYSCSS=420P16";
160 case AV_PIX_FMT_YUV422P16:
161 colorspace = " C422p16 XYSCSS=422P16";
163 case AV_PIX_FMT_YUV444P16:
164 colorspace = " C444p16 XYSCSS=444P16";
168 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);
172 av_log(s, AV_LOG_ERROR,
173 "Error. YUV4MPEG stream header write failed.\n");
181 static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt)
183 AVStream *st = s->streams[pkt->stream_index];
184 AVIOContext *pb = s->pb;
185 const AVFrame *frame = (const AVFrame *)pkt->data;
187 const AVPixFmtDescriptor *desc;
189 /* construct frame header */
191 avio_printf(s->pb, Y4M_FRAME_MAGIC "\n");
193 if (st->codecpar->codec_id == AV_CODEC_ID_RAWVIDEO) {
194 avio_write(pb, pkt->data, pkt->size);
198 width = st->codecpar->width;
199 height = st->codecpar->height;
200 desc = av_pix_fmt_desc_get(st->codecpar->format);
202 /* The following code presumes all planes to be non-interleaved. */
203 for (int k = 0; k < desc->nb_components; k++) {
204 int plane_height = height, plane_width = width;
205 const uint8_t *ptr = frame->data[k];
207 if (desc->nb_components >= 3 && (k == 1 || k == 2)) { /* chroma? */
208 plane_width = AV_CEIL_RSHIFT(plane_width, desc->log2_chroma_w);
209 plane_height = AV_CEIL_RSHIFT(plane_height, desc->log2_chroma_h);
211 plane_width *= desc->comp[k].step;
213 for (int i = 0; i < plane_height; i++) {
214 avio_write(pb, ptr, plane_width);
215 ptr += frame->linesize[k];
222 static int yuv4_init(AVFormatContext *s)
224 if (s->nb_streams != 1)
227 if (s->streams[0]->codecpar->codec_id != AV_CODEC_ID_WRAPPED_AVFRAME &&
228 s->streams[0]->codecpar->codec_id != AV_CODEC_ID_RAWVIDEO) {
229 av_log(s, AV_LOG_ERROR, "ERROR: Codec not supported.\n");
230 return AVERROR_INVALIDDATA;
233 switch (s->streams[0]->codecpar->format) {
234 case AV_PIX_FMT_YUV411P:
235 av_log(s, AV_LOG_WARNING, "Warning: generating rarely used 4:1:1 YUV "
236 "stream, some mjpegtools might not work.\n");
238 case AV_PIX_FMT_GRAY8:
239 case AV_PIX_FMT_YUV420P:
240 case AV_PIX_FMT_YUV422P:
241 case AV_PIX_FMT_YUV444P:
242 // TODO: remove YUVJ pixel formats when they are completely removed from the codebase.
243 case AV_PIX_FMT_YUVJ420P:
244 case AV_PIX_FMT_YUVJ422P:
245 case AV_PIX_FMT_YUVJ444P:
247 case AV_PIX_FMT_GRAY9:
248 case AV_PIX_FMT_GRAY10:
249 case AV_PIX_FMT_GRAY12:
250 case AV_PIX_FMT_GRAY16:
251 case AV_PIX_FMT_YUV420P9:
252 case AV_PIX_FMT_YUV422P9:
253 case AV_PIX_FMT_YUV444P9:
254 case AV_PIX_FMT_YUV420P10:
255 case AV_PIX_FMT_YUV422P10:
256 case AV_PIX_FMT_YUV444P10:
257 case AV_PIX_FMT_YUV420P12:
258 case AV_PIX_FMT_YUV422P12:
259 case AV_PIX_FMT_YUV444P12:
260 case AV_PIX_FMT_YUV420P14:
261 case AV_PIX_FMT_YUV422P14:
262 case AV_PIX_FMT_YUV444P14:
263 case AV_PIX_FMT_YUV420P16:
264 case AV_PIX_FMT_YUV422P16:
265 case AV_PIX_FMT_YUV444P16:
266 case AV_PIX_FMT_YUVA444P:
267 if (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {
268 av_log(s, AV_LOG_ERROR, "'%s' is not an official yuv4mpegpipe pixel format. "
269 "Use '-strict -1' to encode to this pixel format.\n",
270 av_get_pix_fmt_name(s->streams[0]->codecpar->format));
271 return AVERROR(EINVAL);
273 av_log(s, AV_LOG_WARNING, "Warning: generating non standard YUV stream. "
274 "Mjpegtools will not work.\n");
277 av_log(s, AV_LOG_ERROR, "ERROR: yuv4mpeg can only handle "
278 "yuv444p, yuv422p, yuv420p, yuv411p and gray8 pixel formats. "
279 "And using 'strict -1' also yuv444p9, yuv422p9, yuv420p9, "
280 "yuv444p10, yuv422p10, yuv420p10, "
281 "yuv444p12, yuv422p12, yuv420p12, "
282 "yuv444p14, yuv422p14, yuv420p14, "
283 "yuv444p16, yuv422p16, yuv420p16, "
285 "gray9, gray10, gray12 "
286 "and gray16 pixel formats. "
287 "Use -pix_fmt to select one.\n");
294 const FFOutputFormat ff_yuv4mpegpipe_muxer = {
295 .p.name = "yuv4mpegpipe",
296 .p.long_name = NULL_IF_CONFIG_SMALL("YUV4MPEG pipe"),
297 .p.extensions = "y4m",
298 .p.audio_codec = AV_CODEC_ID_NONE,
299 .p.video_codec = AV_CODEC_ID_WRAPPED_AVFRAME,
301 .write_header = yuv4_write_header,
302 .write_packet = yuv4_write_packet,