]> git.sesse.net Git - ffmpeg/blob - libavformat/yuv4mpegenc.c
Fix compilation with --disable-everything --enable-demuxer=matroska.
[ffmpeg] / libavformat / yuv4mpegenc.c
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
27 #define Y4M_LINE_MAX 256
28
29 static int yuv4_generate_header(AVFormatContext *s, char* buf)
30 {
31     AVStream *st;
32     int width, height;
33     int raten, rated, aspectn, aspectd, n;
34     char inter;
35     const char *colorspace = "";
36
37     st     = s->streams[0];
38     width  = st->codec->width;
39     height = st->codec->height;
40
41     av_reduce(&raten, &rated, st->codec->time_base.den,
42               st->codec->time_base.num, (1UL << 31) - 1);
43
44     aspectn = st->sample_aspect_ratio.num;
45     aspectd = st->sample_aspect_ratio.den;
46
47     if (aspectn == 0 && aspectd == 1)
48         aspectd = 0;  // 0:0 means unknown
49
50     inter = 'p'; /* progressive is the default */
51     if (st->codec->coded_frame && st->codec->coded_frame->interlaced_frame)
52         inter = st->codec->coded_frame->top_field_first ? 't' : 'b';
53     if (st->codec->field_order == AV_FIELD_PROGRESSIVE) {
54         inter = 'p';
55     } else if (st->codec->field_order == AV_FIELD_TB || st->codec->field_order == AV_FIELD_TT) {
56         inter = 't';
57     } else if (st->codec->field_order == AV_FIELD_BT || st->codec->field_order == AV_FIELD_BB) {
58         inter = 'b';
59     }
60
61     switch (st->codec->pix_fmt) {
62     case AV_PIX_FMT_GRAY8:
63         colorspace = " Cmono";
64         break;
65     case AV_PIX_FMT_GRAY16:
66         colorspace = " Cmono16";
67         break;
68     case AV_PIX_FMT_YUV411P:
69         colorspace = " C411 XYSCSS=411";
70         break;
71     case AV_PIX_FMT_YUV420P:
72         switch (st->codec->chroma_sample_location) {
73         case AVCHROMA_LOC_TOPLEFT: colorspace = " C420paldv XYSCSS=420PALDV"; break;
74         case AVCHROMA_LOC_LEFT:    colorspace = " C420mpeg2 XYSCSS=420MPEG2"; break;
75         default:                   colorspace = " C420jpeg XYSCSS=420JPEG";   break;
76         }
77         break;
78     case AV_PIX_FMT_YUV422P:
79         colorspace = " C422 XYSCSS=422";
80         break;
81     case AV_PIX_FMT_YUV444P:
82         colorspace = " C444 XYSCSS=444";
83         break;
84     case AV_PIX_FMT_YUV420P9:
85         colorspace = " C420p9 XYSCSS=420P9";
86         break;
87     case AV_PIX_FMT_YUV422P9:
88         colorspace = " C422p9 XYSCSS=422P9";
89         break;
90     case AV_PIX_FMT_YUV444P9:
91         colorspace = " C444p9 XYSCSS=444P9";
92         break;
93     case AV_PIX_FMT_YUV420P10:
94         colorspace = " C420p10 XYSCSS=420P10";
95         break;
96     case AV_PIX_FMT_YUV422P10:
97         colorspace = " C422p10 XYSCSS=422P10";
98         break;
99     case AV_PIX_FMT_YUV444P10:
100         colorspace = " C444p10 XYSCSS=444P10";
101         break;
102     case AV_PIX_FMT_YUV420P12:
103         colorspace = " C420p12 XYSCSS=420P12";
104         break;
105     case AV_PIX_FMT_YUV422P12:
106         colorspace = " C422p12 XYSCSS=422P12";
107         break;
108     case AV_PIX_FMT_YUV444P12:
109         colorspace = " C444p12 XYSCSS=444P12";
110         break;
111     case AV_PIX_FMT_YUV420P14:
112         colorspace = " C420p14 XYSCSS=420P14";
113         break;
114     case AV_PIX_FMT_YUV422P14:
115         colorspace = " C422p14 XYSCSS=422P14";
116         break;
117     case AV_PIX_FMT_YUV444P14:
118         colorspace = " C444p14 XYSCSS=444P14";
119         break;
120     case AV_PIX_FMT_YUV420P16:
121         colorspace = " C420p16 XYSCSS=420P16";
122         break;
123     case AV_PIX_FMT_YUV422P16:
124         colorspace = " C422p16 XYSCSS=422P16";
125         break;
126     case AV_PIX_FMT_YUV444P16:
127         colorspace = " C444p16 XYSCSS=444P16";
128         break;
129     }
130
131     /* construct stream header, if this is the first frame */
132     n = snprintf(buf, Y4M_LINE_MAX, "%s W%d H%d F%d:%d I%c A%d:%d%s\n",
133                  Y4M_MAGIC, width, height, raten, rated, inter,
134                  aspectn, aspectd, colorspace);
135
136     return n;
137 }
138
139 static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt)
140 {
141     AVStream *st = s->streams[pkt->stream_index];
142     AVIOContext *pb = s->pb;
143     AVPicture *picture, picture_tmp;
144     int* first_pkt = s->priv_data;
145     int width, height, h_chroma_shift, v_chroma_shift;
146     int i;
147     char buf2[Y4M_LINE_MAX + 1];
148     char buf1[20];
149     uint8_t *ptr, *ptr1, *ptr2;
150
151     memcpy(&picture_tmp, pkt->data, sizeof(AVPicture));
152     picture = &picture_tmp;
153
154     /* for the first packet we have to output the header as well */
155     if (*first_pkt) {
156         *first_pkt = 0;
157         if (yuv4_generate_header(s, buf2) < 0) {
158             av_log(s, AV_LOG_ERROR,
159                    "Error. YUV4MPEG stream header write failed.\n");
160             return AVERROR(EIO);
161         } else {
162             avio_write(pb, buf2, strlen(buf2));
163         }
164     }
165
166     /* construct frame header */
167
168     snprintf(buf1, sizeof(buf1), "%s\n", Y4M_FRAME_MAGIC);
169     avio_write(pb, buf1, strlen(buf1));
170
171     width  = st->codec->width;
172     height = st->codec->height;
173
174     ptr = picture->data[0];
175
176     switch (st->codec->pix_fmt) {
177     case AV_PIX_FMT_GRAY8:
178     case AV_PIX_FMT_YUV411P:
179     case AV_PIX_FMT_YUV420P:
180     case AV_PIX_FMT_YUV422P:
181     case AV_PIX_FMT_YUV444P:
182         break;
183     case AV_PIX_FMT_GRAY16:
184     case AV_PIX_FMT_YUV420P9:
185     case AV_PIX_FMT_YUV422P9:
186     case AV_PIX_FMT_YUV444P9:
187     case AV_PIX_FMT_YUV420P10:
188     case AV_PIX_FMT_YUV422P10:
189     case AV_PIX_FMT_YUV444P10:
190     case AV_PIX_FMT_YUV420P12:
191     case AV_PIX_FMT_YUV422P12:
192     case AV_PIX_FMT_YUV444P12:
193     case AV_PIX_FMT_YUV420P14:
194     case AV_PIX_FMT_YUV422P14:
195     case AV_PIX_FMT_YUV444P14:
196     case AV_PIX_FMT_YUV420P16:
197     case AV_PIX_FMT_YUV422P16:
198     case AV_PIX_FMT_YUV444P16:
199         width *= 2;
200         break;
201     default:
202         av_log(s, AV_LOG_ERROR, "The pixel format '%s' is not supported.\n",
203                av_get_pix_fmt_name(st->codec->pix_fmt));
204         return AVERROR(EINVAL);
205     }
206
207     for (i = 0; i < height; i++) {
208         avio_write(pb, ptr, width);
209         ptr += picture->linesize[0];
210     }
211
212     if (st->codec->pix_fmt != AV_PIX_FMT_GRAY8 &&
213         st->codec->pix_fmt != AV_PIX_FMT_GRAY16) {
214         // Adjust for smaller Cb and Cr planes
215         av_pix_fmt_get_chroma_sub_sample(st->codec->pix_fmt, &h_chroma_shift,
216                                          &v_chroma_shift);
217         width  = FF_CEIL_RSHIFT(width,  h_chroma_shift);
218         height = FF_CEIL_RSHIFT(height, v_chroma_shift);
219
220         ptr1 = picture->data[1];
221         ptr2 = picture->data[2];
222         for (i = 0; i < height; i++) {     /* Cb */
223             avio_write(pb, ptr1, width);
224             ptr1 += picture->linesize[1];
225         }
226         for (i = 0; i < height; i++) {     /* Cr */
227             avio_write(pb, ptr2, width);
228             ptr2 += picture->linesize[2];
229         }
230     }
231
232     return 0;
233 }
234
235 static int yuv4_write_header(AVFormatContext *s)
236 {
237     int *first_pkt = s->priv_data;
238
239     if (s->nb_streams != 1)
240         return AVERROR(EIO);
241
242     if (s->streams[0]->codec->codec_id != AV_CODEC_ID_RAWVIDEO) {
243         av_log(s, AV_LOG_ERROR, "ERROR: Only rawvideo supported.\n");
244         return AVERROR_INVALIDDATA;
245     }
246
247     switch (s->streams[0]->codec->pix_fmt) {
248     case AV_PIX_FMT_YUV411P:
249         av_log(s, AV_LOG_WARNING, "Warning: generating rarely used 4:1:1 YUV "
250                "stream, some mjpegtools might not work.\n");
251         break;
252     case AV_PIX_FMT_GRAY8:
253     case AV_PIX_FMT_GRAY16:
254     case AV_PIX_FMT_YUV420P:
255     case AV_PIX_FMT_YUV422P:
256     case AV_PIX_FMT_YUV444P:
257         break;
258     case AV_PIX_FMT_YUV420P9:
259     case AV_PIX_FMT_YUV422P9:
260     case AV_PIX_FMT_YUV444P9:
261     case AV_PIX_FMT_YUV420P10:
262     case AV_PIX_FMT_YUV422P10:
263     case AV_PIX_FMT_YUV444P10:
264     case AV_PIX_FMT_YUV420P12:
265     case AV_PIX_FMT_YUV422P12:
266     case AV_PIX_FMT_YUV444P12:
267     case AV_PIX_FMT_YUV420P14:
268     case AV_PIX_FMT_YUV422P14:
269     case AV_PIX_FMT_YUV444P14:
270     case AV_PIX_FMT_YUV420P16:
271     case AV_PIX_FMT_YUV422P16:
272     case AV_PIX_FMT_YUV444P16:
273         if (s->streams[0]->codec->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {
274             av_log(s, AV_LOG_ERROR, "'%s' is not a official yuv4mpegpipe pixel format. "
275                    "Use '-strict -1' to encode to this pixel format.\n",
276                    av_get_pix_fmt_name(s->streams[0]->codec->pix_fmt));
277             return AVERROR(EINVAL);
278         }
279         av_log(s, AV_LOG_WARNING, "Warning: generating non standard YUV stream. "
280                "Mjpegtools will not work.\n");
281         break;
282     default:
283         av_log(s, AV_LOG_ERROR, "ERROR: yuv4mpeg can only handle "
284                "yuv444p, yuv422p, yuv420p, yuv411p and gray8 pixel formats. "
285                "And using 'strict -1' also yuv444p9, yuv422p9, yuv420p9, "
286                "yuv444p10, yuv422p10, yuv420p10, "
287                "yuv444p12, yuv422p12, yuv420p12, "
288                "yuv444p14, yuv422p14, yuv420p14, "
289                "yuv444p16, yuv422p16, yuv420p16 "
290                "and gray16 pixel formats. "
291                "Use -pix_fmt to select one.\n");
292         return AVERROR(EIO);
293     }
294
295     *first_pkt = 1;
296     return 0;
297 }
298
299 AVOutputFormat ff_yuv4mpegpipe_muxer = {
300     .name              = "yuv4mpegpipe",
301     .long_name         = NULL_IF_CONFIG_SMALL("YUV4MPEG pipe"),
302     .extensions        = "y4m",
303     .priv_data_size    = sizeof(int),
304     .audio_codec       = AV_CODEC_ID_NONE,
305     .video_codec       = AV_CODEC_ID_RAWVIDEO,
306     .write_header      = yuv4_write_header,
307     .write_packet      = yuv4_write_packet,
308     .flags             = AVFMT_RAWPICTURE,
309 };