[x265] [PATCH for review] cli: Timebase, PTS and output module
Steve Borho
steve at borho.org
Sat Apr 4 04:45:55 CEST 2015
On 04/03, Xinyue Lu wrote:
> # Final version
>
> # HG changeset patch
> # User Xinyue Lu <i at 7086.in>
> # Date 1428103358 25200
> # Fri Apr 03 16:22:38 2015 -0700
> # Branch Yuuki
> # Node ID f79424a65d40f958a71e79002eb4a92573c8ae73
> # Parent 335c728bbd62018e1e3ed03a4df0514c213e9a4e
> cli: move raw bitstream output to separate file
>
> Timebase and PTS are passed to output module
queued for testing, should land in the repo by Monday
> diff -r 335c728bbd62 -r f79424a65d40 source/input/input.h
> --- a/source/input/input.h Fri Apr 03 14:27:32 2015 -0500
> +++ b/source/input/input.h Fri Apr 03 16:22:38 2015 -0700
> @@ -48,6 +48,8 @@
> int sarWidth;
> int sarHeight;
> int frameCount;
> + int timebaseNum;
> + int timebaseDenom;
>
> /* user supplied */
> int skipFrames;
> diff -r 335c728bbd62 -r f79424a65d40 source/output/output.cpp
> --- a/source/output/output.cpp Fri Apr 03 14:27:32 2015 -0500
> +++ b/source/output/output.cpp Fri Apr 03 16:22:38 2015 -0700
> @@ -1,7 +1,8 @@
> /*****************************************************************************
> - * Copyright (C) 2013 x265 project
> + * Copyright (C) 2013-2015 x265 project
> *
> * Authors: Steve Borho <steve at borho.org>
> + * Xinyue Lu <i at 7086.in>
> *
> * This program is free software; you can redistribute it and/or modify
> * it under the terms of the GNU General Public License as published by
> @@ -25,6 +26,8 @@
> #include "yuv.h"
> #include "y4m.h"
>
> +#include "raw.h"
> +
> using namespace x265;
>
> ReconFile* ReconFile::open(const char *fname, int width, int
> height, uint32_t bitdepth, uint32_t fpsNum, uint32_t fpsDenom, int
> csp)
> @@ -36,3 +39,8 @@
> else
> return new YUVOutput(fname, width, height, bitdepth, csp);
> }
> +
> +OutputFile* OutputFile::open(const char *fname, InputFileInfo& inputInfo)
> +{
> + return new RAWOutput(fname, inputInfo);
> +}
> diff -r 335c728bbd62 -r f79424a65d40 source/output/output.h
> --- a/source/output/output.h Fri Apr 03 14:27:32 2015 -0500
> +++ b/source/output/output.h Fri Apr 03 16:22:38 2015 -0700
> @@ -1,7 +1,8 @@
> /*****************************************************************************
> - * Copyright (C) 2013 x265 project
> + * Copyright (C) 2013-2015 x265 project
> *
> * Authors: Steve Borho <steve at borho.org>
> + * Xinyue Lu <i at 7086.in>
> *
> * This program is free software; you can redistribute it and/or modify
> * it under the terms of the GNU General Public License as published by
> @@ -25,6 +26,7 @@
> #define X265_OUTPUT_H
>
> #include "x265.h"
> +#include "input/input.h"
>
> namespace x265 {
> // private x265 namespace
> @@ -50,6 +52,35 @@
>
> virtual const char *getName() const = 0;
> };
> +
> +class OutputFile
> +{
> +protected:
> +
> + virtual ~OutputFile() {}
> +
> +public:
> +
> + OutputFile() {}
> +
> + static OutputFile* open(const char *fname, InputFileInfo& inputInfo);
> +
> + virtual bool isFail() const = 0;
> +
> + virtual bool needPTS() const = 0;
> +
> + virtual void release() = 0;
> +
> + virtual const char *getName() const = 0;
> +
> + virtual void setParam(x265_param *param, x265_encoder *encoder) = 0;
> +
> + virtual int writeHeaders(const x265_nal* nal, uint32_t nalcount) = 0;
> +
> + virtual int writeFrame(const x265_nal* nal, uint32_t nalcount, x265_picture& pic) = 0;
> +
> + virtual void closeFile(int64_t largest_pts, int64_t second_largest_pts) = 0;
> +};
> }
>
> #endif // ifndef X265_OUTPUT_H
> diff -r 335c728bbd62 -r f79424a65d40 source/output/raw.cpp
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++ b/source/output/raw.cpp Fri Apr 03 16:22:38 2015 -0700
> @@ -0,0 +1,77 @@
> +/*****************************************************************************
> + * Copyright (C) 2013-2015 x265 project
> + *
> + * Authors: Steve Borho <steve at borho.org>
> + * Xinyue Lu <i at 7086.in>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
> + *
> + * This program is also available under a commercial proprietary license.
> + * For more information, contact us at license @ x265.com.
> + *****************************************************************************/
> +
> +#include "raw.h"
> +
> +using namespace x265;
> +using namespace std;
> +
> +RAWOutput::RAWOutput(const char *fname, InputFileInfo&)
> +{
> + b_fail = false;
> + if (!strcmp(fname, "-"))
> + {
> + ofs = &cout;
> + return;
> + }
> + ofs = new ofstream(fname, ios::binary | ios::out);
> + if (ofs->fail())
> + b_fail = true;
> +}
> +
> +void RAWOutput::setParam(x265_param *, x265_encoder *) { }
> +
> +int RAWOutput::writeHeaders(const x265_nal* nal, uint32_t nalcount)
> +{
> + uint32_t bytes = 0;
> +
> + for (uint32_t i = 0; i < nalcount; i++)
> + {
> + ofs->write((const char*)nal->payload, nal->sizeBytes);
> + bytes += nal->sizeBytes;
> + nal++;
> + }
> +
> + return bytes;
> +}
> +
> +int RAWOutput::writeFrame(const x265_nal* nal, uint32_t nalcount, x265_picture&)
> +{
> + uint32_t bytes = 0;
> +
> + for (uint32_t i = 0; i < nalcount; i++)
> + {
> + ofs->write((const char*)nal->payload, nal->sizeBytes);
> + bytes += nal->sizeBytes;
> + nal++;
> + }
> +
> + return bytes;
> +}
> +
> +void RAWOutput::closeFile(int64_t, int64_t)
> +{
> + if (ofs != &cout)
> + delete ofs;
> +}
> diff -r 335c728bbd62 -r f79424a65d40 source/output/raw.h
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++ b/source/output/raw.h Fri Apr 03 16:22:38 2015 -0700
> @@ -0,0 +1,64 @@
> +/*****************************************************************************
> + * Copyright (C) 2013-2015 x265 project
> + *
> + * Authors: Steve Borho <steve at borho.org>
> + * Xinyue Lu <i at 7086.in>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
> + *
> + * This program is also available under a commercial proprietary license.
> + * For more information, contact us at license @ x265.com.
> + *****************************************************************************/
> +
> +#ifndef X265_HEVC_RAW_H
> +#define X265_HEVC_RAW_H
> +
> +#include "output.h"
> +#include "common.h"
> +#include <fstream>
> +#include <iostream>
> +
> +namespace x265 {
> +class RAWOutput : public OutputFile
> +{
> +protected:
> +
> + std::ostream *ofs;
> +
> + bool b_fail;
> +
> +public:
> +
> + RAWOutput(const char *fname, InputFileInfo&);
> +
> + bool isFail() const { return b_fail; }
> +
> + bool needPTS() const { return false; }
> +
> + void release() { delete this; }
> +
> + const char *getName() const { return "RAW Bitstream"; }
> +
> + void setParam(x265_param *param, x265_encoder *);
> +
> + int writeHeaders(const x265_nal* nal, uint32_t nalcount);
> +
> + int writeFrame(const x265_nal* nal, uint32_t nalcount, x265_picture&);
> +
> + void closeFile(int64_t largest_pts, int64_t second_largest_pts);
> +};
> +}
> +
> +#endif // ifndef X265_HEVC_RAW_H
> diff -r 335c728bbd62 -r f79424a65d40 source/x265.cpp
> --- a/source/x265.cpp Fri Apr 03 14:27:32 2015 -0500
> +++ b/source/x265.cpp Fri Apr 03 16:22:38 2015 -0700
> @@ -46,6 +46,7 @@
> #include <string>
> #include <ostream>
> #include <fstream>
> +#include <queue>
>
> #define CONSOLE_TITLE_SIZE 200
> #ifdef _WIN32
> @@ -70,7 +71,7 @@
> {
> InputFile* input;
> ReconFile* recon;
> - std::fstream bitstreamFile;
> + OutputFile* output;
> bool bProgress;
> bool bForceY4m;
> bool bDither;
> @@ -95,6 +96,7 @@
> frameRate = 0.f;
> input = NULL;
> recon = NULL;
> + output = NULL;
> framesToBeEncoded = seek = 0;
> totalbytes = 0;
> bProgress = true;
> @@ -109,7 +111,6 @@
> }
>
> void destroy();
> - void writeNALs(const x265_nal* nal, uint32_t nalcount);
> void printStatus(uint32_t frameNum, x265_param *param);
> bool parse(int argc, char **argv, x265_param* param);
> bool parseQPFile(x265_picture &pic_org);
> @@ -130,17 +131,9 @@
> if (analysisFile)
> fclose(analysisFile);
> analysisFile = NULL;
> -}
> -
> -void CLIOptions::writeNALs(const x265_nal* nal, uint32_t nalcount)
> -{
> - ProfileScopeEvent(bitstreamWrite);
> - for (uint32_t i = 0; i < nalcount; i++)
> - {
> - bitstreamFile.write((const char*)nal->payload, nal->sizeBytes);
> - totalbytes += nal->sizeBytes;
> - nal++;
> - }
> + if (output)
> + output->release();
> + output = NULL;
> }
>
> void CLIOptions::printStatus(uint32_t frameNum, x265_param *param)
> @@ -178,7 +171,7 @@
> int reconFileBitDepth = 0;
> const char *inputfn = NULL;
> const char *reconfn = NULL;
> - const char *bitstreamfn = NULL;
> + const char *outputfn = NULL;
> const char *preset = NULL;
> const char *tune = NULL;
> const char *profile = NULL;
> @@ -264,7 +257,7 @@
> OPT2("frame-skip", "seek") this->seek = (uint32_t)x265_atoi(optarg, bError);
> OPT("frames") this->framesToBeEncoded = (uint32_t)x265_atoi(optarg, bError);
> OPT("no-progress") this->bProgress = false;
> - OPT("output") bitstreamfn = optarg;
> + OPT("output") outputfn = optarg;
> OPT("input") inputfn = optarg;
> OPT("recon") reconfn = optarg;
> OPT("input-depth") inputBitDepth = (uint32_t)x265_atoi(optarg, bError);
> @@ -298,8 +291,8 @@
>
> if (optind < argc && !inputfn)
> inputfn = argv[optind++];
> - if (optind < argc && !bitstreamfn)
> - bitstreamfn = argv[optind++];
> + if (optind < argc && !outputfn)
> + outputfn = argv[optind++];
> if (optind < argc)
> {
> x265_log(param, X265_LOG_WARNING, "extra unused command arguments given <%s>\n", argv[optind]);
> @@ -309,7 +302,7 @@
> if (argc <= 1 || help)
> showHelp(param);
>
> - if (inputfn == NULL || bitstreamfn == NULL)
> + if (inputfn == NULL || outputfn == NULL)
> {
> x265_log(param, X265_LOG_ERROR, "input or output file not specified, try -V for help\n");
> return true;
> @@ -365,6 +358,10 @@
> this->framesToBeEncoded = info.frameCount - seek;
> param->totalFrames = this->framesToBeEncoded;
>
> + /* Force CFR until we have support for VFR */
> + info.timebaseNum = info.fpsDenom;
> + info.timebaseDenom = info.fpsNum;
> +
> if (x265_param_apply_profile(param, profile))
> return true;
>
> @@ -408,12 +405,13 @@
> x265_source_csp_names[param->internalCsp]);
> }
>
> - this->bitstreamFile.open(bitstreamfn, std::fstream::binary | std::fstream::out);
> - if (!this->bitstreamFile)
> + this->output = OutputFile::open(outputfn, info);
> + if (this->output->isFail())
> {
> - x265_log(NULL, X265_LOG_ERROR, "failed to open bitstream file <%s> for writing\n", bitstreamfn);
> + x265_log(NULL, X265_LOG_ERROR, "failed to open output file <%s> for writing\n", outputfn);
> return true;
> }
> + general_log(param, "out", X265_LOG_INFO, "Using %s\n", this->output->getName());
> return false;
> }
>
> @@ -509,7 +507,8 @@
> x265_picture pic_orig, pic_out;
> x265_picture *pic_in = &pic_orig;
> /* Allocate recon picture if analysisMode is enabled */
> - x265_picture *pic_recon = (cliopt.recon || !!param->analysisMode) ? &pic_out : NULL;
> + bool usePTS = cliopt.output->needPTS();
> + x265_picture *pic_recon = (cliopt.recon || !!param->analysisMode || usePTS) ? &pic_out : NULL;
> uint32_t inFrameCount = 0;
> uint32_t outFrameCount = 0;
> x265_nal *p_nal;
> @@ -517,6 +516,7 @@
> uint32_t nal;
> int16_t *errorBuf = NULL;
> int ret = 0;
> + std::priority_queue<int64_t> pts_queue;
>
> if (!param->bRepeatHeaders)
> {
> @@ -527,7 +527,10 @@
> goto fail;
> }
> else
> - cliopt.writeNALs(p_nal, nal);
> + {
> + cliopt.output->setParam(param, encoder);
> + cliopt.totalbytes += cliopt.output->writeHeaders(p_nal, nal);
> + }
> }
>
> api->picture_init(param, pic_in);
> @@ -569,6 +572,8 @@
> ditherImage(*pic_in, param->sourceWidth, param->sourceHeight, errorBuf, X265_DEPTH);
> pic_in->bitDepth = X265_DEPTH;
> }
> + /* Overwrite PTS */
> + pic_in->pts = pic_in->poc;
> }
>
> int numEncoded = api->encoder_encode(encoder, &p_nal, &nal, pic_in, pic_recon);
> @@ -583,7 +588,15 @@
> if (numEncoded && pic_recon && cliopt.recon)
> cliopt.recon->writePicture(pic_out);
> if (nal)
> - cliopt.writeNALs(p_nal, nal);
> + {
> + cliopt.totalbytes += cliopt.output->writeFrame(p_nal, nal, pic_out);
> + if (usePTS)
> + {
> + pts_queue.push(-pic_out.pts);
> + if (pts_queue.size() > 2)
> + pts_queue.pop();
> + }
> + }
>
> cliopt.printStatus(outFrameCount, param);
> }
> @@ -601,7 +614,15 @@
> if (numEncoded && pic_recon && cliopt.recon)
> cliopt.recon->writePicture(pic_out);
> if (nal)
> - cliopt.writeNALs(p_nal, nal);
> + {
> + cliopt.totalbytes += cliopt.output->writeFrame(p_nal, nal, pic_out);
> + if (usePTS)
> + {
> + pts_queue.push(-pic_out.pts);
> + if (pts_queue.size() > 2)
> + pts_queue.pop();
> + }
> + }
>
> cliopt.printStatus(outFrameCount, param);
>
> @@ -618,7 +639,17 @@
> if (param->csvfn && !b_ctrl_c)
> api->encoder_log(encoder, argc, argv);
> api->encoder_close(encoder);
> - cliopt.bitstreamFile.close();
> +
> + int64_t second_largest_pts = 0;
> + int64_t largest_pts = 0;
> + if (usePTS && pts_queue.size() >= 2)
> + {
> + second_largest_pts = -pts_queue.top();
> + pts_queue.pop();
> + largest_pts = -pts_queue.top();
> + pts_queue.pop();
> + }
> + cliopt.output->closeFile(largest_pts, second_largest_pts);
>
> if (b_ctrl_c)
> general_log(param, NULL, X265_LOG_INFO, "aborted at input frame %d, output frame %d\n",
>
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
--
Steve Borho
More information about the x265-devel
mailing list