[x265] [PATCH] cli: refactor handling of input file parameters

Steve Borho steve at borho.org
Tue Feb 25 06:03:54 CET 2014


# HG changeset patch
# User Steve Borho <steve at borho.org>
# Date 1393303499 21600
#      Mon Feb 24 22:44:59 2014 -0600
# Node ID dfc6889247da48d658dfe124d5dcda817b3447b3
# Parent  6214d2609ea806408ed18d92f5f95acad8c8c5d1
cli: refactor handling of input file parameters

* allow y4m header to provide aspect ratio
* allow user to override Y4M aspect ratio or frame rate
* allow user to provide data possibly missing from Y4M header
* do not clamp framesToBeEncoded to predicted file size (stop at EOF)

diff -r 6214d2609ea8 -r dfc6889247da source/common/param.cpp
--- a/source/common/param.cpp	Mon Feb 24 22:45:15 2014 -0600
+++ b/source/common/param.cpp	Mon Feb 24 22:44:59 2014 -0600
@@ -556,10 +556,10 @@
     }
     OPT("extended-sar")
     {
-        p->bEnableVuiParametersPresentFlag = 1;
-        p->bEnableAspectRatioIdc = 1;
-        p->aspectRatioIdc = X265_EXTENDED_SAR;
-        bError |= sscanf(value, "%dx%d", &p->sarWidth, &p->sarHeight) != 2;
+        int width, height;
+        bError |= sscanf(value, "%dx%d", &width, &height) != 2;
+        if (!bError)
+            setParamAspectRatio(p, width, height);
     }
     OPT("overscan")
     {
@@ -751,6 +751,44 @@
 namespace x265 {
 // internal encoder functions
 
+void setParamAspectRatio(x265_param *p, int width, int height)
+{
+    const int fixedRatios[][2] =
+    {
+        { 1,  1 },
+        { 12, 11 },
+        { 10, 11 },
+        { 16, 11 },
+        { 40, 33 },
+        { 24, 11 },
+        { 20, 11 },
+        { 32, 11 },
+        { 80, 33 },
+        { 18, 11 },
+        { 15, 11 },
+        { 64, 33 },
+        { 160, 99 },
+        { 4, 3 },
+        { 3, 2 },
+        { 2, 1 },
+
+        { 0, 0 }
+    };
+    p->bEnableVuiParametersPresentFlag = 1;
+    p->bEnableAspectRatioIdc = 1;
+    p->aspectRatioIdc = X265_EXTENDED_SAR;
+    p->sarWidth = width;
+    p->sarHeight = height;
+    for (int i = 0; fixedRatios[i][0]; i++)
+    {
+        if (width == fixedRatios[i][0] && height == fixedRatios[i][1])
+        {
+            p->aspectRatioIdc = i + 1;
+            return;
+        }
+    }
+}
+
 static inline int _confirm(x265_param *param, bool bflag, const char* message)
 {
     if (!bflag)
diff -r 6214d2609ea8 -r dfc6889247da source/common/param.h
--- a/source/common/param.h	Mon Feb 24 22:45:15 2014 -0600
+++ b/source/common/param.h	Mon Feb 24 22:44:59 2014 -0600
@@ -30,6 +30,7 @@
 int   x265_set_globals(x265_param *param);
 void  x265_print_params(x265_param *param);
 char* x265_param2string(x265_param *param);
+void  setParamAspectRatio(x265_param *p, int width, int height);
 
 }
 
diff -r 6214d2609ea8 -r dfc6889247da source/input/input.cpp
--- a/source/input/input.cpp	Mon Feb 24 22:45:15 2014 -0600
+++ b/source/input/input.cpp	Mon Feb 24 22:44:59 2014 -0600
@@ -28,12 +28,12 @@
 
 using namespace x265;
 
-Input* Input::open(const char *filename, uint32_t inputBitDepth, bool bForceY4m)
+Input* Input::open(InputFileInfo& info, bool bForceY4m)
 {
-    const char * s = strrchr(filename, '.');
+    const char * s = strrchr(info.filename, '.');
 
     if (bForceY4m || (s && !strcmp(s, ".y4m")))
-        return new Y4MInput(filename, inputBitDepth);
+        return new Y4MInput(info);
     else
-        return new YUVInput(filename, inputBitDepth);
+        return new YUVInput(info);
 }
diff -r 6214d2609ea8 -r dfc6889247da source/input/input.h
--- a/source/input/input.h	Mon Feb 24 22:45:15 2014 -0600
+++ b/source/input/input.h	Mon Feb 24 22:44:59 2014 -0600
@@ -36,6 +36,24 @@
 namespace x265 {
 // private x265 namespace
 
+struct InputFileInfo
+{
+    /* possibly user-supplied, possibly read from file header */
+    int width;
+    int height;
+    int csp;
+    int depth;
+    int fpsNum;
+    int fpsDenom;
+    int sarWidth;
+    int sarHeight;
+    int frameCount;
+
+    /* user supplied */
+    int skipFrames;
+    const char *filename;
+};
+
 class Input
 {
 protected:
@@ -46,36 +64,18 @@
 
     Input()           {}
 
-    static Input* open(const char *filename, uint32_t inputBitDepth, bool bForceY4m);
-
-    virtual void setDimensions(int width, int height) = 0;
-
-    virtual void setBitDepth(uint32_t bitDepth) = 0;
-
-    virtual void setColorSpace(int csp) = 0;
-
-    virtual void getRate(uint32_t& num, uint32_t& denom) const = 0;
-
-    virtual int getWidth() const = 0;
-
-    virtual int getHeight() const = 0;
-
-    virtual int getColorSpace() const = 0;
+    static Input* open(InputFileInfo& info, bool bForceY4m);
 
     virtual void startReader() = 0;
 
     virtual void release() = 0;
 
-    virtual void skipFrames(uint32_t numFrames) = 0;
-
     virtual bool readPicture(x265_picture& pic) = 0;
 
     virtual bool isEof() const = 0;
 
     virtual bool isFail() = 0;
 
-    virtual int  guessFrameCount() = 0;
-
     virtual const char *getName() const = 0;
 };
 }
diff -r 6214d2609ea8 -r dfc6889247da source/input/y4m.cpp
--- a/source/input/y4m.cpp	Mon Feb 24 22:45:15 2014 -0600
+++ b/source/input/y4m.cpp	Mon Feb 24 22:44:59 2014 -0600
@@ -41,7 +41,9 @@
 using namespace x265;
 using namespace std;
 
-Y4MInput::Y4MInput(const char *filename, uint32_t /*inputBitDepth*/)
+static const char header[] = "FRAME";
+
+Y4MInput::Y4MInput(InputFileInfo& info)
 {
     for (uint32_t i = 0; i < QUEUE_SIZE; i++)
     {
@@ -49,10 +51,17 @@
     }
 
     head = tail = 0;
-    colorSpace = X265_CSP_I420;
+
+    colorSpace = info.csp;
+    sarWidth = info.sarWidth;
+    sarHeight = info.sarHeight;
+    width = info.width;
+    height = info.height;
+    rateNum = info.fpsNum;
+    rateDenom = info.fpsDenom;
 
     ifs = NULL;
-    if (!strcmp(filename, "-"))
+    if (!strcmp(info.filename, "-"))
     {
         ifs = &cin;
 #if _WIN32
@@ -60,24 +69,47 @@
 #endif
     }
     else
-        ifs = new ifstream(filename, ios::binary | ios::in);
+        ifs = new ifstream(info.filename, ios::binary | ios::in);
 
     threadActive = false;
-    if (ifs && ifs->good())
+    if (ifs && ifs->good() && parseHeader())
     {
-        if (parseHeader())
+        threadActive = true;
+        for (uint32_t i = 0; i < QUEUE_SIZE; i++)
         {
-            threadActive = true;
-            for (uint32_t i = 0; i < QUEUE_SIZE; i++)
-            {
-                pictureAlloc(i);
-            }
+            pictureAlloc(i);
         }
     }
-    if (!threadActive && ifs && ifs != &cin)
+    if (!threadActive)
     {
-        delete ifs;
+        if (ifs && ifs != &cin)
+            delete ifs;
         ifs = NULL;
+        return;
+    }
+
+    info.width = width;
+    info.height = height;
+    info.sarHeight = sarHeight;
+    info.sarWidth = sarWidth;
+    info.fpsNum = rateNum;
+    info.fpsDenom = rateDenom;
+    info.csp = colorSpace;
+    info.depth = 8;
+    info.frameCount = guessFrameCount();
+
+    if (info.skipFrames)
+    {
+        size_t frameSize = strlen(header) + 1;
+        for (int i = 0; i < x265_cli_csps[colorSpace].planes; i++)
+        {
+            frameSize += (size_t)((width >> x265_cli_csps[colorSpace].width[i]) * (height >> x265_cli_csps[colorSpace].height[i]));
+        }
+
+        for (int i = 0; i < info.skipFrames; i++)
+        {
+            ifs->ignore(frameSize);
+        }
     }
 }
 
@@ -117,11 +149,6 @@
     if (!ifs)
         return false;
 
-    width = 0;
-    height = 0;
-    rateNum = 0;
-    rateDenom = 0;
-    colorSpace = X265_CSP_I420;
     int csp = 0;
 
     while (!ifs->eof())
@@ -221,7 +248,37 @@
 
                 break;
 
+            case 'A':
+                sarWidth = 0;
+                sarHeight = 0;
+                while (!ifs->eof())
+                {
+                    c = ifs->get();
+                    if (c == ':')
+                    {
+                        while (!ifs->eof())
+                        {
+                            c = ifs->get();
+                            if (c == ' ' || c == '\n')
+                            {
+                                break;
+                            }
+                            else
+                                sarHeight = sarHeight * 10 + (c - '0');
+                        }
+
+                        break;
+                    }
+                    else
+                    {
+                        sarWidth = sarWidth * 10 + (c - '0');
+                    }
+                }
+
+                break;
+
             case 'C':
+                csp = 0;
                 while (!ifs->eof())
                 {
                     c = ifs->get();
@@ -267,8 +324,6 @@
     return true;
 }
 
-static const char header[] = "FRAME";
-
 int Y4MInput::guessFrameCount()
 {
     if (!ifs || ifs == &cin)
@@ -292,23 +347,6 @@
     return (int)((size - cur) / frameSize);
 }
 
-void Y4MInput::skipFrames(uint32_t numFrames)
-{
-    if (ifs && numFrames)
-    {
-        size_t frameSize = strlen(header) + 1;
-        for (int i = 0; i < x265_cli_csps[colorSpace].planes; i++)
-        {
-            frameSize += (size_t)((width >> x265_cli_csps[colorSpace].width[i]) * (height >> x265_cli_csps[colorSpace].height[i]));
-        }
-
-        for (uint32_t i = 0; i < numFrames; i++)
-        {
-            ifs->ignore(frameSize);
-        }
-    }
-}
-
 void Y4MInput::startReader()
 {
 #if ENABLE_THREADING
diff -r 6214d2609ea8 -r dfc6889247da source/input/y4m.h
--- a/source/input/y4m.h	Mon Feb 24 22:45:15 2014 -0600
+++ b/source/input/y4m.h	Mon Feb 24 22:44:59 2014 -0600
@@ -41,11 +41,15 @@
 
     uint32_t rateDenom;
 
+    uint32_t sarWidth;
+
+    uint32_t sarHeight;
+
     int width;
 
     int height;
 
-    int colorSpace;   ///< source Color Space Parameter
+    int colorSpace;
 
     uint32_t plane_size[3];
 
@@ -69,25 +73,21 @@
 
     bool parseHeader();
 
+    void pictureAlloc(int index);
+
+    int  guessFrameCount();
+
+    void threadMain();
+
+    bool populateFrameQueue();
+
 public:
 
-    Y4MInput(const char *filename, uint32_t inputBitDepth);
+    Y4MInput(InputFileInfo& info);
 
     virtual ~Y4MInput();
 
-    void setDimensions(int, int)  { /* ignore, warn */ }
-
-    void setBitDepth(uint32_t)    { /* ignore, warn */ }
-
-    void setColorSpace(int)       { /* ignore, warn */ }
-
-    void getRate(uint32_t& num, uint32_t& denom) const { num = rateNum; denom = rateDenom; }
-
-    int getWidth() const          { return width; }
-
-    int getHeight() const         { return height; }
-
-    int getColorSpace() const     { return colorSpace; }
+    void release();
 
     bool isEof() const            { return ifs && ifs->eof();  }
 
@@ -95,20 +95,8 @@
 
     void startReader();
 
-    void release();
-
-    int  guessFrameCount();
-
-    void skipFrames(uint32_t numFrames);
-
     bool readPicture(x265_picture&);
 
-    void pictureAlloc(int index);
-
-    void threadMain();
-
-    bool populateFrameQueue();
-
     const char *getName() const   { return "y4m"; }
 };
 }
diff -r 6214d2609ea8 -r dfc6889247da source/input/yuv.cpp
--- a/source/input/yuv.cpp	Mon Feb 24 22:45:15 2014 -0600
+++ b/source/input/yuv.cpp	Mon Feb 24 22:44:59 2014 -0600
@@ -42,7 +42,7 @@
 using namespace x265;
 using namespace std;
 
-YUVInput::YUVInput(const char *filename, uint32_t inputBitDepth)
+YUVInput::YUVInput(InputFileInfo& info)
 {
     for (int i = 0; i < QUEUE_SIZE; i++)
     {
@@ -51,11 +51,21 @@
 
     head = 0;
     tail = 0;
-    depth = inputBitDepth;
-    pixelbytes = inputBitDepth > 8 ? 2 : 1;
-    width = height = framesize = 0;
+    framesize = 0;
+    depth = info.depth;
+    width = info.width;
+    height = info.height;
+    colorSpace = info.csp;
     threadActive = false;
-    if (!strcmp(filename, "-"))
+    ifs = NULL;
+
+    if (width == 0 || height == 0 || info.fpsNum == 0 || info.fpsDenom == 0)
+    {
+        x265_log(NULL, X265_LOG_ERROR, "yuv: width, height, and FPS must be specified\n");
+        return;
+    }
+
+    if (!strcmp(info.filename, "-"))
     {
         ifs = &cin;
 #if _WIN32
@@ -63,14 +73,43 @@
 #endif
     }
     else
-        ifs = new ifstream(filename, ios::binary | ios::in);
+        ifs = new ifstream(info.filename, ios::binary | ios::in);
 
     if (ifs && ifs->good())
         threadActive = true;
-    else if (ifs && ifs != &cin)
+    else
     {
-        delete ifs;
+        if (ifs && ifs != &cin)
+            delete ifs;
         ifs = NULL;
+        return;
+    }
+
+    pixelbytes = depth > 8 ? 2 : 1;
+    for (int i = 0; i < x265_cli_csps[colorSpace].planes; i++)
+    {
+        uint32_t w = width >> x265_cli_csps[colorSpace].width[i];
+        uint32_t h = height >> x265_cli_csps[colorSpace].height[i];
+        framesize += w * h * pixelbytes;
+    }
+
+    for (uint32_t i = 0; i < QUEUE_SIZE; i++)
+    {
+        buf[i] = new char[framesize];
+        if (buf[i] == NULL)
+        {
+            x265_log(NULL, X265_LOG_ERROR, "yuv: buffer allocation failure, aborting\n");
+            threadActive = false;
+            return;
+        }
+    }
+    info.frameCount = guessFrameCount();
+    if (info.skipFrames)
+    {
+        for (int i = 0; i < info.skipFrames; i++)
+        {
+            ifs->ignore(framesize);
+        }
     }
 }
 
@@ -92,32 +131,8 @@
     delete this;
 }
 
-void YUVInput::init()
-{
-    if (!framesize)
-    {
-        for (int i = 0; i < x265_cli_csps[colorSpace].planes; i++)
-        {
-            uint32_t w = width >> x265_cli_csps[colorSpace].width[i];
-            uint32_t h = height >> x265_cli_csps[colorSpace].height[i];
-            framesize += w * h * pixelbytes;
-        }
-
-        for (uint32_t i = 0; i < QUEUE_SIZE; i++)
-        {
-            buf[i] = new char[framesize];
-            if (buf[i] == NULL)
-            {
-                x265_log(NULL, X265_LOG_ERROR, "yuv: buffer allocation failure, aborting\n");
-                threadActive = false;
-            }
-        }
-    }
-}
-
 int YUVInput::guessFrameCount()
 {
-    init();
     if (!ifs || ifs == &cin) return -1;
 
     ifstream::pos_type cur = ifs->tellg();
@@ -134,21 +149,8 @@
     return (int)((size - cur) / framesize);
 }
 
-void YUVInput::skipFrames(uint32_t numFrames)
-{
-    init();
-    if (ifs)
-    {
-        for (uint32_t i = 0; i < numFrames; i++)
-        {
-            ifs->ignore(framesize);
-        }
-    }
-}
-
 void YUVInput::startReader()
 {
-    init();
 #if ENABLE_THREADING
     if (ifs && threadActive)
         start();
diff -r 6214d2609ea8 -r dfc6889247da source/input/yuv.h
--- a/source/input/yuv.h	Mon Feb 24 22:45:15 2014 -0600
+++ b/source/input/yuv.h	Mon Feb 24 22:44:59 2014 -0600
@@ -65,27 +65,19 @@
 
     std::istream *ifs;
 
-    void init();
+    int guessFrameCount();
+
+    void threadMain();
+
+    bool populateFrameQueue();
 
 public:
 
-    YUVInput(const char *filename, uint32_t inputBitDepth);
+    YUVInput(InputFileInfo& info);
 
     virtual ~YUVInput();
 
-    void setDimensions(int w, int h)              { width = w; height = h; }
-
-    void setColorSpace(int csp)                   { colorSpace = csp; }
-
-    int getColorSpace() const                     { return colorSpace; }
-
-    void setBitDepth(uint32_t bitDepth)           { depth = bitDepth; }
-
-    void getRate(uint32_t&, uint32_t&) const      { }
-
-    int getWidth() const                          { return width; }
-
-    int getHeight() const                         { return height; }
+    void release();
 
     bool isEof() const                            { return ifs && ifs->eof();  }
 
@@ -93,18 +85,8 @@
 
     void startReader();
 
-    void release();
-
-    int  guessFrameCount();
-
-    void skipFrames(uint32_t numFrames);
-
     bool readPicture(x265_picture&);
 
-    void threadMain();
-
-    bool populateFrameQueue();
-
     const char *getName() const                   { return "yuv"; }
 };
 }
