#include "yuv4mpeg.h"
/* Header size increased to allow room for optional flags */
-#define MAX_YUV4_HEADER 80
+#define MAX_YUV4_HEADER 96
#define MAX_FRAME_HEADER 80
static int yuv4_read_header(AVFormatContext *s)
enum AVPixelFormat pix_fmt = AV_PIX_FMT_NONE, alt_pix_fmt = AV_PIX_FMT_NONE;
enum AVChromaLocation chroma_sample_location = AVCHROMA_LOC_UNSPECIFIED;
enum AVFieldOrder field_order = AV_FIELD_UNKNOWN;
+ enum AVColorRange color_range = AVCOL_RANGE_UNSPECIFIED;
AVStream *st;
for (i = 0; i < MAX_YUV4_HEADER; i++) {
break;
}
}
- if (i == MAX_YUV4_HEADER)
- return -1;
- if (strncmp(header, Y4M_MAGIC, strlen(Y4M_MAGIC)))
- return -1;
+ if (i == MAX_YUV4_HEADER) {
+ av_log(s, AV_LOG_ERROR, "Header too large.\n");
+ return AVERROR(EINVAL);
+ }
+ if (strncmp(header, Y4M_MAGIC, strlen(Y4M_MAGIC))) {
+ av_log(s, AV_LOG_ERROR, "Invalid magic number for yuv4mpeg.\n");
+ return AVERROR(EINVAL);
+ }
header_end = &header[i + 1]; // Include space
for (tokstart = &header[strlen(Y4M_MAGIC) + 1];
} else if (strncmp("422", tokstart, 3) == 0) {
pix_fmt = AV_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;
+ pix_fmt = AV_PIX_FMT_YUVA444P;
} else if (strncmp("444", tokstart, 3) == 0) {
pix_fmt = AV_PIX_FMT_YUV444P;
} else if (strncmp("mono16", tokstart, 6) == 0) {
} else {
av_log(s, AV_LOG_ERROR, "YUV4MPEG stream contains an unknown "
"pixel format.\n");
- return -1;
+ return AVERROR_INVALIDDATA;
}
while (tokstart < header_end && *tokstart != 0x20)
tokstart++;
alt_pix_fmt = AV_PIX_FMT_YUV422P;
else if (strncmp("444", tokstart, 3) == 0)
alt_pix_fmt = AV_PIX_FMT_YUV444P;
+ } else if (strncmp("COLORRANGE=", tokstart, 11) == 0) {
+ tokstart += 11;
+ if (strncmp("FULL",tokstart, 4) == 0)
+ color_range = AVCOL_RANGE_JPEG;
+ else if (strncmp("LIMITED", tokstart, 7) == 0)
+ color_range = AVCOL_RANGE_MPEG;
}
while (tokstart < header_end && *tokstart != 0x20)
tokstart++;
if (width == -1 || height == -1) {
av_log(s, AV_LOG_ERROR, "YUV4MPEG has invalid header.\n");
- return -1;
+ return AVERROR_INVALIDDATA;
}
if (pix_fmt == AV_PIX_FMT_NONE) {
st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO;
st->sample_aspect_ratio = (AVRational){ aspectn, aspectd };
st->codecpar->chroma_location = chroma_sample_location;
+ st->codecpar->color_range = color_range;
st->codecpar->field_order = field_order;
s->packet_size = av_image_get_buffer_size(st->codecpar->format, width, height, 1) + Y4M_FRAME_MAGIC_LEN;
if ((int) s->packet_size < 0)
if (ret < 0)
return ret;
else if (ret != s->packet_size - Y4M_FRAME_MAGIC_LEN) {
- av_packet_unref(pkt);
return s->pb->eof_reached ? AVERROR_EOF : AVERROR(EIO);
}
pkt->stream_index = 0;
static int yuv4_read_seek(AVFormatContext *s, int stream_index,
int64_t pts, int flags)
{
- if (avio_seek(s->pb, pts * s->packet_size + s->internal->data_offset, SEEK_SET) < 0)
+ int64_t pos;
+
+ if (flags & AVSEEK_FLAG_BACKWARD)
+ pts = FFMAX(0, pts - 1);
+ if (pts < 0)
+ return -1;
+ pos = pts * s->packet_size;
+
+ if (avio_seek(s->pb, pos + s->internal->data_offset, SEEK_SET) < 0)
return -1;
return 0;
}
-static int yuv4_probe(AVProbeData *pd)
+static int yuv4_probe(const AVProbeData *pd)
{
/* check file header */
if (strncmp(pd->buf, Y4M_MAGIC, sizeof(Y4M_MAGIC) - 1) == 0)
return 0;
}
-AVInputFormat ff_yuv4mpegpipe_demuxer = {
+const AVInputFormat ff_yuv4mpegpipe_demuxer = {
.name = "yuv4mpegpipe",
.long_name = NULL_IF_CONFIG_SMALL("YUV4MPEG pipe"),
.read_probe = yuv4_probe,