[x265] [PATCH] build: export x265-extras in the DLL
deepthi at multicorewareinc.com
deepthi at multicorewareinc.com
Mon Aug 17 13:38:54 CEST 2015
# HG changeset patch
# User Deepthi Nandakumar <deepthi at multicorewareinc.com>
# Date 1439811205 -19800
# Mon Aug 17 17:03:25 2015 +0530
# Node ID 9834fc054362a039580b205323d47fe1561c1ac9
# Parent 996ebce8c874fc511d495cee227d24413e99d0c1
build: export x265-extras in the DLL
diff -r 996ebce8c874 -r 9834fc054362 source/CMakeLists.txt
--- a/source/CMakeLists.txt Mon Aug 17 10:52:15 2015 +0530
+++ b/source/CMakeLists.txt Mon Aug 17 17:03:25 2015 +0530
@@ -535,11 +535,11 @@
if(XCODE)
# Xcode seems unable to link the CLI with libs, so link as one targget
add_executable(cli ../COPYING ${InputFiles} ${OutputFiles} ${GETOPT}
- x265.cpp x265.h x265cli.h x265-extras.h x265-extras.cpp
+ x265.cpp x265.h x265cli.h
$<TARGET_OBJECTS:encoder> $<TARGET_OBJECTS:common> ${YASM_OBJS} ${YASM_SRCS})
else()
add_executable(cli ../COPYING ${InputFiles} ${OutputFiles} ${GETOPT} ${X265_RC_FILE}
- ${ExportDefs} x265.cpp x265.h x265cli.h x265-extras.h x265-extras.cpp)
+ ${ExportDefs} x265.cpp x265.h x265cli.h)
if(WIN32 OR NOT ENABLE_SHARED OR INTEL_CXX)
# The CLI cannot link to the shared library on Windows, it
# requires internal APIs not exported from the DLL
diff -r 996ebce8c874 -r 9834fc054362 source/common/CMakeLists.txt
--- a/source/common/CMakeLists.txt Mon Aug 17 10:52:15 2015 +0530
+++ b/source/common/CMakeLists.txt Mon Aug 17 17:03:25 2015 +0530
@@ -110,4 +110,5 @@
predict.cpp predict.h
scalinglist.cpp scalinglist.h
quant.cpp quant.h contexts.h
- deblock.cpp deblock.h)
+ deblock.cpp deblock.h
+ x265-extras.cpp x265-extras.h)
diff -r 996ebce8c874 -r 9834fc054362 source/common/x265-extras.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/source/common/x265-extras.cpp Mon Aug 17 17:03:25 2015 +0530
@@ -0,0 +1,341 @@
+/*****************************************************************************
+ * Copyright (C) 2015 x265 project
+ *
+ * Authors: Steve Borho <steve at borho.org>
+ * Selvakumar Nithiyaruban <selvakumar at multicorewareinc.com>
+ * Divya Manivannan <divya at multicorewareinc.com>
+ *
+ * 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 "x265.h"
+#include "x265-extras.h"
+
+#include "common.h"
+
+using namespace X265_NS;
+
+static const char* summaryCSVHeader =
+ "Command, Date/Time, Elapsed Time, FPS, Bitrate, "
+ "Y PSNR, U PSNR, V PSNR, Global PSNR, SSIM, SSIM (dB), "
+ "I count, I ave-QP, I kbps, I-PSNR Y, I-PSNR U, I-PSNR V, I-SSIM (dB), "
+ "P count, P ave-QP, P kbps, P-PSNR Y, P-PSNR U, P-PSNR V, P-SSIM (dB), "
+ "B count, B ave-QP, B kbps, B-PSNR Y, B-PSNR U, B-PSNR V, B-SSIM (dB), "
+ "MaxCLL, MaxFALL, Version\n";
+
+FILE* x265_csvlog_open(const x265_api& api, const x265_param& param, const char* fname, int level)
+{
+ if (sizeof(x265_stats) != api.sizeof_stats || sizeof(x265_picture) != api.sizeof_picture)
+ {
+ fprintf(stderr, "extras [error]: structure size skew, unable to create CSV logfile\n");
+ return NULL;
+ }
+
+ FILE *csvfp = fopen(fname, "r");
+ if (csvfp)
+ {
+ /* file already exists, re-open for append */
+ fclose(csvfp);
+ return fopen(fname, "ab");
+ }
+ else
+ {
+ /* new CSV file, write header */
+ csvfp = fopen(fname, "wb");
+ if (csvfp)
+ {
+ if (level)
+ {
+ fprintf(csvfp, "Encode Order, Type, POC, QP, Bits, ");
+ if (param.rc.rateControlMode == X265_RC_CRF)
+ fprintf(csvfp, "RateFactor, ");
+ fprintf(csvfp, "Y PSNR, U PSNR, V PSNR, YUV PSNR, SSIM, SSIM (dB), List 0, List 1");
+ /* detailed performance statistics */
+ fprintf(csvfp, ", DecideWait (ms), Row0Wait (ms), Wall time (ms), Ref Wait Wall (ms), Total CTU time (ms), Stall Time (ms), Avg WPP, Row Blocks");
+ if (level >= 2)
+ {
+ uint32_t size = param.maxCUSize;
+ for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
+ {
+ fprintf(csvfp, ", Intra %dx%d DC, Intra %dx%d Planar, Intra %dx%d Ang", size, size, size, size, size, size);
+ size /= 2;
+ }
+ fprintf(csvfp, ", 4x4");
+ size = param.maxCUSize;
+ if (param.bEnableRectInter)
+ {
+ for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
+ {
+ fprintf(csvfp, ", Inter %dx%d, Inter %dx%d (Rect)", size, size, size, size);
+ if (param.bEnableAMP)
+ fprintf(csvfp, ", Inter %dx%d (Amp)", size, size);
+ size /= 2;
+ }
+ }
+ else
+ {
+ for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
+ {
+ fprintf(csvfp, ", Inter %dx%d", size, size);
+ size /= 2;
+ }
+ }
+ size = param.maxCUSize;
+ for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
+ {
+ fprintf(csvfp, ", Skip %dx%d", size, size);
+ size /= 2;
+ }
+ size = param.maxCUSize;
+ for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
+ {
+ fprintf(csvfp, ", Merge %dx%d", size, size);
+ size /= 2;
+ }
+ fprintf(csvfp, ", Avg Luma Distortion, Avg Chroma Distortion, Avg psyEnergy, Avg Luma Level, Max Luma Level");
+ }
+ fprintf(csvfp, "\n");
+ }
+ else
+ fputs(summaryCSVHeader, csvfp);
+ }
+ return csvfp;
+ }
+}
+
+// per frame CSV logging
+void x265_csvlog_frame(FILE* csvfp, const x265_param& param, const x265_picture& pic, int level)
+{
+ if (!csvfp)
+ return;
+
+ const x265_frame_stats* frameStats = &pic.frameData;
+ fprintf(csvfp, "%d, %c-SLICE, %4d, %2.2lf, %10d,", frameStats->encoderOrder, frameStats->sliceType, frameStats->poc, frameStats->qp, (int)frameStats->bits);
+ if (param.rc.rateControlMode == X265_RC_CRF)
+ fprintf(csvfp, "%.3lf,", frameStats->rateFactor);
+ if (param.bEnablePsnr)
+ fprintf(csvfp, "%.3lf, %.3lf, %.3lf, %.3lf,", frameStats->psnrY, frameStats->psnrU, frameStats->psnrV, frameStats->psnr);
+ else
+ fputs(" -, -, -, -,", csvfp);
+ if (param.bEnableSsim)
+ fprintf(csvfp, " %.6f, %6.3f,", frameStats->ssim, x265_ssim2dB(frameStats->ssim));
+ else
+ fputs(" -, -,", csvfp);
+ if (frameStats->sliceType == 'I')
+ fputs(" -, -,", csvfp);
+ else
+ {
+ int i = 0;
+ while (frameStats->list0POC[i] != -1)
+ fprintf(csvfp, "%d ", frameStats->list0POC[i++]);
+ fprintf(csvfp, ",");
+ if (frameStats->sliceType != 'P')
+ {
+ i = 0;
+ while (frameStats->list1POC[i] != -1)
+ fprintf(csvfp, "%d ", frameStats->list1POC[i++]);
+ fprintf(csvfp, ",");
+ }
+ else
+ fputs(" -,", csvfp);
+ }
+ fprintf(csvfp, " %.1lf, %.1lf, %.1lf, %.1lf, %.1lf, %.1lf,", frameStats->decideWaitTime, frameStats->row0WaitTime, frameStats->wallTime, frameStats->refWaitWallTime, frameStats->totalCTUTime, frameStats->stallTime);
+ fprintf(csvfp, " %.3lf, %d", frameStats->avgWPP, frameStats->countRowBlocks);
+ if (level >= 2)
+ {
+ for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
+ fprintf(csvfp, ", %5.2lf%%, %5.2lf%%, %5.2lf%%", frameStats->cuStats.percentIntraDistribution[depth][0], frameStats->cuStats.percentIntraDistribution[depth][1], frameStats->cuStats.percentIntraDistribution[depth][2]);
+ fprintf(csvfp, ", %5.2lf%%", frameStats->cuStats.percentIntraNxN);
+ if (param.bEnableRectInter)
+ {
+ for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
+ {
+ fprintf(csvfp, ", %5.2lf%%, %5.2lf%%", frameStats->cuStats.percentInterDistribution[depth][0], frameStats->cuStats.percentInterDistribution[depth][1]);
+ if (param.bEnableAMP)
+ fprintf(csvfp, ", %5.2lf%%", frameStats->cuStats.percentInterDistribution[depth][2]);
+ }
+ }
+ else
+ {
+ for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
+ fprintf(csvfp, ", %5.2lf%%", frameStats->cuStats.percentInterDistribution[depth][0]);
+ }
+ for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
+ fprintf(csvfp, ", %5.2lf%%", frameStats->cuStats.percentSkipCu[depth]);
+ for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
+ fprintf(csvfp, ", %5.2lf%%", frameStats->cuStats.percentMergeCu[depth]);
+ fprintf(csvfp, ", %.2lf, %.2lf, %.2lf, %.2lf, %d", frameStats->avgLumaDistortion, frameStats->avgChromaDistortion, frameStats->avgPsyEnergy, frameStats->avgLumaLevel, frameStats->maxLumaLevel);
+ }
+ fprintf(csvfp, "\n");
+ fflush(stderr);
+}
+
+void x265_csvlog_encode(FILE* csvfp, const x265_api& api, const x265_param& param, const x265_stats& stats, int level, int argc, char** argv)
+{
+ if (!csvfp)
+ return;
+
+ if (level)
+ {
+ // adding summary to a per-frame csv log file, so it needs a summary header
+ fprintf(csvfp, "\nSummary\n");
+ fputs(summaryCSVHeader, csvfp);
+ }
+
+ // CLI arguments or other
+ for (int i = 1; i < argc; i++)
+ {
+ if (i) fputc(' ', csvfp);
+ fputs(argv[i], csvfp);
+ }
+
+ // current date and time
+ time_t now;
+ struct tm* timeinfo;
+ time(&now);
+ timeinfo = localtime(&now);
+ char buffer[200];
+ strftime(buffer, 128, "%c", timeinfo);
+ fprintf(csvfp, ", %s, ", buffer);
+
+ // elapsed time, fps, bitrate
+ fprintf(csvfp, "%.2f, %.2f, %.2f,",
+ stats.elapsedEncodeTime, stats.encodedPictureCount / stats.elapsedEncodeTime, stats.bitrate);
+
+ if (param.bEnablePsnr)
+ fprintf(csvfp, " %.3lf, %.3lf, %.3lf, %.3lf,",
+ stats.globalPsnrY / stats.encodedPictureCount, stats.globalPsnrU / stats.encodedPictureCount,
+ stats.globalPsnrV / stats.encodedPictureCount, stats.globalPsnr);
+ else
+ fprintf(csvfp, " -, -, -, -,");
+ if (param.bEnableSsim)
+ fprintf(csvfp, " %.6f, %6.3f,", stats.globalSsim, x265_ssim2dB(stats.globalSsim));
+ else
+ fprintf(csvfp, " -, -,");
+
+ if (stats.statsI.numPics)
+ {
+ fprintf(csvfp, " %-6u, %2.2lf, %-8.2lf,", stats.statsI.numPics, stats.statsI.avgQp, stats.statsI.bitrate);
+ if (param.bEnablePsnr)
+ fprintf(csvfp, " %.3lf, %.3lf, %.3lf,", stats.statsI.psnrY, stats.statsI.psnrU, stats.statsI.psnrV);
+ else
+ fprintf(csvfp, " -, -, -,");
+ if (param.bEnableSsim)
+ fprintf(csvfp, " %.3lf,", stats.statsI.ssim);
+ else
+ fprintf(csvfp, " -,");
+ }
+ else
+ fprintf(csvfp, " -, -, -, -, -, -, -,");
+
+ if (stats.statsP.numPics)
+ {
+ fprintf(csvfp, " %-6u, %2.2lf, %-8.2lf,", stats.statsP.numPics, stats.statsP.avgQp, stats.statsP.bitrate);
+ if (param.bEnablePsnr)
+ fprintf(csvfp, " %.3lf, %.3lf, %.3lf,", stats.statsP.psnrY, stats.statsP.psnrU, stats.statsP.psnrV);
+ else
+ fprintf(csvfp, " -, -, -,");
+ if (param.bEnableSsim)
+ fprintf(csvfp, " %.3lf,", stats.statsP.ssim);
+ else
+ fprintf(csvfp, " -,");
+ }
+ else
+ fprintf(csvfp, " -, -, -, -, -, -, -,");
+
+ if (stats.statsB.numPics)
+ {
+ fprintf(csvfp, " %-6u, %2.2lf, %-8.2lf,", stats.statsB.numPics, stats.statsB.avgQp, stats.statsB.bitrate);
+ if (param.bEnablePsnr)
+ fprintf(csvfp, " %.3lf, %.3lf, %.3lf,", stats.statsB.psnrY, stats.statsB.psnrU, stats.statsB.psnrV);
+ else
+ fprintf(csvfp, " -, -, -,");
+ if (param.bEnableSsim)
+ fprintf(csvfp, " %.3lf,", stats.statsB.ssim);
+ else
+ fprintf(csvfp, " -,");
+ }
+ else
+ fprintf(csvfp, " -, -, -, -, -, -, -,");
+
+ fprintf(csvfp, " %-6u, %-6u, %s\n", stats.maxCLL, stats.maxFALL, api.version_str);
+}
+
+/* The dithering algorithm is based on Sierra-2-4A error diffusion. */
+static void ditherPlane(pixel *dst, int dstStride, uint16_t *src, int srcStride,
+ int width, int height, int16_t *errors, int bitDepth)
+{
+ const int lShift = 16 - bitDepth;
+ const int rShift = 16 - bitDepth + 2;
+ const int half = (1 << (16 - bitDepth + 1));
+ const int pixelMax = (1 << bitDepth) - 1;
+
+ memset(errors, 0, (width + 1) * sizeof(int16_t));
+ int pitch = 1;
+ for (int y = 0; y < height; y++, src += srcStride, dst += dstStride)
+ {
+ int16_t err = 0;
+ for (int x = 0; x < width; x++)
+ {
+ err = err * 2 + errors[x] + errors[x + 1];
+ dst[x * pitch] = (pixel)x265_clip3(0, pixelMax, ((src[x * 1] << 2) + err + half) >> rShift);
+ errors[x] = err = src[x * pitch] - (dst[x * pitch] << lShift);
+ }
+ }
+}
+
+void x265_dither_image(const x265_api& api, x265_picture& picIn, int picWidth, int picHeight, int16_t *errorBuf, int bitDepth)
+{
+ if (sizeof(x265_picture) != api.sizeof_picture)
+ {
+ fprintf(stderr, "extras [error]: structure size skew, unable to dither\n");
+ return;
+ }
+
+ if (picIn.bitDepth <= 8)
+ {
+ fprintf(stderr, "extras [error]: dither support enabled only for input bitdepth > 8\n");
+ return;
+ }
+
+ /* This portion of code is from readFrame in x264. */
+ for (int i = 0; i < x265_cli_csps[picIn.colorSpace].planes; i++)
+ {
+ if ((picIn.bitDepth & 7) && (picIn.bitDepth != 16))
+ {
+ /* upconvert non 16bit high depth planes to 16bit */
+ uint16_t *plane = (uint16_t*)picIn.planes[i];
+ uint32_t pixelCount = x265_picturePlaneSize(picIn.colorSpace, picWidth, picHeight, i);
+ int lShift = 16 - picIn.bitDepth;
+
+ /* This loop assumes width is equal to stride which
+ * happens to be true for file reader outputs */
+ for (uint32_t j = 0; j < pixelCount; j++)
+ plane[j] = plane[j] << lShift;
+ }
+ }
+
+ for (int i = 0; i < x265_cli_csps[picIn.colorSpace].planes; i++)
+ {
+ int height = (int)(picHeight >> x265_cli_csps[picIn.colorSpace].height[i]);
+ int width = (int)(picWidth >> x265_cli_csps[picIn.colorSpace].width[i]);
+
+ ditherPlane(((pixel*)picIn.planes[i]), picIn.stride[i] / sizeof(pixel), ((uint16_t*)picIn.planes[i]),
+ picIn.stride[i] / 2, width, height, errorBuf, bitDepth);
+ }
+}
diff -r 996ebce8c874 -r 9834fc054362 source/common/x265-extras.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/source/common/x265-extras.h Mon Aug 17 17:03:25 2015 +0530
@@ -0,0 +1,60 @@
+/*****************************************************************************
+ * Copyright (C) 2015 x265 project
+ *
+ * Authors: Steve Borho <steve at borho.org>
+ *
+ * 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_EXTRAS_H
+#define X265_EXTRAS_H 1
+
+#include "x265.h"
+
+#include <stdio.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Open a CSV log file. On success it returns a file handle which must be passed
+ * to x265_csvlog_frame() and/or x265_csvlog_encode(). The file handle must be
+ * closed by the caller using fclose(). If level is 0, then no frame logging
+ * header is written to the file. This function will return NULL if it is unable
+ * to open the file for write or if it detects a structure size skew */
+FILE* x265_csvlog_open(const x265_api& api, const x265_param& param, const char* fname, int level);
+
+/* Log frame statistics to the CSV file handle. level should have been non-zero
+ * in the call to x265_csvlog_open() if this function is called. */
+void x265_csvlog_frame(FILE* csvfp, const x265_param& param, const x265_picture& pic, int level);
+
+/* Log final encode statistics to the CSV file handle. 'argc' and 'argv' are
+ * intended to be command line arguments passed to the encoder. Encode
+ * statistics should be queried from the encoder just prior to closing it. */
+void x265_csvlog_encode(FILE* csvfp, const x265_api& api, const x265_param& param, const x265_stats& stats, int level, int argc, char** argv);
+
+/* In-place downshift from a bit-depth greater than 8 to a bit-depth of 8, using
+ * the residual bits to dither each row. */
+void x265_dither_image(const x265_api& api, x265_picture&, int picWidth, int picHeight, int16_t *errorBuf, int bitDepth);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -r 996ebce8c874 -r 9834fc054362 source/x265-extras.cpp
--- a/source/x265-extras.cpp Mon Aug 17 10:52:15 2015 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,341 +0,0 @@
-/*****************************************************************************
- * Copyright (C) 2015 x265 project
- *
- * Authors: Steve Borho <steve at borho.org>
- * Selvakumar Nithiyaruban <selvakumar at multicorewareinc.com>
- * Divya Manivannan <divya at multicorewareinc.com>
- *
- * 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 "x265.h"
-#include "x265-extras.h"
-
-#include "common.h"
-
-using namespace X265_NS;
-
-static const char* summaryCSVHeader =
- "Command, Date/Time, Elapsed Time, FPS, Bitrate, "
- "Y PSNR, U PSNR, V PSNR, Global PSNR, SSIM, SSIM (dB), "
- "I count, I ave-QP, I kbps, I-PSNR Y, I-PSNR U, I-PSNR V, I-SSIM (dB), "
- "P count, P ave-QP, P kbps, P-PSNR Y, P-PSNR U, P-PSNR V, P-SSIM (dB), "
- "B count, B ave-QP, B kbps, B-PSNR Y, B-PSNR U, B-PSNR V, B-SSIM (dB), "
- "MaxCLL, MaxFALL, Version\n";
-
-FILE* x265_csvlog_open(const x265_api& api, const x265_param& param, const char* fname, int level)
-{
- if (sizeof(x265_stats) != api.sizeof_stats || sizeof(x265_picture) != api.sizeof_picture)
- {
- fprintf(stderr, "extras [error]: structure size skew, unable to create CSV logfile\n");
- return NULL;
- }
-
- FILE *csvfp = fopen(fname, "r");
- if (csvfp)
- {
- /* file already exists, re-open for append */
- fclose(csvfp);
- return fopen(fname, "ab");
- }
- else
- {
- /* new CSV file, write header */
- csvfp = fopen(fname, "wb");
- if (csvfp)
- {
- if (level)
- {
- fprintf(csvfp, "Encode Order, Type, POC, QP, Bits, ");
- if (param.rc.rateControlMode == X265_RC_CRF)
- fprintf(csvfp, "RateFactor, ");
- fprintf(csvfp, "Y PSNR, U PSNR, V PSNR, YUV PSNR, SSIM, SSIM (dB), List 0, List 1");
- /* detailed performance statistics */
- fprintf(csvfp, ", DecideWait (ms), Row0Wait (ms), Wall time (ms), Ref Wait Wall (ms), Total CTU time (ms), Stall Time (ms), Avg WPP, Row Blocks");
- if (level >= 2)
- {
- uint32_t size = param.maxCUSize;
- for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
- {
- fprintf(csvfp, ", Intra %dx%d DC, Intra %dx%d Planar, Intra %dx%d Ang", size, size, size, size, size, size);
- size /= 2;
- }
- fprintf(csvfp, ", 4x4");
- size = param.maxCUSize;
- if (param.bEnableRectInter)
- {
- for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
- {
- fprintf(csvfp, ", Inter %dx%d, Inter %dx%d (Rect)", size, size, size, size);
- if (param.bEnableAMP)
- fprintf(csvfp, ", Inter %dx%d (Amp)", size, size);
- size /= 2;
- }
- }
- else
- {
- for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
- {
- fprintf(csvfp, ", Inter %dx%d", size, size);
- size /= 2;
- }
- }
- size = param.maxCUSize;
- for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
- {
- fprintf(csvfp, ", Skip %dx%d", size, size);
- size /= 2;
- }
- size = param.maxCUSize;
- for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
- {
- fprintf(csvfp, ", Merge %dx%d", size, size);
- size /= 2;
- }
- fprintf(csvfp, ", Avg Luma Distortion, Avg Chroma Distortion, Avg psyEnergy, Avg Luma Level, Max Luma Level");
- }
- fprintf(csvfp, "\n");
- }
- else
- fputs(summaryCSVHeader, csvfp);
- }
- return csvfp;
- }
-}
-
-// per frame CSV logging
-void x265_csvlog_frame(FILE* csvfp, const x265_param& param, const x265_picture& pic, int level)
-{
- if (!csvfp)
- return;
-
- const x265_frame_stats* frameStats = &pic.frameData;
- fprintf(csvfp, "%d, %c-SLICE, %4d, %2.2lf, %10d,", frameStats->encoderOrder, frameStats->sliceType, frameStats->poc, frameStats->qp, (int)frameStats->bits);
- if (param.rc.rateControlMode == X265_RC_CRF)
- fprintf(csvfp, "%.3lf,", frameStats->rateFactor);
- if (param.bEnablePsnr)
- fprintf(csvfp, "%.3lf, %.3lf, %.3lf, %.3lf,", frameStats->psnrY, frameStats->psnrU, frameStats->psnrV, frameStats->psnr);
- else
- fputs(" -, -, -, -,", csvfp);
- if (param.bEnableSsim)
- fprintf(csvfp, " %.6f, %6.3f,", frameStats->ssim, x265_ssim2dB(frameStats->ssim));
- else
- fputs(" -, -,", csvfp);
- if (frameStats->sliceType == 'I')
- fputs(" -, -,", csvfp);
- else
- {
- int i = 0;
- while (frameStats->list0POC[i] != -1)
- fprintf(csvfp, "%d ", frameStats->list0POC[i++]);
- fprintf(csvfp, ",");
- if (frameStats->sliceType != 'P')
- {
- i = 0;
- while (frameStats->list1POC[i] != -1)
- fprintf(csvfp, "%d ", frameStats->list1POC[i++]);
- fprintf(csvfp, ",");
- }
- else
- fputs(" -,", csvfp);
- }
- fprintf(csvfp, " %.1lf, %.1lf, %.1lf, %.1lf, %.1lf, %.1lf,", frameStats->decideWaitTime, frameStats->row0WaitTime, frameStats->wallTime, frameStats->refWaitWallTime, frameStats->totalCTUTime, frameStats->stallTime);
- fprintf(csvfp, " %.3lf, %d", frameStats->avgWPP, frameStats->countRowBlocks);
- if (level >= 2)
- {
- for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
- fprintf(csvfp, ", %5.2lf%%, %5.2lf%%, %5.2lf%%", frameStats->cuStats.percentIntraDistribution[depth][0], frameStats->cuStats.percentIntraDistribution[depth][1], frameStats->cuStats.percentIntraDistribution[depth][2]);
- fprintf(csvfp, ", %5.2lf%%", frameStats->cuStats.percentIntraNxN);
- if (param.bEnableRectInter)
- {
- for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
- {
- fprintf(csvfp, ", %5.2lf%%, %5.2lf%%", frameStats->cuStats.percentInterDistribution[depth][0], frameStats->cuStats.percentInterDistribution[depth][1]);
- if (param.bEnableAMP)
- fprintf(csvfp, ", %5.2lf%%", frameStats->cuStats.percentInterDistribution[depth][2]);
- }
- }
- else
- {
- for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
- fprintf(csvfp, ", %5.2lf%%", frameStats->cuStats.percentInterDistribution[depth][0]);
- }
- for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
- fprintf(csvfp, ", %5.2lf%%", frameStats->cuStats.percentSkipCu[depth]);
- for (uint32_t depth = 0; depth <= g_maxCUDepth; depth++)
- fprintf(csvfp, ", %5.2lf%%", frameStats->cuStats.percentMergeCu[depth]);
- fprintf(csvfp, ", %.2lf, %.2lf, %.2lf, %.2lf, %d", frameStats->avgLumaDistortion, frameStats->avgChromaDistortion, frameStats->avgPsyEnergy, frameStats->avgLumaLevel, frameStats->maxLumaLevel);
- }
- fprintf(csvfp, "\n");
- fflush(stderr);
-}
-
-void x265_csvlog_encode(FILE* csvfp, const x265_api& api, const x265_param& param, const x265_stats& stats, int level, int argc, char** argv)
-{
- if (!csvfp)
- return;
-
- if (level)
- {
- // adding summary to a per-frame csv log file, so it needs a summary header
- fprintf(csvfp, "\nSummary\n");
- fputs(summaryCSVHeader, csvfp);
- }
-
- // CLI arguments or other
- for (int i = 1; i < argc; i++)
- {
- if (i) fputc(' ', csvfp);
- fputs(argv[i], csvfp);
- }
-
- // current date and time
- time_t now;
- struct tm* timeinfo;
- time(&now);
- timeinfo = localtime(&now);
- char buffer[200];
- strftime(buffer, 128, "%c", timeinfo);
- fprintf(csvfp, ", %s, ", buffer);
-
- // elapsed time, fps, bitrate
- fprintf(csvfp, "%.2f, %.2f, %.2f,",
- stats.elapsedEncodeTime, stats.encodedPictureCount / stats.elapsedEncodeTime, stats.bitrate);
-
- if (param.bEnablePsnr)
- fprintf(csvfp, " %.3lf, %.3lf, %.3lf, %.3lf,",
- stats.globalPsnrY / stats.encodedPictureCount, stats.globalPsnrU / stats.encodedPictureCount,
- stats.globalPsnrV / stats.encodedPictureCount, stats.globalPsnr);
- else
- fprintf(csvfp, " -, -, -, -,");
- if (param.bEnableSsim)
- fprintf(csvfp, " %.6f, %6.3f,", stats.globalSsim, x265_ssim2dB(stats.globalSsim));
- else
- fprintf(csvfp, " -, -,");
-
- if (stats.statsI.numPics)
- {
- fprintf(csvfp, " %-6u, %2.2lf, %-8.2lf,", stats.statsI.numPics, stats.statsI.avgQp, stats.statsI.bitrate);
- if (param.bEnablePsnr)
- fprintf(csvfp, " %.3lf, %.3lf, %.3lf,", stats.statsI.psnrY, stats.statsI.psnrU, stats.statsI.psnrV);
- else
- fprintf(csvfp, " -, -, -,");
- if (param.bEnableSsim)
- fprintf(csvfp, " %.3lf,", stats.statsI.ssim);
- else
- fprintf(csvfp, " -,");
- }
- else
- fprintf(csvfp, " -, -, -, -, -, -, -,");
-
- if (stats.statsP.numPics)
- {
- fprintf(csvfp, " %-6u, %2.2lf, %-8.2lf,", stats.statsP.numPics, stats.statsP.avgQp, stats.statsP.bitrate);
- if (param.bEnablePsnr)
- fprintf(csvfp, " %.3lf, %.3lf, %.3lf,", stats.statsP.psnrY, stats.statsP.psnrU, stats.statsP.psnrV);
- else
- fprintf(csvfp, " -, -, -,");
- if (param.bEnableSsim)
- fprintf(csvfp, " %.3lf,", stats.statsP.ssim);
- else
- fprintf(csvfp, " -,");
- }
- else
- fprintf(csvfp, " -, -, -, -, -, -, -,");
-
- if (stats.statsB.numPics)
- {
- fprintf(csvfp, " %-6u, %2.2lf, %-8.2lf,", stats.statsB.numPics, stats.statsB.avgQp, stats.statsB.bitrate);
- if (param.bEnablePsnr)
- fprintf(csvfp, " %.3lf, %.3lf, %.3lf,", stats.statsB.psnrY, stats.statsB.psnrU, stats.statsB.psnrV);
- else
- fprintf(csvfp, " -, -, -,");
- if (param.bEnableSsim)
- fprintf(csvfp, " %.3lf,", stats.statsB.ssim);
- else
- fprintf(csvfp, " -,");
- }
- else
- fprintf(csvfp, " -, -, -, -, -, -, -,");
-
- fprintf(csvfp, " %-6u, %-6u, %s\n", stats.maxCLL, stats.maxFALL, api.version_str);
-}
-
-/* The dithering algorithm is based on Sierra-2-4A error diffusion. */
-static void ditherPlane(pixel *dst, int dstStride, uint16_t *src, int srcStride,
- int width, int height, int16_t *errors, int bitDepth)
-{
- const int lShift = 16 - bitDepth;
- const int rShift = 16 - bitDepth + 2;
- const int half = (1 << (16 - bitDepth + 1));
- const int pixelMax = (1 << bitDepth) - 1;
-
- memset(errors, 0, (width + 1) * sizeof(int16_t));
- int pitch = 1;
- for (int y = 0; y < height; y++, src += srcStride, dst += dstStride)
- {
- int16_t err = 0;
- for (int x = 0; x < width; x++)
- {
- err = err * 2 + errors[x] + errors[x + 1];
- dst[x * pitch] = (pixel)x265_clip3(0, pixelMax, ((src[x * 1] << 2) + err + half) >> rShift);
- errors[x] = err = src[x * pitch] - (dst[x * pitch] << lShift);
- }
- }
-}
-
-void x265_dither_image(const x265_api& api, x265_picture& picIn, int picWidth, int picHeight, int16_t *errorBuf, int bitDepth)
-{
- if (sizeof(x265_picture) != api.sizeof_picture)
- {
- fprintf(stderr, "extras [error]: structure size skew, unable to dither\n");
- return;
- }
-
- if (picIn.bitDepth <= 8)
- {
- fprintf(stderr, "extras [error]: dither support enabled only for input bitdepth > 8\n");
- return;
- }
-
- /* This portion of code is from readFrame in x264. */
- for (int i = 0; i < x265_cli_csps[picIn.colorSpace].planes; i++)
- {
- if ((picIn.bitDepth & 7) && (picIn.bitDepth != 16))
- {
- /* upconvert non 16bit high depth planes to 16bit */
- uint16_t *plane = (uint16_t*)picIn.planes[i];
- uint32_t pixelCount = x265_picturePlaneSize(picIn.colorSpace, picWidth, picHeight, i);
- int lShift = 16 - picIn.bitDepth;
-
- /* This loop assumes width is equal to stride which
- * happens to be true for file reader outputs */
- for (uint32_t j = 0; j < pixelCount; j++)
- plane[j] = plane[j] << lShift;
- }
- }
-
- for (int i = 0; i < x265_cli_csps[picIn.colorSpace].planes; i++)
- {
- int height = (int)(picHeight >> x265_cli_csps[picIn.colorSpace].height[i]);
- int width = (int)(picWidth >> x265_cli_csps[picIn.colorSpace].width[i]);
-
- ditherPlane(((pixel*)picIn.planes[i]), picIn.stride[i] / sizeof(pixel), ((uint16_t*)picIn.planes[i]),
- picIn.stride[i] / 2, width, height, errorBuf, bitDepth);
- }
-}
diff -r 996ebce8c874 -r 9834fc054362 source/x265-extras.h
--- a/source/x265-extras.h Mon Aug 17 10:52:15 2015 +0530
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*****************************************************************************
- * Copyright (C) 2015 x265 project
- *
- * Authors: Steve Borho <steve at borho.org>
- *
- * 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_EXTRAS_H
-#define X265_EXTRAS_H 1
-
-#include "x265.h"
-
-#include <stdio.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if _WIN32
-#define LIBAPI __declspec(dllexport)
-#else
-#define LIBAPI
-#endif
-
-/* Open a CSV log file. On success it returns a file handle which must be passed
- * to x265_csvlog_frame() and/or x265_csvlog_encode(). The file handle must be
- * closed by the caller using fclose(). If level is 0, then no frame logging
- * header is written to the file. This function will return NULL if it is unable
- * to open the file for write or if it detects a structure size skew */
-LIBAPI FILE* x265_csvlog_open(const x265_api& api, const x265_param& param, const char* fname, int level);
-
-/* Log frame statistics to the CSV file handle. level should have been non-zero
- * in the call to x265_csvlog_open() if this function is called. */
-LIBAPI void x265_csvlog_frame(FILE* csvfp, const x265_param& param, const x265_picture& pic, int level);
-
-/* Log final encode statistics to the CSV file handle. 'argc' and 'argv' are
- * intended to be command line arguments passed to the encoder. Encode
- * statistics should be queried from the encoder just prior to closing it. */
-LIBAPI void x265_csvlog_encode(FILE* csvfp, const x265_api& api, const x265_param& param, const x265_stats& stats, int level, int argc, char** argv);
-
-/* In-place downshift from a bit-depth greater than 8 to a bit-depth of 8, using
- * the residual bits to dither each row. */
-LIBAPI void x265_dither_image(const x265_api& api, x265_picture&, int picWidth, int picHeight, int16_t *errorBuf, int bitDepth);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff -r 996ebce8c874 -r 9834fc054362 source/x265.def.in
--- a/source/x265.def.in Mon Aug 17 10:52:15 2015 +0530
+++ b/source/x265.def.in Mon Aug 17 17:03:25 2015 +0530
@@ -22,3 +22,7 @@
x265_cleanup
x265_api_get_${X265_BUILD}
x265_api_query
+x265_csvlog_open
+x265_csvlog_frame
+x265_csvlog_encode
+x265_dither_image
More information about the x265-devel
mailing list