diff -r 6214d2609ea8 -r dfc6889247da source/x265.cpp
--- a/source/x265.cpp	Mon Feb 24 22:45:15 2014 -0600
+++ b/source/x265.cpp	Mon Feb 24 22:44:59 2014 -0600
@@ -527,57 +527,70 @@
         x265_log(param, X265_LOG_ERROR, "input or output file not specified, try -V for help\n");
         return true;
     }
-    this->input = Input::open(inputfn, inputBitDepth, bForceY4m);
+
+#if HIGH_BIT_DEPTH
+    if (param->internalBitDepth != 10)
+    {
+        x265_log(param, X265_LOG_ERROR, "Only bit depths of 10 are supported in this build\n");
+        return true;
+    }
+#else
+    if (param->internalBitDepth != 8)
+    {
+        x265_log(param, X265_LOG_ERROR, "Only bit depths of 8 are supported in this build\n");
+        return true;
+    }
+#endif // if HIGH_BIT_DEPTH
+
+    InputFileInfo info;
+    info.filename = inputfn;
+    info.depth = inputBitDepth;
+    info.csp = param->internalCsp;
+    info.width = param->sourceWidth;
+    info.height = param->sourceHeight;
+    info.fpsNum = param->fpsNum;
+    info.fpsDenom = param->fpsDenom;
+    info.sarWidth = param->sarWidth;
+    info.sarHeight = param->sarHeight;
+    info.skipFrames = seek;
+    info.frameCount = 0;
+
+    this->input = Input::open(info, bForceY4m);
     if (!this->input || this->input->isFail())
     {
         x265_log(param, X265_LOG_ERROR, "unable to open input file <%s>\n", inputfn);
         return true;
     }
