]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/yuv4mpegdec.c
doc/APIchanges: add hashes and version numbers for recent entries
[ffmpeg] / libavformat / yuv4mpegdec.c
index ff0125e4cf3065832ae6a446d4f91d593ef25229..146533c4cc23b0f7cd43c6a48eb4025487b47509 100644 (file)
@@ -26,7 +26,7 @@
 #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)
@@ -41,6 +41,7 @@ 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++) {
@@ -52,10 +53,14 @@ static int yuv4_read_header(AVFormatContext *s)
             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];
@@ -119,9 +124,7 @@ static int yuv4_read_header(AVFormatContext *s)
             } 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) {
@@ -137,7 +140,7 @@ static int yuv4_read_header(AVFormatContext *s)
             } 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++;
@@ -220,6 +223,12 @@ static int yuv4_read_header(AVFormatContext *s)
                     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++;
@@ -229,7 +238,7 @@ static int yuv4_read_header(AVFormatContext *s)
 
     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) {
@@ -263,6 +272,7 @@ static int yuv4_read_header(AVFormatContext *s)
     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)
@@ -302,7 +312,6 @@ static int yuv4_read_packet(AVFormatContext *s, AVPacket *pkt)
     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;
@@ -314,12 +323,20 @@ static int yuv4_read_packet(AVFormatContext *s, AVPacket *pkt)
 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)
@@ -328,7 +345,7 @@ static int yuv4_probe(AVProbeData *pd)
         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,