annotate ffmpeg/libavformat/yuv4mpeg.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /*
yading@11 2 * YUV4MPEG format
yading@11 3 * Copyright (c) 2001, 2002, 2003 Fabrice Bellard
yading@11 4 *
yading@11 5 * This file is part of FFmpeg.
yading@11 6 *
yading@11 7 * FFmpeg is free software; you can redistribute it and/or
yading@11 8 * modify it under the terms of the GNU Lesser General Public
yading@11 9 * License as published by the Free Software Foundation; either
yading@11 10 * version 2.1 of the License, or (at your option) any later version.
yading@11 11 *
yading@11 12 * FFmpeg is distributed in the hope that it will be useful,
yading@11 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 15 * Lesser General Public License for more details.
yading@11 16 *
yading@11 17 * You should have received a copy of the GNU Lesser General Public
yading@11 18 * License along with FFmpeg; if not, write to the Free Software
yading@11 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 20 */
yading@11 21
yading@11 22 #include "libavutil/pixdesc.h"
yading@11 23 #include "avformat.h"
yading@11 24 #include "internal.h"
yading@11 25 #include "libavutil/pixdesc.h"
yading@11 26
yading@11 27 #define Y4M_MAGIC "YUV4MPEG2"
yading@11 28 #define Y4M_FRAME_MAGIC "FRAME"
yading@11 29 #define Y4M_LINE_MAX 256
yading@11 30
yading@11 31 #if CONFIG_YUV4MPEGPIPE_MUXER
yading@11 32 static int yuv4_generate_header(AVFormatContext *s, char* buf)
yading@11 33 {
yading@11 34 AVStream *st;
yading@11 35 int width, height;
yading@11 36 int raten, rated, aspectn, aspectd, n;
yading@11 37 char inter;
yading@11 38 const char *colorspace = "";
yading@11 39
yading@11 40 st = s->streams[0];
yading@11 41 width = st->codec->width;
yading@11 42 height = st->codec->height;
yading@11 43
yading@11 44 av_reduce(&raten, &rated, st->codec->time_base.den,
yading@11 45 st->codec->time_base.num, (1UL << 31) - 1);
yading@11 46
yading@11 47 aspectn = st->sample_aspect_ratio.num;
yading@11 48 aspectd = st->sample_aspect_ratio.den;
yading@11 49
yading@11 50 if (aspectn == 0 && aspectd == 1)
yading@11 51 aspectd = 0; // 0:0 means unknown
yading@11 52
yading@11 53 inter = 'p'; /* progressive is the default */
yading@11 54 if (st->codec->coded_frame && st->codec->coded_frame->interlaced_frame)
yading@11 55 inter = st->codec->coded_frame->top_field_first ? 't' : 'b';
yading@11 56 if (st->codec->field_order == AV_FIELD_PROGRESSIVE) {
yading@11 57 inter = 'p';
yading@11 58 } else if (st->codec->field_order == AV_FIELD_TB || st->codec->field_order == AV_FIELD_TT) {
yading@11 59 inter = 't';
yading@11 60 } else if (st->codec->field_order == AV_FIELD_BT || st->codec->field_order == AV_FIELD_BB) {
yading@11 61 inter = 'b';
yading@11 62 }
yading@11 63
yading@11 64 switch (st->codec->pix_fmt) {
yading@11 65 case AV_PIX_FMT_GRAY8:
yading@11 66 colorspace = " Cmono";
yading@11 67 break;
yading@11 68 case AV_PIX_FMT_GRAY16:
yading@11 69 colorspace = " Cmono16";
yading@11 70 break;
yading@11 71 case AV_PIX_FMT_YUV411P:
yading@11 72 colorspace = " C411 XYSCSS=411";
yading@11 73 break;
yading@11 74 case AV_PIX_FMT_YUV420P:
yading@11 75 switch (st->codec->chroma_sample_location) {
yading@11 76 case AVCHROMA_LOC_TOPLEFT: colorspace = " C420paldv XYSCSS=420PALDV"; break;
yading@11 77 case AVCHROMA_LOC_LEFT: colorspace = " C420mpeg2 XYSCSS=420MPEG2"; break;
yading@11 78 default: colorspace = " C420jpeg XYSCSS=420JPEG"; break;
yading@11 79 }
yading@11 80 break;
yading@11 81 case AV_PIX_FMT_YUV422P:
yading@11 82 colorspace = " C422 XYSCSS=422";
yading@11 83 break;
yading@11 84 case AV_PIX_FMT_YUV444P:
yading@11 85 colorspace = " C444 XYSCSS=444";
yading@11 86 break;
yading@11 87 case AV_PIX_FMT_YUV420P9:
yading@11 88 colorspace = " C420p9 XYSCSS=420P9";
yading@11 89 break;
yading@11 90 case AV_PIX_FMT_YUV422P9:
yading@11 91 colorspace = " C422p9 XYSCSS=422P9";
yading@11 92 break;
yading@11 93 case AV_PIX_FMT_YUV444P9:
yading@11 94 colorspace = " C444p9 XYSCSS=444P9";
yading@11 95 break;
yading@11 96 case AV_PIX_FMT_YUV420P10:
yading@11 97 colorspace = " C420p10 XYSCSS=420P10";
yading@11 98 break;
yading@11 99 case AV_PIX_FMT_YUV422P10:
yading@11 100 colorspace = " C422p10 XYSCSS=422P10";
yading@11 101 break;
yading@11 102 case AV_PIX_FMT_YUV444P10:
yading@11 103 colorspace = " C444p10 XYSCSS=444P10";
yading@11 104 break;
yading@11 105 case AV_PIX_FMT_YUV420P12:
yading@11 106 colorspace = " C420p12 XYSCSS=420P12";
yading@11 107 break;
yading@11 108 case AV_PIX_FMT_YUV422P12:
yading@11 109 colorspace = " C422p12 XYSCSS=422P12";
yading@11 110 break;
yading@11 111 case AV_PIX_FMT_YUV444P12:
yading@11 112 colorspace = " C444p12 XYSCSS=444P12";
yading@11 113 break;
yading@11 114 case AV_PIX_FMT_YUV420P14:
yading@11 115 colorspace = " C420p14 XYSCSS=420P14";
yading@11 116 break;
yading@11 117 case AV_PIX_FMT_YUV422P14:
yading@11 118 colorspace = " C422p14 XYSCSS=422P14";
yading@11 119 break;
yading@11 120 case AV_PIX_FMT_YUV444P14:
yading@11 121 colorspace = " C444p14 XYSCSS=444P14";
yading@11 122 break;
yading@11 123 case AV_PIX_FMT_YUV420P16:
yading@11 124 colorspace = " C420p16 XYSCSS=420P16";
yading@11 125 break;
yading@11 126 case AV_PIX_FMT_YUV422P16:
yading@11 127 colorspace = " C422p16 XYSCSS=422P16";
yading@11 128 break;
yading@11 129 case AV_PIX_FMT_YUV444P16:
yading@11 130 colorspace = " C444p16 XYSCSS=444P16";
yading@11 131 break;
yading@11 132 }
yading@11 133
yading@11 134 /* construct stream header, if this is the first frame */
yading@11 135 n = snprintf(buf, Y4M_LINE_MAX, "%s W%d H%d F%d:%d I%c A%d:%d%s\n",
yading@11 136 Y4M_MAGIC, width, height, raten, rated, inter,
yading@11 137 aspectn, aspectd, colorspace);
yading@11 138
yading@11 139 return n;
yading@11 140 }
yading@11 141
yading@11 142 static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt)
yading@11 143 {
yading@11 144 AVStream *st = s->streams[pkt->stream_index];
yading@11 145 AVIOContext *pb = s->pb;
yading@11 146 AVPicture *picture, picture_tmp;
yading@11 147 int* first_pkt = s->priv_data;
yading@11 148 int width, height, h_chroma_shift, v_chroma_shift;
yading@11 149 int i;
yading@11 150 char buf2[Y4M_LINE_MAX + 1];
yading@11 151 char buf1[20];
yading@11 152 uint8_t *ptr, *ptr1, *ptr2;
yading@11 153
yading@11 154 memcpy(&picture_tmp, pkt->data, sizeof(AVPicture));
yading@11 155 picture = &picture_tmp;
yading@11 156
yading@11 157 /* for the first packet we have to output the header as well */
yading@11 158 if (*first_pkt) {
yading@11 159 *first_pkt = 0;
yading@11 160 if (yuv4_generate_header(s, buf2) < 0) {
yading@11 161 av_log(s, AV_LOG_ERROR,
yading@11 162 "Error. YUV4MPEG stream header write failed.\n");
yading@11 163 return AVERROR(EIO);
yading@11 164 } else {
yading@11 165 avio_write(pb, buf2, strlen(buf2));
yading@11 166 }
yading@11 167 }
yading@11 168
yading@11 169 /* construct frame header */
yading@11 170
yading@11 171 snprintf(buf1, sizeof(buf1), "%s\n", Y4M_FRAME_MAGIC);
yading@11 172 avio_write(pb, buf1, strlen(buf1));
yading@11 173
yading@11 174 width = st->codec->width;
yading@11 175 height = st->codec->height;
yading@11 176
yading@11 177 ptr = picture->data[0];
yading@11 178
yading@11 179 switch (st->codec->pix_fmt) {
yading@11 180 case AV_PIX_FMT_GRAY8:
yading@11 181 case AV_PIX_FMT_YUV411P:
yading@11 182 case AV_PIX_FMT_YUV420P:
yading@11 183 case AV_PIX_FMT_YUV422P:
yading@11 184 case AV_PIX_FMT_YUV444P:
yading@11 185 break;
yading@11 186 case AV_PIX_FMT_GRAY16:
yading@11 187 case AV_PIX_FMT_YUV420P9:
yading@11 188 case AV_PIX_FMT_YUV422P9:
yading@11 189 case AV_PIX_FMT_YUV444P9:
yading@11 190 case AV_PIX_FMT_YUV420P10:
yading@11 191 case AV_PIX_FMT_YUV422P10:
yading@11 192 case AV_PIX_FMT_YUV444P10:
yading@11 193 case AV_PIX_FMT_YUV420P12:
yading@11 194 case AV_PIX_FMT_YUV422P12:
yading@11 195 case AV_PIX_FMT_YUV444P12:
yading@11 196 case AV_PIX_FMT_YUV420P14:
yading@11 197 case AV_PIX_FMT_YUV422P14:
yading@11 198 case AV_PIX_FMT_YUV444P14:
yading@11 199 case AV_PIX_FMT_YUV420P16:
yading@11 200 case AV_PIX_FMT_YUV422P16:
yading@11 201 case AV_PIX_FMT_YUV444P16:
yading@11 202 width *= 2;
yading@11 203 break;
yading@11 204 default:
yading@11 205 av_log(s, AV_LOG_ERROR, "The pixel format '%s' is not supported.\n",
yading@11 206 av_get_pix_fmt_name(st->codec->pix_fmt));
yading@11 207 return AVERROR(EINVAL);
yading@11 208 }
yading@11 209
yading@11 210 for (i = 0; i < height; i++) {
yading@11 211 avio_write(pb, ptr, width);
yading@11 212 ptr += picture->linesize[0];
yading@11 213 }
yading@11 214
yading@11 215 if (st->codec->pix_fmt != AV_PIX_FMT_GRAY8 &&
yading@11 216 st->codec->pix_fmt != AV_PIX_FMT_GRAY16) {
yading@11 217 // Adjust for smaller Cb and Cr planes
yading@11 218 av_pix_fmt_get_chroma_sub_sample(st->codec->pix_fmt, &h_chroma_shift,
yading@11 219 &v_chroma_shift);
yading@11 220 width >>= h_chroma_shift;
yading@11 221 height >>= v_chroma_shift;
yading@11 222
yading@11 223 ptr1 = picture->data[1];
yading@11 224 ptr2 = picture->data[2];
yading@11 225 for (i = 0; i < height; i++) { /* Cb */
yading@11 226 avio_write(pb, ptr1, width);
yading@11 227 ptr1 += picture->linesize[1];
yading@11 228 }
yading@11 229 for (i = 0; i < height; i++) { /* Cr */
yading@11 230 avio_write(pb, ptr2, width);
yading@11 231 ptr2 += picture->linesize[2];
yading@11 232 }
yading@11 233 }
yading@11 234
yading@11 235 return 0;
yading@11 236 }
yading@11 237
yading@11 238 static int yuv4_write_header(AVFormatContext *s)
yading@11 239 {
yading@11 240 int *first_pkt = s->priv_data;
yading@11 241
yading@11 242 if (s->nb_streams != 1)
yading@11 243 return AVERROR(EIO);
yading@11 244
yading@11 245 if (s->streams[0]->codec->codec_id != AV_CODEC_ID_RAWVIDEO) {
yading@11 246 av_log(s, AV_LOG_ERROR, "ERROR: Only rawvideo supported.\n");
yading@11 247 return AVERROR_INVALIDDATA;
yading@11 248 }
yading@11 249
yading@11 250 switch (s->streams[0]->codec->pix_fmt) {
yading@11 251 case AV_PIX_FMT_YUV411P:
yading@11 252 av_log(s, AV_LOG_WARNING, "Warning: generating rarely used 4:1:1 YUV "
yading@11 253 "stream, some mjpegtools might not work.\n");
yading@11 254 break;
yading@11 255 case AV_PIX_FMT_GRAY8:
yading@11 256 case AV_PIX_FMT_GRAY16:
yading@11 257 case AV_PIX_FMT_YUV420P:
yading@11 258 case AV_PIX_FMT_YUV422P:
yading@11 259 case AV_PIX_FMT_YUV444P:
yading@11 260 break;
yading@11 261 case AV_PIX_FMT_YUV420P9:
yading@11 262 case AV_PIX_FMT_YUV422P9:
yading@11 263 case AV_PIX_FMT_YUV444P9:
yading@11 264 case AV_PIX_FMT_YUV420P10:
yading@11 265 case AV_PIX_FMT_YUV422P10:
yading@11 266 case AV_PIX_FMT_YUV444P10:
yading@11 267 case AV_PIX_FMT_YUV420P12:
yading@11 268 case AV_PIX_FMT_YUV422P12:
yading@11 269 case AV_PIX_FMT_YUV444P12:
yading@11 270 case AV_PIX_FMT_YUV420P14:
yading@11 271 case AV_PIX_FMT_YUV422P14:
yading@11 272 case AV_PIX_FMT_YUV444P14:
yading@11 273 case AV_PIX_FMT_YUV420P16:
yading@11 274 case AV_PIX_FMT_YUV422P16:
yading@11 275 case AV_PIX_FMT_YUV444P16:
yading@11 276 if (s->streams[0]->codec->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {
yading@11 277 av_log(s, AV_LOG_ERROR, "'%s' is not a official yuv4mpegpipe pixel format. "
yading@11 278 "Use '-strict -1' to encode to this pixel format.\n",
yading@11 279 av_get_pix_fmt_name(s->streams[0]->codec->pix_fmt));
yading@11 280 return AVERROR(EINVAL);
yading@11 281 }
yading@11 282 av_log(s, AV_LOG_WARNING, "Warning: generating non standard YUV stream. "
yading@11 283 "Mjpegtools will not work.\n");
yading@11 284 break;
yading@11 285 default:
yading@11 286 av_log(s, AV_LOG_ERROR, "ERROR: yuv4mpeg can only handle "
yading@11 287 "yuv444p, yuv422p, yuv420p, yuv411p and gray8 pixel formats. "
yading@11 288 "And using 'strict -1' also yuv444p9, yuv422p9, yuv420p9, "
yading@11 289 "yuv444p10, yuv422p10, yuv420p10, "
yading@11 290 "yuv444p12, yuv422p12, yuv420p12, "
yading@11 291 "yuv444p14, yuv422p14, yuv420p14, "
yading@11 292 "yuv444p16, yuv422p16, yuv420p16 "
yading@11 293 "and gray16 pixel formats. "
yading@11 294 "Use -pix_fmt to select one.\n");
yading@11 295 return AVERROR(EIO);
yading@11 296 }
yading@11 297
yading@11 298 *first_pkt = 1;
yading@11 299 return 0;
yading@11 300 }
yading@11 301
yading@11 302 AVOutputFormat ff_yuv4mpegpipe_muxer = {
yading@11 303 .name = "yuv4mpegpipe",
yading@11 304 .long_name = NULL_IF_CONFIG_SMALL("YUV4MPEG pipe"),
yading@11 305 .extensions = "y4m",
yading@11 306 .priv_data_size = sizeof(int),
yading@11 307 .audio_codec = AV_CODEC_ID_NONE,
yading@11 308 .video_codec = AV_CODEC_ID_RAWVIDEO,
yading@11 309 .write_header = yuv4_write_header,
yading@11 310 .write_packet = yuv4_write_packet,
yading@11 311 .flags = AVFMT_RAWPICTURE,
yading@11 312 };
yading@11 313 #endif
yading@11 314
yading@11 315 /* Header size increased to allow room for optional flags */
yading@11 316 #define MAX_YUV4_HEADER 80
yading@11 317 #define MAX_FRAME_HEADER 80
yading@11 318
yading@11 319 static int yuv4_read_header(AVFormatContext *s)
yading@11 320 {
yading@11 321 char header[MAX_YUV4_HEADER + 10]; // Include headroom for
yading@11 322 // the longest option
yading@11 323 char *tokstart, *tokend, *header_end, interlaced = '?';
yading@11 324 int i;
yading@11 325 AVIOContext *pb = s->pb;
yading@11 326 int width = -1, height = -1, raten = 0,
yading@11 327 rated = 0, aspectn = 0, aspectd = 0;
yading@11 328 enum AVPixelFormat pix_fmt = AV_PIX_FMT_NONE, alt_pix_fmt = AV_PIX_FMT_NONE;
yading@11 329 enum AVChromaLocation chroma_sample_location = AVCHROMA_LOC_UNSPECIFIED;
yading@11 330 AVStream *st;
yading@11 331
yading@11 332 for (i = 0; i < MAX_YUV4_HEADER; i++) {
yading@11 333 header[i] = avio_r8(pb);
yading@11 334 if (header[i] == '\n') {
yading@11 335 header[i + 1] = 0x20; // Add a space after last option.
yading@11 336 // Makes parsing "444" vs "444alpha" easier.
yading@11 337 header[i + 2] = 0;
yading@11 338 break;
yading@11 339 }
yading@11 340 }
yading@11 341 if (i == MAX_YUV4_HEADER)
yading@11 342 return -1;
yading@11 343 if (strncmp(header, Y4M_MAGIC, strlen(Y4M_MAGIC)))
yading@11 344 return -1;
yading@11 345
yading@11 346 header_end = &header[i + 1]; // Include space
yading@11 347 for (tokstart = &header[strlen(Y4M_MAGIC) + 1];
yading@11 348 tokstart < header_end; tokstart++) {
yading@11 349 if (*tokstart == 0x20)
yading@11 350 continue;
yading@11 351 switch (*tokstart++) {
yading@11 352 case 'W': // Width. Required.
yading@11 353 width = strtol(tokstart, &tokend, 10);
yading@11 354 tokstart = tokend;
yading@11 355 break;
yading@11 356 case 'H': // Height. Required.
yading@11 357 height = strtol(tokstart, &tokend, 10);
yading@11 358 tokstart = tokend;
yading@11 359 break;
yading@11 360 case 'C': // Color space
yading@11 361 if (strncmp("420jpeg", tokstart, 7) == 0) {
yading@11 362 pix_fmt = AV_PIX_FMT_YUV420P;
yading@11 363 chroma_sample_location = AVCHROMA_LOC_CENTER;
yading@11 364 } else if (strncmp("420mpeg2", tokstart, 8) == 0) {
yading@11 365 pix_fmt = AV_PIX_FMT_YUV420P;
yading@11 366 chroma_sample_location = AVCHROMA_LOC_LEFT;
yading@11 367 } else if (strncmp("420paldv", tokstart, 8) == 0) {
yading@11 368 pix_fmt = AV_PIX_FMT_YUV420P;
yading@11 369 chroma_sample_location = AVCHROMA_LOC_TOPLEFT;
yading@11 370 } else if (strncmp("420p16", tokstart, 6) == 0) {
yading@11 371 pix_fmt = AV_PIX_FMT_YUV420P16;
yading@11 372 } else if (strncmp("422p16", tokstart, 6) == 0) {
yading@11 373 pix_fmt = AV_PIX_FMT_YUV422P16;
yading@11 374 } else if (strncmp("444p16", tokstart, 6) == 0) {
yading@11 375 pix_fmt = AV_PIX_FMT_YUV444P16;
yading@11 376 } else if (strncmp("420p14", tokstart, 6) == 0) {
yading@11 377 pix_fmt = AV_PIX_FMT_YUV420P14;
yading@11 378 } else if (strncmp("422p14", tokstart, 6) == 0) {
yading@11 379 pix_fmt = AV_PIX_FMT_YUV422P14;
yading@11 380 } else if (strncmp("444p14", tokstart, 6) == 0) {
yading@11 381 pix_fmt = AV_PIX_FMT_YUV444P14;
yading@11 382 } else if (strncmp("420p12", tokstart, 6) == 0) {
yading@11 383 pix_fmt = AV_PIX_FMT_YUV420P12;
yading@11 384 } else if (strncmp("422p12", tokstart, 6) == 0) {
yading@11 385 pix_fmt = AV_PIX_FMT_YUV422P12;
yading@11 386 } else if (strncmp("444p12", tokstart, 6) == 0) {
yading@11 387 pix_fmt = AV_PIX_FMT_YUV444P12;
yading@11 388 } else if (strncmp("420p10", tokstart, 6) == 0) {
yading@11 389 pix_fmt = AV_PIX_FMT_YUV420P10;
yading@11 390 } else if (strncmp("422p10", tokstart, 6) == 0) {
yading@11 391 pix_fmt = AV_PIX_FMT_YUV422P10;
yading@11 392 } else if (strncmp("444p10", tokstart, 6) == 0) {
yading@11 393 pix_fmt = AV_PIX_FMT_YUV444P10;
yading@11 394 } else if (strncmp("420p9", tokstart, 5) == 0) {
yading@11 395 pix_fmt = AV_PIX_FMT_YUV420P9;
yading@11 396 } else if (strncmp("422p9", tokstart, 5) == 0) {
yading@11 397 pix_fmt = AV_PIX_FMT_YUV422P9;
yading@11 398 } else if (strncmp("444p9", tokstart, 5) == 0) {
yading@11 399 pix_fmt = AV_PIX_FMT_YUV444P9;
yading@11 400 } else if (strncmp("420", tokstart, 3) == 0) {
yading@11 401 pix_fmt = AV_PIX_FMT_YUV420P;
yading@11 402 chroma_sample_location = AVCHROMA_LOC_CENTER;
yading@11 403 } else if (strncmp("411", tokstart, 3) == 0) {
yading@11 404 pix_fmt = AV_PIX_FMT_YUV411P;
yading@11 405 } else if (strncmp("422", tokstart, 3) == 0) {
yading@11 406 pix_fmt = AV_PIX_FMT_YUV422P;
yading@11 407 } else if (strncmp("444alpha", tokstart, 8) == 0 ) {
yading@11 408 av_log(s, AV_LOG_ERROR, "Cannot handle 4:4:4:4 "
yading@11 409 "YUV4MPEG stream.\n");
yading@11 410 return -1;
yading@11 411 } else if (strncmp("444", tokstart, 3) == 0) {
yading@11 412 pix_fmt = AV_PIX_FMT_YUV444P;
yading@11 413 } else if (strncmp("mono16", tokstart, 6) == 0) {
yading@11 414 pix_fmt = AV_PIX_FMT_GRAY16;
yading@11 415 } else if (strncmp("mono", tokstart, 4) == 0) {
yading@11 416 pix_fmt = AV_PIX_FMT_GRAY8;
yading@11 417 } else {
yading@11 418 av_log(s, AV_LOG_ERROR, "YUV4MPEG stream contains an unknown "
yading@11 419 "pixel format.\n");
yading@11 420 return -1;
yading@11 421 }
yading@11 422 while (tokstart < header_end && *tokstart != 0x20)
yading@11 423 tokstart++;
yading@11 424 break;
yading@11 425 case 'I': // Interlace type
yading@11 426 interlaced = *tokstart++;
yading@11 427 break;
yading@11 428 case 'F': // Frame rate
yading@11 429 sscanf(tokstart, "%d:%d", &raten, &rated); // 0:0 if unknown
yading@11 430 while (tokstart < header_end && *tokstart != 0x20)
yading@11 431 tokstart++;
yading@11 432 break;
yading@11 433 case 'A': // Pixel aspect
yading@11 434 sscanf(tokstart, "%d:%d", &aspectn, &aspectd); // 0:0 if unknown
yading@11 435 while (tokstart < header_end && *tokstart != 0x20)
yading@11 436 tokstart++;
yading@11 437 break;
yading@11 438 case 'X': // Vendor extensions
yading@11 439 if (strncmp("YSCSS=", tokstart, 6) == 0) {
yading@11 440 // Older nonstandard pixel format representation
yading@11 441 tokstart += 6;
yading@11 442 if (strncmp("420JPEG", tokstart, 7) == 0)
yading@11 443 alt_pix_fmt = AV_PIX_FMT_YUV420P;
yading@11 444 else if (strncmp("420MPEG2", tokstart, 8) == 0)
yading@11 445 alt_pix_fmt = AV_PIX_FMT_YUV420P;
yading@11 446 else if (strncmp("420PALDV", tokstart, 8) == 0)
yading@11 447 alt_pix_fmt = AV_PIX_FMT_YUV420P;
yading@11 448 else if (strncmp("420P9", tokstart, 5) == 0)
yading@11 449 alt_pix_fmt = AV_PIX_FMT_YUV420P9;
yading@11 450 else if (strncmp("422P9", tokstart, 5) == 0)
yading@11 451 alt_pix_fmt = AV_PIX_FMT_YUV422P9;
yading@11 452 else if (strncmp("444P9", tokstart, 5) == 0)
yading@11 453 alt_pix_fmt = AV_PIX_FMT_YUV444P9;
yading@11 454 else if (strncmp("420P10", tokstart, 6) == 0)
yading@11 455 alt_pix_fmt = AV_PIX_FMT_YUV420P10;
yading@11 456 else if (strncmp("422P10", tokstart, 6) == 0)
yading@11 457 alt_pix_fmt = AV_PIX_FMT_YUV422P10;
yading@11 458 else if (strncmp("444P10", tokstart, 6) == 0)
yading@11 459 alt_pix_fmt = AV_PIX_FMT_YUV444P10;
yading@11 460 else if (strncmp("420P12", tokstart, 6) == 0)
yading@11 461 alt_pix_fmt = AV_PIX_FMT_YUV420P12;
yading@11 462 else if (strncmp("422P12", tokstart, 6) == 0)
yading@11 463 alt_pix_fmt = AV_PIX_FMT_YUV422P12;
yading@11 464 else if (strncmp("444P12", tokstart, 6) == 0)
yading@11 465 alt_pix_fmt = AV_PIX_FMT_YUV444P12;
yading@11 466 else if (strncmp("420P14", tokstart, 6) == 0)
yading@11 467 alt_pix_fmt = AV_PIX_FMT_YUV420P14;
yading@11 468 else if (strncmp("422P14", tokstart, 6) == 0)
yading@11 469 alt_pix_fmt = AV_PIX_FMT_YUV422P14;
yading@11 470 else if (strncmp("444P14", tokstart, 6) == 0)
yading@11 471 alt_pix_fmt = AV_PIX_FMT_YUV444P14;
yading@11 472 else if (strncmp("420P16", tokstart, 6) == 0)
yading@11 473 alt_pix_fmt = AV_PIX_FMT_YUV420P16;
yading@11 474 else if (strncmp("422P16", tokstart, 6) == 0)
yading@11 475 alt_pix_fmt = AV_PIX_FMT_YUV422P16;
yading@11 476 else if (strncmp("444P16", tokstart, 6) == 0)
yading@11 477 alt_pix_fmt = AV_PIX_FMT_YUV444P16;
yading@11 478 else if (strncmp("411", tokstart, 3) == 0)
yading@11 479 alt_pix_fmt = AV_PIX_FMT_YUV411P;
yading@11 480 else if (strncmp("422", tokstart, 3) == 0)
yading@11 481 alt_pix_fmt = AV_PIX_FMT_YUV422P;
yading@11 482 else if (strncmp("444", tokstart, 3) == 0)
yading@11 483 alt_pix_fmt = AV_PIX_FMT_YUV444P;
yading@11 484 }
yading@11 485 while (tokstart < header_end && *tokstart != 0x20)
yading@11 486 tokstart++;
yading@11 487 break;
yading@11 488 }
yading@11 489 }
yading@11 490
yading@11 491 if (width == -1 || height == -1) {
yading@11 492 av_log(s, AV_LOG_ERROR, "YUV4MPEG has invalid header.\n");
yading@11 493 return -1;
yading@11 494 }
yading@11 495
yading@11 496 if (pix_fmt == AV_PIX_FMT_NONE) {
yading@11 497 if (alt_pix_fmt == AV_PIX_FMT_NONE)
yading@11 498 pix_fmt = AV_PIX_FMT_YUV420P;
yading@11 499 else
yading@11 500 pix_fmt = alt_pix_fmt;
yading@11 501 }
yading@11 502
yading@11 503 if (raten <= 0 || rated <= 0) {
yading@11 504 // Frame rate unknown
yading@11 505 raten = 25;
yading@11 506 rated = 1;
yading@11 507 }
yading@11 508
yading@11 509 if (aspectn == 0 && aspectd == 0) {
yading@11 510 // Pixel aspect unknown
yading@11 511 aspectd = 1;
yading@11 512 }
yading@11 513
yading@11 514 st = avformat_new_stream(s, NULL);
yading@11 515 if (!st)
yading@11 516 return AVERROR(ENOMEM);
yading@11 517 st->codec->width = width;
yading@11 518 st->codec->height = height;
yading@11 519 av_reduce(&raten, &rated, raten, rated, (1UL << 31) - 1);
yading@11 520 avpriv_set_pts_info(st, 64, rated, raten);
yading@11 521 st->codec->pix_fmt = pix_fmt;
yading@11 522 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
yading@11 523 st->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
yading@11 524 st->sample_aspect_ratio = (AVRational){ aspectn, aspectd };
yading@11 525 st->codec->chroma_sample_location = chroma_sample_location;
yading@11 526
yading@11 527 switch (interlaced){
yading@11 528 case 'p':
yading@11 529 st->codec->field_order = AV_FIELD_PROGRESSIVE;
yading@11 530 break;
yading@11 531 case 't':
yading@11 532 st->codec->field_order = AV_FIELD_TB;
yading@11 533 break;
yading@11 534 case 'b':
yading@11 535 st->codec->field_order = AV_FIELD_BT;
yading@11 536 break;
yading@11 537 case 'm':
yading@11 538 av_log(s, AV_LOG_ERROR, "YUV4MPEG stream contains mixed "
yading@11 539 "interlaced and non-interlaced frames.\n");
yading@11 540 case '?':
yading@11 541 st->codec->field_order = AV_FIELD_UNKNOWN;
yading@11 542 break;
yading@11 543 default:
yading@11 544 av_log(s, AV_LOG_ERROR, "YUV4MPEG has invalid header.\n");
yading@11 545 return AVERROR(EINVAL);
yading@11 546 }
yading@11 547
yading@11 548 return 0;
yading@11 549 }
yading@11 550
yading@11 551 static int yuv4_read_packet(AVFormatContext *s, AVPacket *pkt)
yading@11 552 {
yading@11 553 int i;
yading@11 554 char header[MAX_FRAME_HEADER+1];
yading@11 555 int packet_size, width, height, ret;
yading@11 556 AVStream *st = s->streams[0];
yading@11 557
yading@11 558 for (i = 0; i < MAX_FRAME_HEADER; i++) {
yading@11 559 header[i] = avio_r8(s->pb);
yading@11 560 if (header[i] == '\n') {
yading@11 561 header[i + 1] = 0;
yading@11 562 break;
yading@11 563 }
yading@11 564 }
yading@11 565 if (s->pb->error)
yading@11 566 return s->pb->error;
yading@11 567 else if (s->pb->eof_reached)
yading@11 568 return AVERROR_EOF;
yading@11 569 else if (i == MAX_FRAME_HEADER)
yading@11 570 return AVERROR_INVALIDDATA;
yading@11 571
yading@11 572 if (strncmp(header, Y4M_FRAME_MAGIC, strlen(Y4M_FRAME_MAGIC)))
yading@11 573 return AVERROR_INVALIDDATA;
yading@11 574
yading@11 575 width = st->codec->width;
yading@11 576 height = st->codec->height;
yading@11 577
yading@11 578 packet_size = avpicture_get_size(st->codec->pix_fmt, width, height);
yading@11 579 if (packet_size < 0)
yading@11 580 return packet_size;
yading@11 581
yading@11 582 ret = av_get_packet(s->pb, pkt, packet_size);
yading@11 583 if (ret < 0)
yading@11 584 return ret;
yading@11 585 else if (ret != packet_size)
yading@11 586 return s->pb->eof_reached ? AVERROR_EOF : AVERROR(EIO);
yading@11 587
yading@11 588 pkt->stream_index = 0;
yading@11 589 return 0;
yading@11 590 }
yading@11 591
yading@11 592 static int yuv4_probe(AVProbeData *pd)
yading@11 593 {
yading@11 594 /* check file header */
yading@11 595 if (strncmp(pd->buf, Y4M_MAGIC, sizeof(Y4M_MAGIC) - 1) == 0)
yading@11 596 return AVPROBE_SCORE_MAX;
yading@11 597 else
yading@11 598 return 0;
yading@11 599 }
yading@11 600
yading@11 601 #if CONFIG_YUV4MPEGPIPE_DEMUXER
yading@11 602 AVInputFormat ff_yuv4mpegpipe_demuxer = {
yading@11 603 .name = "yuv4mpegpipe",
yading@11 604 .long_name = NULL_IF_CONFIG_SMALL("YUV4MPEG pipe"),
yading@11 605 .read_probe = yuv4_probe,
yading@11 606 .read_header = yuv4_read_header,
yading@11 607 .read_packet = yuv4_read_packet,
yading@11 608 .extensions = "y4m",
yading@11 609 };
yading@11 610 #endif