[x265] [PATCH for review] cli: Timebase, PTS and output module
Xinyue Lu
maillist at 7086.in
Sat Apr 4 01:25:07 CEST 2015
# 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
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",
More information about the x265-devel
mailing list