3 * Copyright (c) 2001, 2002, 2003 Fabrice Bellard.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #define Y4M_MAGIC "YUV4MPEG2"
22 #define Y4M_FRAME_MAGIC "FRAME"
23 #define Y4M_LINE_MAX 256
25 #ifdef CONFIG_ENCODERS
27 static int yuv4_generate_header(AVFormatContext
*s
, char* buf
)
31 int raten
, rated
, aspectn
, aspectd
, n
;
35 width
= st
->codec
.width
;
36 height
= st
->codec
.height
;
38 av_reduce(&raten
, &rated
, st
->codec
.frame_rate
, st
->codec
.frame_rate_base
, (1UL<<31)-1);
40 aspectn
= st
->codec
.sample_aspect_ratio
.num
;
41 aspectd
= st
->codec
.sample_aspect_ratio
.den
;
43 inter
= 'p'; /* progressive is the default */
44 if (st
->codec
.coded_frame
&& st
->codec
.coded_frame
->interlaced_frame
) {
45 inter
= st
->codec
.coded_frame
->top_field_first ?
't' : 'b';
48 /* construct stream header, if this is the first frame */
49 n
= snprintf(buf
, Y4M_LINE_MAX
, "%s W%d H%d F%d:%d I%c A%d:%d%s\n",
56 (st
->codec
.pix_fmt
== PIX_FMT_YUV411P
) ?
" XYSCSS=411" : "");
61 static int yuv4_write_packet(AVFormatContext
*s
, int stream_index
,
62 const uint8_t *buf
, int size
, int64_t pts
)
64 AVStream
*st
= s
->streams
[stream_index
];
65 ByteIOContext
*pb
= &s
->pb
;
67 int* first_pkt
= s
->priv_data
;
70 char buf2
[Y4M_LINE_MAX
+1];
72 uint8_t *ptr
, *ptr1
, *ptr2
;
74 picture
= (AVPicture
*)buf
;
76 /* for the first packet we have to output the header as well */
79 if (yuv4_generate_header(s
, buf2
) < 0) {
80 fprintf(stderr
, "Error. YUV4MPEG stream header write failed.\n");
83 put_buffer(pb
, buf2
, strlen(buf2
));
87 /* construct frame header */
89 m
= snprintf(buf1
, sizeof(buf1
), "%s\n", Y4M_FRAME_MAGIC
);
90 put_buffer(pb
, buf1
, strlen(buf1
));
92 width
= st
->codec
.width
;
93 height
= st
->codec
.height
;
95 ptr
= picture
->data
[0];
96 for(i
=0;i
<height
;i
++) {
97 put_buffer(pb
, ptr
, width
);
98 ptr
+= picture
->linesize
[0];
103 ptr1
= picture
->data
[1];
104 ptr2
= picture
->data
[2];
105 for(i
=0;i
<height
;i
++) { /* Cb */
106 put_buffer(pb
, ptr1
, width
);
107 ptr1
+= picture
->linesize
[1];
109 for(i
=0;i
<height
;i
++) { /* Cr */
110 put_buffer(pb
, ptr2
, width
);
111 ptr2
+= picture
->linesize
[2];
113 put_flush_packet(pb
);
117 static int yuv4_write_header(AVFormatContext
*s
)
119 int* first_pkt
= s
->priv_data
;
121 if (s
->nb_streams
!= 1)
124 if (s
->streams
[0]->codec
.pix_fmt
== PIX_FMT_YUV411P
) {
125 fprintf(stderr
, "Warning: generating non-standard 4:1:1 YUV stream, some mjpegtools might not work.\n");
127 else if (s
->streams
[0]->codec
.pix_fmt
!= PIX_FMT_YUV420P
) {
128 fprintf(stderr
, "ERROR: yuv4mpeg only handles 4:2:0, 4:1:1 YUV data. Use -pix_fmt to select one.\n");
136 static int yuv4_write_trailer(AVFormatContext
*s
)
141 AVOutputFormat yuv4mpegpipe_oformat
= {
143 "YUV4MPEG pipe format",
152 .flags
= AVFMT_RAWPICTURE
,
154 #endif //CONFIG_ENCODERS
156 /* Header size increased to allow room for optional flags */
157 #define MAX_YUV4_HEADER 80
158 #define MAX_FRAME_HEADER 10
160 static int yuv4_read_header(AVFormatContext
*s
, AVFormatParameters
*ap
)
162 char header
[MAX_YUV4_HEADER
+1];
164 ByteIOContext
*pb
= &s
->pb
;
165 int width
, height
, raten
, rated
, aspectn
, aspectd
;
169 for (i
=0; i
<MAX_YUV4_HEADER
; i
++) {
170 header
[i
] = get_byte(pb
);
171 if (header
[i
] == '\n') {
176 if (i
== MAX_YUV4_HEADER
) return -1;
177 if (strncmp(header
, Y4M_MAGIC
, strlen(Y4M_MAGIC
))) return -1;
178 sscanf(header
+strlen(Y4M_MAGIC
), " W%d H%d F%d:%d I%c A%d:%d",
179 &width
, &height
, &raten
, &rated
, &lacing
, &aspectn
, &aspectd
);
181 st
= av_new_stream(s
, 0);
183 st
->codec
.width
= width
;
184 st
->codec
.height
= height
;
185 av_reduce(&raten
, &rated
, raten
, rated
, (1UL<<31)-1);
186 st
->codec
.frame_rate
= raten
;
187 st
->codec
.frame_rate_base
= rated
;
188 st
->codec
.pix_fmt
= PIX_FMT_YUV420P
;
189 st
->codec
.codec_type
= CODEC_TYPE_VIDEO
;
190 st
->codec
.codec_id
= CODEC_ID_RAWVIDEO
;
191 st
->codec
.sample_aspect_ratio
= (AVRational
){aspectn
, aspectd
};
196 static int yuv4_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
199 char header
[MAX_FRAME_HEADER
+1];
200 int packet_size
, ret
, width
, height
;
201 AVStream
*st
= s
->streams
[0];
203 for (i
=0; i
<MAX_FRAME_HEADER
; i
++) {
204 header
[i
] = get_byte(&s
->pb
);
205 if (header
[i
] == '\n') {
210 if (i
== MAX_FRAME_HEADER
) return -1;
211 if (strncmp(header
, Y4M_FRAME_MAGIC
, strlen(Y4M_FRAME_MAGIC
))) return -1;
213 width
= st
->codec
.width
;
214 height
= st
->codec
.height
;
216 packet_size
= avpicture_get_size(st
->codec
.pix_fmt
, width
, height
);
220 if (av_new_packet(pkt
, packet_size
) < 0)
223 pkt
->stream_index
= 0;
224 ret
= get_buffer(&s
->pb
, pkt
->data
, pkt
->size
);
225 if (ret
!= pkt
->size
) {
233 static int yuv4_read_close(AVFormatContext
*s
)
238 AVInputFormat yuv4mpegpipe_iformat
= {
240 "YUV4MPEG pipe format",
246 .extensions
= "yuv4mpeg"
249 int yuv4mpeg_init(void)
251 av_register_input_format(&yuv4mpegpipe_iformat
);
252 #ifdef CONFIG_ENCODERS
253 av_register_output_format(&yuv4mpegpipe_oformat
);
254 #endif //CONFIG_ENCODERS