| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * YUV4MPEG format | 
					
						
							| 
									
										
										
										
											2009-01-19 15:46:40 +00:00
										 |  |  |  * Copyright (c) 2001, 2002, 2003 Fabrice Bellard | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-10-07 15:30:46 +00:00
										 |  |  |  * This file is part of FFmpeg. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * FFmpeg is free software; you can redistribute it and/or | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License as published by the Free Software Foundation; either | 
					
						
							| 
									
										
										
										
											2006-10-07 15:30:46 +00:00
										 |  |  |  * version 2.1 of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-10-07 15:30:46 +00:00
										 |  |  |  * FFmpeg is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |  * Lesser General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Lesser General Public | 
					
						
							| 
									
										
										
										
											2006-10-07 15:30:46 +00:00
										 |  |  |  * License along with FFmpeg; if not, write to the Free Software | 
					
						
							| 
									
										
										
										
											2006-01-12 22:43:26 +00:00
										 |  |  |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | #include "avformat.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define Y4M_MAGIC "YUV4MPEG2"
 | 
					
						
							|  |  |  | #define Y4M_FRAME_MAGIC "FRAME"
 | 
					
						
							|  |  |  | #define Y4M_LINE_MAX 256
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-08 11:54:05 +00:00
										 |  |  | struct frame_attributes { | 
					
						
							|  |  |  |     int interlaced_frame; | 
					
						
							|  |  |  |     int top_field_first; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-13 23:44:16 +00:00
										 |  |  | #if CONFIG_YUV4MPEGPIPE_MUXER
 | 
					
						
							| 
									
										
										
										
											2003-10-18 03:19:44 +00:00
										 |  |  | static int yuv4_generate_header(AVFormatContext *s, char* buf) | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     AVStream *st; | 
					
						
							|  |  |  |     int width, height; | 
					
						
							| 
									
										
										
										
											2003-10-20 20:23:46 +00:00
										 |  |  |     int raten, rated, aspectn, aspectd, n; | 
					
						
							| 
									
										
										
										
											2003-10-18 03:19:44 +00:00
										 |  |  |     char inter; | 
					
						
							| 
									
										
										
										
											2006-06-17 15:53:23 +00:00
										 |  |  |     const char *colorspace = ""; | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     st = s->streams[0]; | 
					
						
							| 
									
										
										
										
											2005-07-17 22:24:36 +00:00
										 |  |  |     width = st->codec->width; | 
					
						
							|  |  |  |     height = st->codec->height; | 
					
						
							| 
									
										
										
										
											2003-03-12 15:16:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-17 22:24:36 +00:00
										 |  |  |     av_reduce(&raten, &rated, st->codec->time_base.den, st->codec->time_base.num, (1UL<<31)-1); | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-23 23:43:20 +00:00
										 |  |  |     aspectn = st->sample_aspect_ratio.num; | 
					
						
							|  |  |  |     aspectd = st->sample_aspect_ratio.den; | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |     if ( aspectn == 0 && aspectd == 1 ) aspectd = 0;  // 0:0 means unknown
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-10-18 03:19:44 +00:00
										 |  |  |     inter = 'p'; /* progressive is the default */ | 
					
						
							| 
									
										
										
										
											2005-07-17 22:24:36 +00:00
										 |  |  |     if (st->codec->coded_frame && st->codec->coded_frame->interlaced_frame) { | 
					
						
							|  |  |  |         inter = st->codec->coded_frame->top_field_first ? 't' : 'b'; | 
					
						
							| 
									
										
										
										
											2003-10-18 03:19:44 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-17 22:24:36 +00:00
										 |  |  |     switch(st->codec->pix_fmt) { | 
					
						
							| 
									
										
										
										
											2005-01-19 12:27:48 +00:00
										 |  |  |     case PIX_FMT_GRAY8: | 
					
						
							|  |  |  |         colorspace = " Cmono"; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |     case PIX_FMT_YUV411P: | 
					
						
							|  |  |  |         colorspace = " C411 XYSCSS=411"; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case PIX_FMT_YUV420P: | 
					
						
							| 
									
										
										
										
											2009-05-11 04:35:15 +00:00
										 |  |  |         colorspace = (st->codec->chroma_sample_location == AVCHROMA_LOC_TOPLEFT)?" C420paldv XYSCSS=420PALDV": | 
					
						
							|  |  |  |                      (st->codec->chroma_sample_location == AVCHROMA_LOC_LEFT)   ?" C420mpeg2 XYSCSS=420MPEG2": | 
					
						
							|  |  |  |                      " C420jpeg XYSCSS=420JPEG"; | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case PIX_FMT_YUV422P: | 
					
						
							|  |  |  |         colorspace = " C422 XYSCSS=422"; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case PIX_FMT_YUV444P: | 
					
						
							|  |  |  |         colorspace = " C444 XYSCSS=444"; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  |     /* construct stream header, if this is the first frame */ | 
					
						
							| 
									
										
										
										
											2003-10-18 03:19:44 +00:00
										 |  |  |     n = snprintf(buf, Y4M_LINE_MAX, "%s W%d H%d F%d:%d I%c A%d:%d%s\n", | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  |                  Y4M_MAGIC, | 
					
						
							|  |  |  |                  width, | 
					
						
							|  |  |  |                  height, | 
					
						
							|  |  |  |                  raten, rated, | 
					
						
							| 
									
										
										
										
											2003-10-18 03:19:44 +00:00
										 |  |  |                  inter, | 
					
						
							|  |  |  |                  aspectn, aspectd, | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |                  colorspace); | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-10-18 03:19:44 +00:00
										 |  |  |     return n; | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-29 02:06:32 +00:00
										 |  |  | static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt) | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2004-05-29 02:06:32 +00:00
										 |  |  |     AVStream *st = s->streams[pkt->stream_index]; | 
					
						
							| 
									
										
										
										
											2011-02-20 11:04:12 +01:00
										 |  |  |     AVIOContext *pb = s->pb; | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  |     AVPicture *picture; | 
					
						
							| 
									
										
										
										
											2003-10-18 03:19:44 +00:00
										 |  |  |     int* first_pkt = s->priv_data; | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |     int width, height, h_chroma_shift, v_chroma_shift; | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  |     int i, m; | 
					
						
							| 
									
										
										
										
											2003-10-18 03:19:44 +00:00
										 |  |  |     char buf2[Y4M_LINE_MAX+1]; | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  |     char buf1[20]; | 
					
						
							| 
									
										
										
										
											2003-02-11 16:35:48 +00:00
										 |  |  |     uint8_t *ptr, *ptr1, *ptr2; | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-29 02:06:32 +00:00
										 |  |  |     picture = (AVPicture *)pkt->data; | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-10-18 03:19:44 +00:00
										 |  |  |     /* for the first packet we have to output the header as well */ | 
					
						
							|  |  |  |     if (*first_pkt) { | 
					
						
							|  |  |  |         *first_pkt = 0; | 
					
						
							| 
									
										
										
										
											2005-12-22 01:10:11 +00:00
										 |  |  |         if (yuv4_generate_header(s, buf2) < 0) { | 
					
						
							|  |  |  |             av_log(s, AV_LOG_ERROR, "Error. YUV4MPEG stream header write failed.\n"); | 
					
						
							| 
									
										
										
										
											2007-07-19 15:23:32 +00:00
										 |  |  |             return AVERROR(EIO); | 
					
						
							| 
									
										
										
										
											2005-12-22 01:10:11 +00:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             put_buffer(pb, buf2, strlen(buf2)); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2003-10-18 03:19:44 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  |     /* construct frame header */ | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-09-25 08:38:16 +00:00
										 |  |  |     m = snprintf(buf1, sizeof(buf1), "%s\n", Y4M_FRAME_MAGIC); | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  |     put_buffer(pb, buf1, strlen(buf1)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-17 22:24:36 +00:00
										 |  |  |     width = st->codec->width; | 
					
						
							|  |  |  |     height = st->codec->height; | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  |     ptr = picture->data[0]; | 
					
						
							|  |  |  |     for(i=0;i<height;i++) { | 
					
						
							|  |  |  |         put_buffer(pb, ptr, width); | 
					
						
							|  |  |  |         ptr += picture->linesize[0]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-17 22:24:36 +00:00
										 |  |  |     if (st->codec->pix_fmt != PIX_FMT_GRAY8){ | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |     // Adjust for smaller Cb and Cr planes
 | 
					
						
							| 
									
										
										
										
											2005-07-17 22:24:36 +00:00
										 |  |  |     avcodec_get_chroma_sub_sample(st->codec->pix_fmt, &h_chroma_shift, &v_chroma_shift); | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |     width >>= h_chroma_shift; | 
					
						
							|  |  |  |     height >>= v_chroma_shift; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  |     ptr1 = picture->data[1]; | 
					
						
							|  |  |  |     ptr2 = picture->data[2]; | 
					
						
							| 
									
										
										
										
											2005-12-22 01:10:11 +00:00
										 |  |  |     for(i=0;i<height;i++) {     /* Cb */ | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  |         put_buffer(pb, ptr1, width); | 
					
						
							|  |  |  |         ptr1 += picture->linesize[1]; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2005-12-22 01:10:11 +00:00
										 |  |  |     for(i=0;i<height;i++) {     /* Cr */ | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  |         put_buffer(pb, ptr2, width); | 
					
						
							|  |  |  |             ptr2 += picture->linesize[2]; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2005-01-19 12:27:48 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  |     put_flush_packet(pb); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-10-18 03:19:44 +00:00
										 |  |  | static int yuv4_write_header(AVFormatContext *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int* first_pkt = s->priv_data; | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-10-18 03:19:44 +00:00
										 |  |  |     if (s->nb_streams != 1) | 
					
						
							| 
									
										
										
										
											2007-07-19 15:23:32 +00:00
										 |  |  |         return AVERROR(EIO); | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-17 22:24:36 +00:00
										 |  |  |     if (s->streams[0]->codec->pix_fmt == PIX_FMT_YUV411P) { | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |         av_log(s, AV_LOG_ERROR, "Warning: generating rarely used 4:1:1 YUV stream, some mjpegtools might not work.\n"); | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else if ((s->streams[0]->codec->pix_fmt != PIX_FMT_YUV420P) && | 
					
						
							|  |  |  |              (s->streams[0]->codec->pix_fmt != PIX_FMT_YUV422P) && | 
					
						
							|  |  |  |              (s->streams[0]->codec->pix_fmt != PIX_FMT_GRAY8) && | 
					
						
							| 
									
										
										
										
											2005-07-17 22:24:36 +00:00
										 |  |  |              (s->streams[0]->codec->pix_fmt != PIX_FMT_YUV444P)) { | 
					
						
							| 
									
										
										
										
											2005-01-19 12:27:48 +00:00
										 |  |  |         av_log(s, AV_LOG_ERROR, "ERROR: yuv4mpeg only handles yuv444p, yuv422p, yuv420p, yuv411p and gray pixel formats. Use -pix_fmt to select one.\n"); | 
					
						
							| 
									
										
										
										
											2007-07-19 15:23:32 +00:00
										 |  |  |         return AVERROR(EIO); | 
					
						
							| 
									
										
										
										
											2003-10-18 03:19:44 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-10-18 03:19:44 +00:00
										 |  |  |     *first_pkt = 1; | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-25 22:03:28 +00:00
										 |  |  | AVOutputFormat ff_yuv4mpegpipe_muxer = { | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  |     "yuv4mpegpipe", | 
					
						
							| 
									
										
										
										
											2008-06-03 16:20:54 +00:00
										 |  |  |     NULL_IF_CONFIG_SMALL("YUV4MPEG pipe format"), | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  |     "", | 
					
						
							| 
									
										
										
										
											2005-04-26 09:06:39 +00:00
										 |  |  |     "y4m", | 
					
						
							| 
									
										
										
										
											2003-10-18 03:19:44 +00:00
										 |  |  |     sizeof(int), | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  |     CODEC_ID_NONE, | 
					
						
							|  |  |  |     CODEC_ID_RAWVIDEO, | 
					
						
							|  |  |  |     yuv4_write_header, | 
					
						
							|  |  |  |     yuv4_write_packet, | 
					
						
							|  |  |  |     .flags = AVFMT_RAWPICTURE, | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2006-07-10 21:14:37 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2003-01-11 04:58:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-08-29 20:51:10 +00:00
										 |  |  | /* Header size increased to allow room for optional flags */ | 
					
						
							|  |  |  | #define MAX_YUV4_HEADER 80
 | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  | #define MAX_FRAME_HEADER 80
 | 
					
						
							| 
									
										
										
										
											2003-08-05 09:32:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static int yuv4_read_header(AVFormatContext *s, AVFormatParameters *ap) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |     char header[MAX_YUV4_HEADER+10];  // Include headroom for the longest option
 | 
					
						
							|  |  |  |     char *tokstart,*tokend,*header_end; | 
					
						
							| 
									
										
										
										
											2003-08-05 09:32:31 +00:00
										 |  |  |     int i; | 
					
						
							| 
									
										
										
										
											2011-02-20 11:04:12 +01:00
										 |  |  |     AVIOContext *pb = s->pb; | 
					
						
							| 
									
										
										
										
											2006-02-08 11:54:05 +00:00
										 |  |  |     int width=-1, height=-1, raten=0, rated=0, aspectn=0, aspectd=0; | 
					
						
							| 
									
										
										
										
											2005-04-26 08:57:41 +00:00
										 |  |  |     enum PixelFormat pix_fmt=PIX_FMT_NONE,alt_pix_fmt=PIX_FMT_NONE; | 
					
						
							| 
									
										
										
										
											2009-05-11 04:35:15 +00:00
										 |  |  |     enum AVChromaLocation chroma_sample_location = AVCHROMA_LOC_UNSPECIFIED; | 
					
						
							| 
									
										
										
										
											2003-08-05 09:32:31 +00:00
										 |  |  |     AVStream *st; | 
					
						
							| 
									
										
										
										
											2006-02-08 11:54:05 +00:00
										 |  |  |     struct frame_attributes *s1 = s->priv_data; | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-08-05 09:32:31 +00:00
										 |  |  |     for (i=0; i<MAX_YUV4_HEADER; i++) { | 
					
						
							|  |  |  |         header[i] = get_byte(pb); | 
					
						
							| 
									
										
										
										
											2005-12-22 01:10:11 +00:00
										 |  |  |         if (header[i] == '\n') { | 
					
						
							|  |  |  |             header[i+1] = 0x20;  // Add a space after last option. Makes parsing "444" vs "444alpha" easier.
 | 
					
						
							|  |  |  |             header[i+2] = 0; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2003-08-05 09:32:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (i == MAX_YUV4_HEADER) return -1; | 
					
						
							|  |  |  |     if (strncmp(header, Y4M_MAGIC, strlen(Y4M_MAGIC))) return -1; | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-08 11:54:05 +00:00
										 |  |  |     s1->interlaced_frame = 0; | 
					
						
							|  |  |  |     s1->top_field_first = 0; | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |     header_end = &header[i+1]; // Include space
 | 
					
						
							|  |  |  |     for(tokstart = &header[strlen(Y4M_MAGIC) + 1]; tokstart < header_end; tokstart++) { | 
					
						
							|  |  |  |         if (*tokstart==0x20) continue; | 
					
						
							|  |  |  |         switch (*tokstart++) { | 
					
						
							|  |  |  |         case 'W': // Width. Required.
 | 
					
						
							|  |  |  |             width = strtol(tokstart, &tokend, 10); | 
					
						
							|  |  |  |             tokstart=tokend; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case 'H': // Height. Required.
 | 
					
						
							|  |  |  |             height = strtol(tokstart, &tokend, 10); | 
					
						
							|  |  |  |             tokstart=tokend; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case 'C': // Color space
 | 
					
						
							| 
									
										
										
										
											2009-05-11 04:35:15 +00:00
										 |  |  |             if (strncmp("420jpeg",tokstart,7)==0) { | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |                 pix_fmt = PIX_FMT_YUV420P; | 
					
						
							| 
									
										
										
										
											2009-05-11 04:35:15 +00:00
										 |  |  |                 chroma_sample_location = AVCHROMA_LOC_CENTER; | 
					
						
							|  |  |  |             } else if (strncmp("420mpeg2",tokstart,8)==0) { | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |                 pix_fmt = PIX_FMT_YUV420P; | 
					
						
							| 
									
										
										
										
											2009-05-11 04:35:15 +00:00
										 |  |  |                 chroma_sample_location = AVCHROMA_LOC_LEFT; | 
					
						
							|  |  |  |             } else if (strncmp("420paldv", tokstart, 8)==0) { | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |                 pix_fmt = PIX_FMT_YUV420P; | 
					
						
							| 
									
										
										
										
											2009-05-11 04:35:15 +00:00
										 |  |  |                 chroma_sample_location = AVCHROMA_LOC_TOPLEFT; | 
					
						
							|  |  |  |             } else if (strncmp("411", tokstart, 3)==0) | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |                 pix_fmt = PIX_FMT_YUV411P; | 
					
						
							|  |  |  |             else if (strncmp("422", tokstart, 3)==0) | 
					
						
							|  |  |  |                 pix_fmt = PIX_FMT_YUV422P; | 
					
						
							|  |  |  |             else if (strncmp("444alpha", tokstart, 8)==0) { | 
					
						
							|  |  |  |                 av_log(s, AV_LOG_ERROR, "Cannot handle 4:4:4:4 YUV4MPEG stream.\n"); | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |             } else if (strncmp("444", tokstart, 3)==0) | 
					
						
							|  |  |  |                 pix_fmt = PIX_FMT_YUV444P; | 
					
						
							|  |  |  |             else if (strncmp("mono",tokstart, 4)==0) { | 
					
						
							| 
									
										
										
										
											2005-01-19 12:27:48 +00:00
										 |  |  |                 pix_fmt = PIX_FMT_GRAY8; | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |             } else { | 
					
						
							|  |  |  |                 av_log(s, AV_LOG_ERROR, "YUV4MPEG stream contains an unknown pixel format.\n"); | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             while(tokstart<header_end&&*tokstart!=0x20) tokstart++; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case 'I': // Interlace type
 | 
					
						
							|  |  |  |             switch (*tokstart++){ | 
					
						
							|  |  |  |             case '?': | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case 'p': | 
					
						
							| 
									
										
										
										
											2006-02-08 11:54:05 +00:00
										 |  |  |                 s1->interlaced_frame=0; | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             case 't': | 
					
						
							| 
									
										
										
										
											2006-02-08 11:54:05 +00:00
										 |  |  |                 s1->interlaced_frame=1; | 
					
						
							|  |  |  |                 s1->top_field_first=1; | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             case 'b': | 
					
						
							| 
									
										
										
										
											2006-02-08 11:54:05 +00:00
										 |  |  |                 s1->interlaced_frame=1; | 
					
						
							|  |  |  |                 s1->top_field_first=0; | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             case 'm': | 
					
						
							|  |  |  |                 av_log(s, AV_LOG_ERROR, "YUV4MPEG stream contains mixed interlaced and non-interlaced frames.\n"); | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 av_log(s, AV_LOG_ERROR, "YUV4MPEG has invalid header.\n"); | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case 'F': // Frame rate
 | 
					
						
							|  |  |  |             sscanf(tokstart,"%d:%d",&raten,&rated); // 0:0 if unknown
 | 
					
						
							|  |  |  |             while(tokstart<header_end&&*tokstart!=0x20) tokstart++; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case 'A': // Pixel aspect
 | 
					
						
							|  |  |  |             sscanf(tokstart,"%d:%d",&aspectn,&aspectd); // 0:0 if unknown
 | 
					
						
							|  |  |  |             while(tokstart<header_end&&*tokstart!=0x20) tokstart++; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case 'X': // Vendor extensions
 | 
					
						
							|  |  |  |             if (strncmp("YSCSS=",tokstart,6)==0) { | 
					
						
							|  |  |  |                 // Older nonstandard pixel format representation
 | 
					
						
							|  |  |  |                 tokstart+=6; | 
					
						
							|  |  |  |                 if (strncmp("420JPEG",tokstart,7)==0) | 
					
						
							|  |  |  |                     alt_pix_fmt=PIX_FMT_YUV420P; | 
					
						
							|  |  |  |                 else if (strncmp("420MPEG2",tokstart,8)==0) | 
					
						
							|  |  |  |                     alt_pix_fmt=PIX_FMT_YUV420P; | 
					
						
							|  |  |  |                 else if (strncmp("420PALDV",tokstart,8)==0) | 
					
						
							|  |  |  |                     alt_pix_fmt=PIX_FMT_YUV420P; | 
					
						
							|  |  |  |                 else if (strncmp("411",tokstart,3)==0) | 
					
						
							|  |  |  |                     alt_pix_fmt=PIX_FMT_YUV411P; | 
					
						
							|  |  |  |                 else if (strncmp("422",tokstart,3)==0) | 
					
						
							|  |  |  |                     alt_pix_fmt=PIX_FMT_YUV422P; | 
					
						
							|  |  |  |                 else if (strncmp("444",tokstart,3)==0) | 
					
						
							|  |  |  |                     alt_pix_fmt=PIX_FMT_YUV444P; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             while(tokstart<header_end&&*tokstart!=0x20) tokstart++; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if ((width == -1) || (height == -1)) { | 
					
						
							|  |  |  |         av_log(s, AV_LOG_ERROR, "YUV4MPEG has invalid header.\n"); | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-26 08:57:41 +00:00
										 |  |  |     if (pix_fmt == PIX_FMT_NONE) { | 
					
						
							|  |  |  |         if (alt_pix_fmt == PIX_FMT_NONE) | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |             pix_fmt = PIX_FMT_YUV420P; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             pix_fmt = alt_pix_fmt; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-02 05:01:46 +00:00
										 |  |  |     if (raten <= 0 || rated <= 0) { | 
					
						
							| 
									
										
										
										
											2005-01-04 01:55:50 +00:00
										 |  |  |         // Frame rate unknown
 | 
					
						
							|  |  |  |         raten = 25; | 
					
						
							|  |  |  |         rated = 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (aspectn == 0 && aspectd == 0) { | 
					
						
							|  |  |  |         // Pixel aspect unknown
 | 
					
						
							|  |  |  |         aspectd = 1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-08-05 09:32:31 +00:00
										 |  |  |     st = av_new_stream(s, 0); | 
					
						
							| 
									
										
										
										
											2008-05-28 01:57:19 +00:00
										 |  |  |     if(!st) | 
					
						
							| 
									
										
										
										
											2008-05-29 15:40:16 +00:00
										 |  |  |         return AVERROR(ENOMEM); | 
					
						
							| 
									
										
										
										
											2005-07-17 22:24:36 +00:00
										 |  |  |     st->codec->width = width; | 
					
						
							|  |  |  |     st->codec->height = height; | 
					
						
							| 
									
										
										
										
											2003-08-05 09:32:31 +00:00
										 |  |  |     av_reduce(&raten, &rated, raten, rated, (1UL<<31)-1); | 
					
						
							| 
									
										
										
										
											2005-04-30 21:43:59 +00:00
										 |  |  |     av_set_pts_info(st, 64, rated, raten); | 
					
						
							| 
									
										
										
										
											2005-07-17 22:24:36 +00:00
										 |  |  |     st->codec->pix_fmt = pix_fmt; | 
					
						
							| 
									
										
										
										
											2010-03-30 23:30:55 +00:00
										 |  |  |     st->codec->codec_type = AVMEDIA_TYPE_VIDEO; | 
					
						
							| 
									
										
										
										
											2005-07-17 22:24:36 +00:00
										 |  |  |     st->codec->codec_id = CODEC_ID_RAWVIDEO; | 
					
						
							| 
									
										
										
										
											2008-08-23 23:43:20 +00:00
										 |  |  |     st->sample_aspect_ratio= (AVRational){aspectn, aspectd}; | 
					
						
							| 
									
										
										
										
											2009-05-11 04:35:15 +00:00
										 |  |  |     st->codec->chroma_sample_location = chroma_sample_location; | 
					
						
							| 
									
										
										
										
											2003-08-05 09:32:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int yuv4_read_packet(AVFormatContext *s, AVPacket *pkt) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  |     char header[MAX_FRAME_HEADER+1]; | 
					
						
							| 
									
										
										
										
											2005-08-14 15:42:40 +00:00
										 |  |  |     int packet_size, width, height; | 
					
						
							| 
									
										
										
										
											2003-08-05 09:32:31 +00:00
										 |  |  |     AVStream *st = s->streams[0]; | 
					
						
							| 
									
										
										
										
											2006-02-08 11:54:05 +00:00
										 |  |  |     struct frame_attributes *s1 = s->priv_data; | 
					
						
							| 
									
										
										
										
											2003-08-05 09:32:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (i=0; i<MAX_FRAME_HEADER; i++) { | 
					
						
							| 
									
										
										
										
											2007-11-21 07:41:00 +00:00
										 |  |  |         header[i] = get_byte(s->pb); | 
					
						
							| 
									
										
										
										
											2005-12-22 01:10:11 +00:00
										 |  |  |         if (header[i] == '\n') { | 
					
						
							|  |  |  |             header[i+1] = 0; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2003-08-05 09:32:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (i == MAX_FRAME_HEADER) return -1; | 
					
						
							|  |  |  |     if (strncmp(header, Y4M_FRAME_MAGIC, strlen(Y4M_FRAME_MAGIC))) return -1; | 
					
						
							| 
									
										
										
										
											2005-12-17 18:14:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-17 22:24:36 +00:00
										 |  |  |     width = st->codec->width; | 
					
						
							|  |  |  |     height = st->codec->height; | 
					
						
							| 
									
										
										
										
											2003-08-05 09:32:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-17 22:24:36 +00:00
										 |  |  |     packet_size = avpicture_get_size(st->codec->pix_fmt, width, height); | 
					
						
							| 
									
										
										
										
											2003-08-05 09:32:31 +00:00
										 |  |  |     if (packet_size < 0) | 
					
						
							| 
									
										
										
										
											2004-10-01 13:16:16 +00:00
										 |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2003-08-05 09:32:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-21 07:41:00 +00:00
										 |  |  |     if (av_get_packet(s->pb, pkt, packet_size) != packet_size) | 
					
						
							| 
									
										
										
										
											2007-07-19 15:23:32 +00:00
										 |  |  |         return AVERROR(EIO); | 
					
						
							| 
									
										
										
										
											2003-08-05 09:32:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-08 11:54:05 +00:00
										 |  |  |     if (s->streams[0]->codec->coded_frame) { | 
					
						
							|  |  |  |         s->streams[0]->codec->coded_frame->interlaced_frame = s1->interlaced_frame; | 
					
						
							|  |  |  |         s->streams[0]->codec->coded_frame->top_field_first = s1->top_field_first; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-08-05 09:32:31 +00:00
										 |  |  |     pkt->stream_index = 0; | 
					
						
							| 
									
										
										
										
											2005-05-26 20:17:12 +00:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2003-08-05 09:32:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-26 09:06:39 +00:00
										 |  |  | static int yuv4_probe(AVProbeData *pd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /* check file header */ | 
					
						
							|  |  |  |     if (strncmp(pd->buf, Y4M_MAGIC, sizeof(Y4M_MAGIC)-1)==0) | 
					
						
							|  |  |  |         return AVPROBE_SCORE_MAX; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-13 23:44:16 +00:00
										 |  |  | #if CONFIG_YUV4MPEGPIPE_DEMUXER
 | 
					
						
							| 
									
										
										
										
											2011-01-25 22:03:28 +00:00
										 |  |  | AVInputFormat ff_yuv4mpegpipe_demuxer = { | 
					
						
							| 
									
										
										
										
											2003-08-05 09:32:31 +00:00
										 |  |  |     "yuv4mpegpipe", | 
					
						
							| 
									
										
										
										
											2008-06-03 16:20:54 +00:00
										 |  |  |     NULL_IF_CONFIG_SMALL("YUV4MPEG pipe format"), | 
					
						
							| 
									
										
										
										
											2006-02-08 11:54:05 +00:00
										 |  |  |     sizeof(struct frame_attributes), | 
					
						
							| 
									
										
										
										
											2005-04-26 09:06:39 +00:00
										 |  |  |     yuv4_probe, | 
					
						
							| 
									
										
										
										
											2003-08-05 09:32:31 +00:00
										 |  |  |     yuv4_read_header, | 
					
						
							|  |  |  |     yuv4_read_packet, | 
					
						
							| 
									
										
										
										
											2005-04-26 09:06:39 +00:00
										 |  |  |     .extensions = "y4m" | 
					
						
							| 
									
										
										
										
											2003-08-05 09:32:31 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2006-07-10 21:14:37 +00:00
										 |  |  | #endif
 |