-    if (this->input->getWidth())
-    {
-        /* the file knows its own dimensions, must be Y4M */
-        param->internalCsp = this->input->getColorSpace();
-        param->sourceWidth = this->input->getWidth();
-        param->sourceHeight = this->input->getHeight();
-        this->input->getRate(param->fpsNum, param->fpsDenom);
-    }
-    else
-    {
-        if (param->sourceHeight <= 0 || param->sourceWidth <= 0 || param->fpsNum == 0 || param->fpsDenom == 0)
-        {
-            x265_log(param, X265_LOG_ERROR, "YUV input requires --input-res WxH and --fps N to be specified\n");
-            return true;
-        }
-        this->input->setDimensions(param->sourceWidth, param->sourceHeight);
-        this->input->setColorSpace(param->internalCsp);
-        this->input->setBitDepth(inputBitDepth);
-    }
-    if (param->internalCsp != X265_CSP_I420 && param->internalCsp != X265_CSP_I444)
+    if (info.csp != X265_CSP_I420 && info.csp != X265_CSP_I444)
     {
         x265_log(param, X265_LOG_ERROR, "Only i420 and i444 color spaces are supported in this build\n");
         return true;
     }
-    if (inputBitDepth < 8 || inputBitDepth > 16)
+    if (info.depth < 8 || info.depth > 16)
     {
         x265_log(param, X265_LOG_ERROR, "Input bit depth (%d) must be between 8 and 16\n", inputBitDepth);
         return true;
     }
 
