00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "avformat.h"
00022 #include "internal.h"
00023 #include "libavutil/pixdesc.h"
00024
00025 #define Y4M_MAGIC "YUV4MPEG2"
00026 #define Y4M_FRAME_MAGIC "FRAME"
00027 #define Y4M_LINE_MAX 256
00028
00029 struct frame_attributes {
00030 int interlaced_frame;
00031 int top_field_first;
00032 };
00033
00034 #if CONFIG_YUV4MPEGPIPE_MUXER
00035 static int yuv4_generate_header(AVFormatContext *s, char* buf)
00036 {
00037 AVStream *st;
00038 int width, height;
00039 int raten, rated, aspectn, aspectd, n;
00040 char inter;
00041 const char *colorspace = "";
00042
00043 st = s->streams[0];
00044 width = st->codec->width;
00045 height = st->codec->height;
00046
00047 av_reduce(&raten, &rated, st->codec->time_base.den,
00048 st->codec->time_base.num, (1UL << 31) - 1);
00049
00050 aspectn = st->sample_aspect_ratio.num;
00051 aspectd = st->sample_aspect_ratio.den;
00052
00053 if (aspectn == 0 && aspectd == 1)
00054 aspectd = 0;
00055
00056 inter = 'p';
00057 if (st->codec->coded_frame && st->codec->coded_frame->interlaced_frame)
00058 inter = st->codec->coded_frame->top_field_first ? 't' : 'b';
00059
00060 switch (st->codec->pix_fmt) {
00061 case AV_PIX_FMT_GRAY8:
00062 colorspace = " Cmono";
00063 break;
00064 case AV_PIX_FMT_GRAY16:
00065 colorspace = " Cmono16";
00066 break;
00067 case AV_PIX_FMT_YUV411P:
00068 colorspace = " C411 XYSCSS=411";
00069 break;
00070 case AV_PIX_FMT_YUV420P:
00071 switch (st->codec->chroma_sample_location) {
00072 case AVCHROMA_LOC_TOPLEFT: colorspace = " C420paldv XYSCSS=420PALDV"; break;
00073 case AVCHROMA_LOC_LEFT: colorspace = " C420mpeg2 XYSCSS=420MPEG2"; break;
00074 default: colorspace = " C420jpeg XYSCSS=420JPEG"; break;
00075 }
00076 break;
00077 case AV_PIX_FMT_YUV422P:
00078 colorspace = " C422 XYSCSS=422";
00079 break;
00080 case AV_PIX_FMT_YUV444P:
00081 colorspace = " C444 XYSCSS=444";
00082 break;
00083 case AV_PIX_FMT_YUV420P9:
00084 colorspace = " C420p9 XYSCSS=420P9";
00085 break;
00086 case AV_PIX_FMT_YUV422P9:
00087 colorspace = " C422p9 XYSCSS=422P9";
00088 break;
00089 case AV_PIX_FMT_YUV444P9:
00090 colorspace = " C444p9 XYSCSS=444P9";
00091 break;
00092 case AV_PIX_FMT_YUV420P10:
00093 colorspace = " C420p10 XYSCSS=420P10";
00094 break;
00095 case AV_PIX_FMT_YUV422P10:
00096 colorspace = " C422p10 XYSCSS=422P10";
00097 break;
00098 case AV_PIX_FMT_YUV444P10:
00099 colorspace = " C444p10 XYSCSS=444P10";
00100 break;
00101 case AV_PIX_FMT_YUV420P12:
00102 colorspace = " C420p12 XYSCSS=420P12";
00103 break;
00104 case AV_PIX_FMT_YUV422P12:
00105 colorspace = " C422p12 XYSCSS=422P12";
00106 break;
00107 case AV_PIX_FMT_YUV444P12:
00108 colorspace = " C444p12 XYSCSS=444P12";
00109 break;
00110 case AV_PIX_FMT_YUV420P14:
00111 colorspace = " C420p14 XYSCSS=420P14";
00112 break;
00113 case AV_PIX_FMT_YUV422P14:
00114 colorspace = " C422p14 XYSCSS=422P14";
00115 break;
00116 case AV_PIX_FMT_YUV444P14:
00117 colorspace = " C444p14 XYSCSS=444P14";
00118 break;
00119 case AV_PIX_FMT_YUV420P16:
00120 colorspace = " C420p16 XYSCSS=420P16";
00121 break;
00122 case AV_PIX_FMT_YUV422P16:
00123 colorspace = " C422p16 XYSCSS=422P16";
00124 break;
00125 case AV_PIX_FMT_YUV444P16:
00126 colorspace = " C444p16 XYSCSS=444P16";
00127 break;
00128 }
00129
00130
00131 n = snprintf(buf, Y4M_LINE_MAX, "%s W%d H%d F%d:%d I%c A%d:%d%s\n",
00132 Y4M_MAGIC, width, height, raten, rated, inter,
00133 aspectn, aspectd, colorspace);
00134
00135 return n;
00136 }
00137
00138 static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt)
00139 {
00140 AVStream *st = s->streams[pkt->stream_index];
00141 AVIOContext *pb = s->pb;
00142 AVPicture *picture, picture_tmp;
00143 int* first_pkt = s->priv_data;
00144 int width, height, h_chroma_shift, v_chroma_shift;
00145 int i;
00146 char buf2[Y4M_LINE_MAX + 1];
00147 char buf1[20];
00148 uint8_t *ptr, *ptr1, *ptr2;
00149
00150 memcpy(&picture_tmp, pkt->data, sizeof(AVPicture));
00151 picture = &picture_tmp;
00152
00153
00154 if (*first_pkt) {
00155 *first_pkt = 0;
00156 if (yuv4_generate_header(s, buf2) < 0) {
00157 av_log(s, AV_LOG_ERROR,
00158 "Error. YUV4MPEG stream header write failed.\n");
00159 return AVERROR(EIO);
00160 } else {
00161 avio_write(pb, buf2, strlen(buf2));
00162 }
00163 }
00164
00165
00166
00167 snprintf(buf1, sizeof(buf1), "%s\n", Y4M_FRAME_MAGIC);
00168 avio_write(pb, buf1, strlen(buf1));
00169
00170 width = st->codec->width;
00171 height = st->codec->height;
00172
00173 ptr = picture->data[0];
00174
00175 switch (st->codec->pix_fmt) {
00176 case AV_PIX_FMT_GRAY8:
00177 case AV_PIX_FMT_YUV411P:
00178 case AV_PIX_FMT_YUV420P:
00179 case AV_PIX_FMT_YUV422P:
00180 case AV_PIX_FMT_YUV444P:
00181 break;
00182 case AV_PIX_FMT_GRAY16:
00183 case AV_PIX_FMT_YUV420P9:
00184 case AV_PIX_FMT_YUV422P9:
00185 case AV_PIX_FMT_YUV444P9:
00186 case AV_PIX_FMT_YUV420P10:
00187 case AV_PIX_FMT_YUV422P10:
00188 case AV_PIX_FMT_YUV444P10:
00189 case AV_PIX_FMT_YUV420P12:
00190 case AV_PIX_FMT_YUV422P12:
00191 case AV_PIX_FMT_YUV444P12:
00192 case AV_PIX_FMT_YUV420P14:
00193 case AV_PIX_FMT_YUV422P14:
00194 case AV_PIX_FMT_YUV444P14:
00195 case AV_PIX_FMT_YUV420P16:
00196 case AV_PIX_FMT_YUV422P16:
00197 case AV_PIX_FMT_YUV444P16:
00198 width *= 2;
00199 break;
00200 default:
00201 av_log(s, AV_LOG_ERROR, "The pixel format '%s' is not supported.\n",
00202 av_get_pix_fmt_name(st->codec->pix_fmt));
00203 return AVERROR(EINVAL);
00204 }
00205
00206 for (i = 0; i < height; i++) {
00207 avio_write(pb, ptr, width);
00208 ptr += picture->linesize[0];
00209 }
00210
00211 if (st->codec->pix_fmt != AV_PIX_FMT_GRAY8 &&
00212 st->codec->pix_fmt != AV_PIX_FMT_GRAY16) {
00213
00214 avcodec_get_chroma_sub_sample(st->codec->pix_fmt, &h_chroma_shift,
00215 &v_chroma_shift);
00216 width >>= h_chroma_shift;
00217 height >>= v_chroma_shift;
00218
00219 ptr1 = picture->data[1];
00220 ptr2 = picture->data[2];
00221 for (i = 0; i < height; i++) {
00222 avio_write(pb, ptr1, width);
00223 ptr1 += picture->linesize[1];
00224 }
00225 for (i = 0; i < height; i++) {
00226 avio_write(pb, ptr2, width);
00227 ptr2 += picture->linesize[2];
00228 }
00229 }
00230
00231 avio_flush(pb);
00232 return 0;
00233 }
00234
00235 static int yuv4_write_header(AVFormatContext *s)
00236 {
00237 int *first_pkt = s->priv_data;
00238
00239 if (s->nb_streams != 1)
00240 return AVERROR(EIO);
00241
00242 if (s->streams[0]->codec->codec_id != AV_CODEC_ID_RAWVIDEO) {
00243 av_log(s, AV_LOG_ERROR, "ERROR: Only rawvideo supported.\n");
00244 return AVERROR_INVALIDDATA;
00245 }
00246
00247 switch (s->streams[0]->codec->pix_fmt) {
00248 case AV_PIX_FMT_YUV411P:
00249 av_log(s, AV_LOG_WARNING, "Warning: generating rarely used 4:1:1 YUV "
00250 "stream, some mjpegtools might not work.\n");
00251 break;
00252 case AV_PIX_FMT_GRAY8:
00253 case AV_PIX_FMT_GRAY16:
00254 case AV_PIX_FMT_YUV420P:
00255 case AV_PIX_FMT_YUV422P:
00256 case AV_PIX_FMT_YUV444P:
00257 break;
00258 case AV_PIX_FMT_YUV420P9:
00259 case AV_PIX_FMT_YUV422P9:
00260 case AV_PIX_FMT_YUV444P9:
00261 case AV_PIX_FMT_YUV420P10:
00262 case AV_PIX_FMT_YUV422P10:
00263 case AV_PIX_FMT_YUV444P10:
00264 case AV_PIX_FMT_YUV420P12:
00265 case AV_PIX_FMT_YUV422P12:
00266 case AV_PIX_FMT_YUV444P12:
00267 case AV_PIX_FMT_YUV420P14:
00268 case AV_PIX_FMT_YUV422P14:
00269 case AV_PIX_FMT_YUV444P14:
00270 case AV_PIX_FMT_YUV420P16:
00271 case AV_PIX_FMT_YUV422P16:
00272 case AV_PIX_FMT_YUV444P16:
00273 if (s->streams[0]->codec->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {
00274 av_log(s, AV_LOG_ERROR, "'%s' is not a official yuv4mpegpipe pixel format. "
00275 "Use '-strict -1' to encode to this pixel format.\n",
00276 av_get_pix_fmt_name(s->streams[0]->codec->pix_fmt));
00277 return AVERROR(EINVAL);
00278 }
00279 av_log(s, AV_LOG_WARNING, "Warning: generating non standart YUV stream. "
00280 "Mjpegtools will not work.\n");
00281 break;
00282 default:
00283 av_log(s, AV_LOG_ERROR, "ERROR: yuv4mpeg can only handle "
00284 "yuv444p, yuv422p, yuv420p, yuv411p and gray8 pixel formats. "
00285 "And using 'strict -1' also yuv444p9, yuv422p9, yuv420p9, "
00286 "yuv444p10, yuv422p10, yuv420p10, "
00287 "yuv444p12, yuv422p12, yuv420p12, "
00288 "yuv444p14, yuv422p14, yuv420p14, "
00289 "yuv444p16, yuv422p16, yuv420p16 "
00290 "and gray16 pixel formats. "
00291 "Use -pix_fmt to select one.\n");
00292 return AVERROR(EIO);
00293 }
00294
00295 *first_pkt = 1;
00296 return 0;
00297 }
00298
00299 AVOutputFormat ff_yuv4mpegpipe_muxer = {
00300 .name = "yuv4mpegpipe",
00301 .long_name = NULL_IF_CONFIG_SMALL("YUV4MPEG pipe"),
00302 .extensions = "y4m",
00303 .priv_data_size = sizeof(int),
00304 .audio_codec = AV_CODEC_ID_NONE,
00305 .video_codec = AV_CODEC_ID_RAWVIDEO,
00306 .write_header = yuv4_write_header,
00307 .write_packet = yuv4_write_packet,
00308 .flags = AVFMT_RAWPICTURE,
00309 };
00310 #endif
00311
00312
00313 #define MAX_YUV4_HEADER 80
00314 #define MAX_FRAME_HEADER 80
00315
00316 static int yuv4_read_header(AVFormatContext *s)
00317 {
00318 char header[MAX_YUV4_HEADER + 10];
00319
00320 char *tokstart, *tokend, *header_end;
00321 int i;
00322 AVIOContext *pb = s->pb;
00323 int width = -1, height = -1, raten = 0,
00324 rated = 0, aspectn = 0, aspectd = 0;
00325 enum AVPixelFormat pix_fmt = AV_PIX_FMT_NONE, alt_pix_fmt = AV_PIX_FMT_NONE;
00326 enum AVChromaLocation chroma_sample_location = AVCHROMA_LOC_UNSPECIFIED;
00327 AVStream *st;
00328 struct frame_attributes *s1 = s->priv_data;
00329
00330 for (i = 0; i < MAX_YUV4_HEADER; i++) {
00331 header[i] = avio_r8(pb);
00332 if (header[i] == '\n') {
00333 header[i + 1] = 0x20;
00334
00335 header[i + 2] = 0;
00336 break;
00337 }
00338 }
00339 if (i == MAX_YUV4_HEADER)
00340 return -1;
00341 if (strncmp(header, Y4M_MAGIC, strlen(Y4M_MAGIC)))
00342 return -1;
00343
00344 s1->interlaced_frame = 0;
00345 s1->top_field_first = 0;
00346 header_end = &header[i + 1];
00347 for (tokstart = &header[strlen(Y4M_MAGIC) + 1];
00348 tokstart < header_end; tokstart++) {
00349 if (*tokstart == 0x20)
00350 continue;
00351 switch (*tokstart++) {
00352 case 'W':
00353 width = strtol(tokstart, &tokend, 10);
00354 tokstart = tokend;
00355 break;
00356 case 'H':
00357 height = strtol(tokstart, &tokend, 10);
00358 tokstart = tokend;
00359 break;
00360 case 'C':
00361 if (strncmp("420jpeg", tokstart, 7) == 0) {
00362 pix_fmt = AV_PIX_FMT_YUV420P;
00363 chroma_sample_location = AVCHROMA_LOC_CENTER;
00364 } else if (strncmp("420mpeg2", tokstart, 8) == 0) {
00365 pix_fmt = AV_PIX_FMT_YUV420P;
00366 chroma_sample_location = AVCHROMA_LOC_LEFT;
00367 } else if (strncmp("420paldv", tokstart, 8) == 0) {
00368 pix_fmt = AV_PIX_FMT_YUV420P;
00369 chroma_sample_location = AVCHROMA_LOC_TOPLEFT;
00370 } else if (strncmp("420p16", tokstart, 6) == 0) {
00371 pix_fmt = AV_PIX_FMT_YUV420P16;
00372 } else if (strncmp("422p16", tokstart, 6) == 0) {
00373 pix_fmt = AV_PIX_FMT_YUV422P16;
00374 } else if (strncmp("444p16", tokstart, 6) == 0) {
00375 pix_fmt = AV_PIX_FMT_YUV444P16;
00376 } else if (strncmp("420p14", tokstart, 6) == 0) {
00377 pix_fmt = AV_PIX_FMT_YUV420P14;
00378 } else if (strncmp("422p14", tokstart, 6) == 0) {
00379 pix_fmt = AV_PIX_FMT_YUV422P14;
00380 } else if (strncmp("444p14", tokstart, 6) == 0) {
00381 pix_fmt = AV_PIX_FMT_YUV444P14;
00382 } else if (strncmp("420p12", tokstart, 6) == 0) {
00383 pix_fmt = AV_PIX_FMT_YUV420P12;
00384 } else if (strncmp("422p12", tokstart, 6) == 0) {
00385 pix_fmt = AV_PIX_FMT_YUV422P12;
00386 } else if (strncmp("444p12", tokstart, 6) == 0) {
00387 pix_fmt = AV_PIX_FMT_YUV444P12;
00388 } else if (strncmp("420p10", tokstart, 6) == 0) {
00389 pix_fmt = AV_PIX_FMT_YUV420P10;
00390 } else if (strncmp("422p10", tokstart, 6) == 0) {
00391 pix_fmt = AV_PIX_FMT_YUV422P10;
00392 } else if (strncmp("444p10", tokstart, 6) == 0) {
00393 pix_fmt = AV_PIX_FMT_YUV444P10;
00394 } else if (strncmp("420p9", tokstart, 5) == 0) {
00395 pix_fmt = AV_PIX_FMT_YUV420P9;
00396 } else if (strncmp("422p9", tokstart, 5) == 0) {
00397 pix_fmt = AV_PIX_FMT_YUV422P9;
00398 } else if (strncmp("444p9", tokstart, 5) == 0) {
00399 pix_fmt = AV_PIX_FMT_YUV444P9;
00400 } else if (strncmp("420", tokstart, 3) == 0) {
00401 pix_fmt = AV_PIX_FMT_YUV420P;
00402 chroma_sample_location = AVCHROMA_LOC_CENTER;
00403 } else if (strncmp("411", tokstart, 3) == 0) {
00404 pix_fmt = AV_PIX_FMT_YUV411P;
00405 } else if (strncmp("422", tokstart, 3) == 0) {
00406 pix_fmt = AV_PIX_FMT_YUV422P;
00407 } else if (strncmp("444alpha", tokstart, 8) == 0 ) {
00408 av_log(s, AV_LOG_ERROR, "Cannot handle 4:4:4:4 "
00409 "YUV4MPEG stream.\n");
00410 return -1;
00411 } else if (strncmp("444", tokstart, 3) == 0) {
00412 pix_fmt = AV_PIX_FMT_YUV444P;
00413 } else if (strncmp("mono16", tokstart, 6) == 0) {
00414 pix_fmt = AV_PIX_FMT_GRAY16;
00415 } else if (strncmp("mono", tokstart, 4) == 0) {
00416 pix_fmt = AV_PIX_FMT_GRAY8;
00417 } else {
00418 av_log(s, AV_LOG_ERROR, "YUV4MPEG stream contains an unknown "
00419 "pixel format.\n");
00420 return -1;
00421 }
00422 while (tokstart < header_end && *tokstart != 0x20)
00423 tokstart++;
00424 break;
00425 case 'I':
00426 switch (*tokstart++){
00427 case '?':
00428 break;
00429 case 'p':
00430 s1->interlaced_frame = 0;
00431 break;
00432 case 't':
00433 s1->interlaced_frame = 1;
00434 s1->top_field_first = 1;
00435 break;
00436 case 'b':
00437 s1->interlaced_frame = 1;
00438 s1->top_field_first = 0;
00439 break;
00440 case 'm':
00441 av_log(s, AV_LOG_ERROR, "YUV4MPEG stream contains mixed "
00442 "interlaced and non-interlaced frames.\n");
00443 return -1;
00444 default:
00445 av_log(s, AV_LOG_ERROR, "YUV4MPEG has invalid header.\n");
00446 return -1;
00447 }
00448 break;
00449 case 'F':
00450 sscanf(tokstart, "%d:%d", &raten, &rated);
00451 while (tokstart < header_end && *tokstart != 0x20)
00452 tokstart++;
00453 break;
00454 case 'A':
00455 sscanf(tokstart, "%d:%d", &aspectn, &aspectd);
00456 while (tokstart < header_end && *tokstart != 0x20)
00457 tokstart++;
00458 break;
00459 case 'X':
00460 if (strncmp("YSCSS=", tokstart, 6) == 0) {
00461
00462 tokstart += 6;
00463 if (strncmp("420JPEG", tokstart, 7) == 0)
00464 alt_pix_fmt = AV_PIX_FMT_YUV420P;
00465 else if (strncmp("420MPEG2", tokstart, 8) == 0)
00466 alt_pix_fmt = AV_PIX_FMT_YUV420P;
00467 else if (strncmp("420PALDV", tokstart, 8) == 0)
00468 alt_pix_fmt = AV_PIX_FMT_YUV420P;
00469 else if (strncmp("420P9", tokstart, 5) == 0)
00470 alt_pix_fmt = AV_PIX_FMT_YUV420P9;
00471 else if (strncmp("422P9", tokstart, 5) == 0)
00472 alt_pix_fmt = AV_PIX_FMT_YUV422P9;
00473 else if (strncmp("444P9", tokstart, 5) == 0)
00474 alt_pix_fmt = AV_PIX_FMT_YUV444P9;
00475 else if (strncmp("420P10", tokstart, 6) == 0)
00476 alt_pix_fmt = AV_PIX_FMT_YUV420P10;
00477 else if (strncmp("422P10", tokstart, 6) == 0)
00478 alt_pix_fmt = AV_PIX_FMT_YUV422P10;
00479 else if (strncmp("444P10", tokstart, 6) == 0)
00480 alt_pix_fmt = AV_PIX_FMT_YUV444P10;
00481 else if (strncmp("420P12", tokstart, 6) == 0)
00482 alt_pix_fmt = AV_PIX_FMT_YUV420P12;
00483 else if (strncmp("422P12", tokstart, 6) == 0)
00484 alt_pix_fmt = AV_PIX_FMT_YUV422P12;
00485 else if (strncmp("444P12", tokstart, 6) == 0)
00486 alt_pix_fmt = AV_PIX_FMT_YUV444P12;
00487 else if (strncmp("420P14", tokstart, 6) == 0)
00488 alt_pix_fmt = AV_PIX_FMT_YUV420P14;
00489 else if (strncmp("422P14", tokstart, 6) == 0)
00490 alt_pix_fmt = AV_PIX_FMT_YUV422P14;
00491 else if (strncmp("444P14", tokstart, 6) == 0)
00492 alt_pix_fmt = AV_PIX_FMT_YUV444P14;
00493 else if (strncmp("420P16", tokstart, 6) == 0)
00494 alt_pix_fmt = AV_PIX_FMT_YUV420P16;
00495 else if (strncmp("422P16", tokstart, 6) == 0)
00496 alt_pix_fmt = AV_PIX_FMT_YUV422P16;
00497 else if (strncmp("444P16", tokstart, 6) == 0)
00498 alt_pix_fmt = AV_PIX_FMT_YUV444P16;
00499 else if (strncmp("411", tokstart, 3) == 0)
00500 alt_pix_fmt = AV_PIX_FMT_YUV411P;
00501 else if (strncmp("422", tokstart, 3) == 0)
00502 alt_pix_fmt = AV_PIX_FMT_YUV422P;
00503 else if (strncmp("444", tokstart, 3) == 0)
00504 alt_pix_fmt = AV_PIX_FMT_YUV444P;
00505 }
00506 while (tokstart < header_end && *tokstart != 0x20)
00507 tokstart++;
00508 break;
00509 }
00510 }
00511
00512 if (width == -1 || height == -1) {
00513 av_log(s, AV_LOG_ERROR, "YUV4MPEG has invalid header.\n");
00514 return -1;
00515 }
00516
00517 if (pix_fmt == AV_PIX_FMT_NONE) {
00518 if (alt_pix_fmt == AV_PIX_FMT_NONE)
00519 pix_fmt = AV_PIX_FMT_YUV420P;
00520 else
00521 pix_fmt = alt_pix_fmt;
00522 }
00523
00524 if (raten <= 0 || rated <= 0) {
00525
00526 raten = 25;
00527 rated = 1;
00528 }
00529
00530 if (aspectn == 0 && aspectd == 0) {
00531
00532 aspectd = 1;
00533 }
00534
00535 st = avformat_new_stream(s, NULL);
00536 if (!st)
00537 return AVERROR(ENOMEM);
00538 st->codec->width = width;
00539 st->codec->height = height;
00540 av_reduce(&raten, &rated, raten, rated, (1UL << 31) - 1);
00541 avpriv_set_pts_info(st, 64, rated, raten);
00542 st->codec->pix_fmt = pix_fmt;
00543 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00544 st->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
00545 st->sample_aspect_ratio = (AVRational){ aspectn, aspectd };
00546 st->codec->chroma_sample_location = chroma_sample_location;
00547
00548 return 0;
00549 }
00550
00551 static int yuv4_read_packet(AVFormatContext *s, AVPacket *pkt)
00552 {
00553 int i;
00554 char header[MAX_FRAME_HEADER+1];
00555 int packet_size, width, height, ret;
00556 AVStream *st = s->streams[0];
00557 struct frame_attributes *s1 = s->priv_data;
00558
00559 for (i = 0; i < MAX_FRAME_HEADER; i++) {
00560 header[i] = avio_r8(s->pb);
00561 if (header[i] == '\n') {
00562 header[i + 1] = 0;
00563 break;
00564 }
00565 }
00566 if (s->pb->error)
00567 return s->pb->error;
00568 else if (s->pb->eof_reached)
00569 return AVERROR_EOF;
00570 else if (i == MAX_FRAME_HEADER)
00571 return AVERROR_INVALIDDATA;
00572
00573 if (strncmp(header, Y4M_FRAME_MAGIC, strlen(Y4M_FRAME_MAGIC)))
00574 return AVERROR_INVALIDDATA;
00575
00576 width = st->codec->width;
00577 height = st->codec->height;
00578
00579 packet_size = avpicture_get_size(st->codec->pix_fmt, width, height);
00580 if (packet_size < 0)
00581 return packet_size;
00582
00583 ret = av_get_packet(s->pb, pkt, packet_size);
00584 if (ret < 0)
00585 return ret;
00586 else if (ret != packet_size)
00587 return s->pb->eof_reached ? AVERROR_EOF : AVERROR(EIO);
00588
00589 if (st->codec->coded_frame) {
00590 st->codec->coded_frame->interlaced_frame = s1->interlaced_frame;
00591 st->codec->coded_frame->top_field_first = s1->top_field_first;
00592 }
00593
00594 pkt->stream_index = 0;
00595 return 0;
00596 }
00597
00598 static int yuv4_probe(AVProbeData *pd)
00599 {
00600
00601 if (strncmp(pd->buf, Y4M_MAGIC, sizeof(Y4M_MAGIC) - 1) == 0)
00602 return AVPROBE_SCORE_MAX;
00603 else
00604 return 0;
00605 }
00606
00607 #if CONFIG_YUV4MPEGPIPE_DEMUXER
00608 AVInputFormat ff_yuv4mpegpipe_demuxer = {
00609 .name = "yuv4mpegpipe",
00610 .long_name = NULL_IF_CONFIG_SMALL("YUV4MPEG pipe"),
00611 .priv_data_size = sizeof(struct frame_attributes),
00612 .read_probe = yuv4_probe,
00613 .read_header = yuv4_read_header,
00614 .read_packet = yuv4_read_packet,
00615 .extensions = "y4m",
00616 };
00617 #endif