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