-    int guess = this->input->guessFrameCount();
-    if (this->seek)
+    /* Unconditionally accept height/width/csp from file info */
+    param->sourceWidth = info.width;
+    param->sourceHeight = info.height;
+    param->internalCsp = info.csp;
+
+    /* Accept fps and sar from file info if not specified by user */
+    if (param->fpsDenom == 0 || param->fpsNum == 0)
     {
-        this->input->skipFrames(this->seek);
+        param->fpsDenom = info.fpsDenom;
+        param->fpsNum = info.fpsNum;
     }
+    if (!param->bEnableAspectRatioIdc && info.sarWidth && info.sarHeight)
+        setParamAspectRatio(param, info.sarWidth, info.sarHeight);
 
-    uint32_t fileFrameCount = guess < 0 ? 0 : (uint32_t)guess;
-    if (this->framesToBeEncoded && fileFrameCount)
-        this->framesToBeEncoded = X265_MIN(this->framesToBeEncoded, fileFrameCount - this->seek);
-    else if (fileFrameCount)
-        this->framesToBeEncoded = fileFrameCount - this->seek;
-
+    if (this->framesToBeEncoded == 0 && info.frameCount > seek)
+        this->framesToBeEncoded = info.frameCount - seek;
     if (param->logLevel >= X265_LOG_INFO)
     {
-        if (this->framesToBeEncoded == 0)
+        if (framesToBeEncoded == 0)
             fprintf(stderr, "%s  [info]: %dx%d %d/%d fps %s, unknown frame count\n", input->getName(),
                     param->sourceWidth, param->sourceHeight, param->fpsNum, param->fpsDenom,
                     x265_source_csp_names[param->internalCsp]);
@@ -585,7 +598,7 @@
             fprintf(stderr, "%s  [info]: %dx%d %d/%d fps %s, frames %u - %d of %d\n", input->getName(),
                     param->sourceWidth, param->sourceHeight, param->fpsNum, param->fpsDenom,
                     x265_source_csp_names[param->internalCsp],
-                    this->seek, this->seek + this->framesToBeEncoded - 1, fileFrameCount);
+                    this->seek, this->seek + this->framesToBeEncoded - 1, info.frameCount);
     }
 
     this->input->startReader();
@@ -608,20 +621,6 @@
                     x265_source_csp_names[param->internalCsp]);
     }
 
-#if HIGH_BIT_DEPTH
-    if (param->internalBitDepth != 10)
-    {
-        x265_log(param, X265_LOG_ERROR, "Only bit depths of 10 are supported in this build\n");
-        return true;
-    }
-#else
-    if (param->internalBitDepth != 8)
-    {
-        x265_log(param, X265_LOG_ERROR, "Only bit depths of 8 are supported in this build\n");
-        return true;
-    }
-#endif // if HIGH_BIT_DEPTH
-
     this->bitstreamFile.open(bitstreamfn, std::fstream::binary | std::fstream::out);
     if (!this->bitstreamFile)
     {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 6278.diff
Type: text/x-patch
Size: 21121 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20140224/f9e0fe94/attachment-0001.bin>


More information about the x265-devel mailing list