<div dir="ltr">Why are file reads required to compute vmaf? The recon and original yuv sources are available. <div><br></div><div>Why floating point reads? </div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Apr 12, 2018 at 5:31 PM, Ashok Kumar Mishra <span dir="ltr"><<a href="mailto:ashok@multicorewareinc.com" target="_blank">ashok@multicorewareinc.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="h5">On Thu, Apr 12, 2018 at 4:43 PM,  <span dir="ltr"><<a href="mailto:indumathi@multicorewareinc.com" target="_blank">indumathi@multicorewareinc.<wbr>com</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5"><span># HG changeset patch<br>
# User IndumathiR<<a href="mailto:indumathi@multicorewareinc.com" target="_blank">indumathi@multicore<wbr>wareinc.com</a>><br>
# Date 1518528290 -19800<br>
#      Tue Feb 13 18:54:50 2018 +0530<br>
</span># Node ID 27e3b161cd8b59ad1cae67a96e11e3<wbr>e0506d5017<br>
# Parent  04a337abd70de269cef7d9655365f3<wbr>a3ebde02aa<br>
<span>Add VMAF suppport to report per frame and aggregate VMAF score<br>
<br>
</span>diff -r 04a337abd70d -r 27e3b161cd8b doc/reST/api.rst<br>
--- a/doc/reST/api.rst  Thu Apr 12 15:10:59 2018 +0530<br>
<div><div class="m_-8146764849290315441h5">+++ b/doc/reST/api.rst  Tue Feb 13 18:54:50 2018 +0530<br>
@@ -398,7 +398,30 @@<br>
         *     release library static allocations, reset configured CTU size */<br>
        void x265_cleanup(void);<br>
<br>
+VMAF (Video Multi-Method Assessment Fusion)<br>
+=============================<wbr>=============<br>
<br>
+If you set the ENABLE_LIBVMAF cmake option to ON, then x265 will report per frame<br>
+and aggregate VMAF score for the given input and dump the scores in csv file.<br>
+The user also need to specify the :option:`--recon` in command line to get the VMAF scores.<br>
+<br>
+    /* x265_calculate_vmafScore:<br>
+     *    returns VMAF score for the input video.<br>
+     *    This api must be called only after encoding was done. */<br>
+    double x265_calculate_vmafscore(x265_<wbr>param*, x265_vmaf_data*);<br>
+<br>
+    /* x265_calculate_vmaf_framelevel<wbr>score:<br>
+     *    returns VMAF score for each frame in a given input video. */<br>
+    double x265_calculate_vmaf_framelevel<wbr>score(x265_vmaf_framedata*);<br>
+<br>
+.. Note::<br>
+<br>
+    When setting ENABLE_LIBVMAF cmake option to ON, it is recommended to<br>
+    also set ENABLE_SHARED to OFF to prevent build problems.<br>
+    We only need the static library from these builds.<br>
+<br>
+    Binaries build with windows will not have VMAF support.<br>
+<br>
 Multi-library Interface<br>
 =======================<br>
<br>
</div></div>diff -r 04a337abd70d -r 27e3b161cd8b source/CMakeLists.txt<br>
--- a/source/CMakeLists.txt     Thu Apr 12 15:10:59 2018 +0530<br>
<div><div class="m_-8146764849290315441h5">+++ b/source/CMakeLists.txt     Tue Feb 13 18:54:50 2018 +0530<br>
@@ -29,7 +29,7 @@<br>
 option(STATIC_LINK_CRT "Statically link C runtime for release builds" OFF)<br>
 mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD)<br>
 # X265_BUILD must be incremented each time the public API is changed<br>
-set(X265_BUILD 157)<br>
+set(X265_BUILD 158)<br>
 configure_file("${PROJECT_SOU<wbr>RCE_DIR}/<a href="http://x265.def.in" rel="noreferrer" target="_blank">x265.def.in</a>"<br>
                "${PROJECT_BINARY_DIR}/<a href="http://x265.de">x265.de</a><wbr>f")<br>
 configure_file("${PROJECT_SOU<wbr>RCE_DIR}/<a href="http://x265_config.h.in" rel="noreferrer" target="_blank">x265_config.h.in</a>"<br>
@@ -109,6 +109,11 @@<br>
     if(NO_ATOMICS)<br>
         add_definitions(-DNO_ATOMICS=<wbr>1)<br>
     endif(NO_ATOMICS)<br>
+    find_library(VMAF vmaf)<br>
+    option(ENABLE_LIBVMAF "Enable VMAF" OFF)<br>
+    if(ENABLE_LIBVMAF)<br>
+        add_definitions(-DENABLE_LIBVM<wbr>AF)<br>
+    endif()<br>
 endif(UNIX)<br>
<br>
 if(X64 AND NOT WIN32)<br>
@@ -536,6 +541,9 @@<br>
 if(EXTRA_LIB)<br>
     target_link_libraries(x265-st<wbr>atic ${EXTRA_LIB})<br>
 endif()<br>
+if(ENABLE_LIBVMAF)<br>
+    target_link_libraries(x265-sta<wbr>tic ${VMAF})<br>
+endif()<br>
 install(TARGETS x265-static<br>
     LIBRARY DESTINATION ${LIB_INSTALL_DIR}<br>
     ARCHIVE DESTINATION ${LIB_INSTALL_DIR})<br>
</div></div>diff -r 04a337abd70d -r 27e3b161cd8b source/common/picyuv.h<br>
--- a/source/common/picyuv.h    Thu Apr 12 15:10:59 2018 +0530<br>
<span>+++ b/source/common/picyuv.h    Tue Feb 13 18:54:50 2018 +0530<br>
@@ -72,6 +72,7 @@<br>
     pixel   m_maxChromaVLevel;<br>
     pixel   m_minChromaVLevel;<br>
     double  m_avgChromaVLevel;<br>
+    double  m_vmafScore;<br>
     x265_param *m_param;<br>
<br>
     PicYuv();<br>
</span>diff -r 04a337abd70d -r 27e3b161cd8b source/encoder/api.cpp<br>
--- a/source/encoder/api.cpp    Thu Apr 12 15:10:59 2018 +0530<br>
<div><div class="m_-8146764849290315441h5">+++ b/source/encoder/api.cpp    Tue Feb 13 18:54:50 2018 +0530<br>
@@ -31,6 +31,10 @@<br>
 #include "nal.h"<br>
 #include "bitcost.h"<br>
<br>
+#if ENABLE_LIBVMAF<br>
+#include "libvmaf.h"<br>
+#endif<br>
+<br>
 /* multilib namespace reflectors */<br>
 #if LINKED_8BIT<br>
 namespace x265_8bit {<br>
@@ -302,13 +306,34 @@<br>
         encoder->fetchStats(outputSta<wbr>ts, statsSizeBytes);<br>
     }<br>
 }<br>
+#if ENABLE_LIBVMAF<br>
+void x265_vmaf_encoder_log(x265_enc<wbr>oder* enc, int argc, char **argv, x265_param *param, x265_vmaf_data *vmafdata)<br>
+{<br>
+    if (enc)<br>
+    {<br>
+        Encoder *encoder = static_cast<Encoder*>(enc);<br>
+        x265_stats stats;<br>
+        stats.aggregateVmafScore = x265_calculate_vmafscore(param<wbr>, vmafdata);<br>
+        if(vmafdata->reference_file)<br>
+            fclose(vmafdata->reference_fil<wbr>e);<br>
+        if(vmafdata->distorted_file)<br>
+            fclose(vmafdata->distorted_fil<wbr>e);<br>
+        if(vmafdata)<br>
+            x265_free(vmafdata);<br>
+        encoder->fetchStats(&stats, sizeof(stats));<br>
+        int padx = encoder->m_sps.conformanceWind<wbr>ow.rightOffset;<br>
+        int pady = encoder->m_sps.conformanceWind<wbr>ow.bottomOffset;<br>
+        x265_csvlog_encode(encoder->m_<wbr>param, &stats, padx, pady, argc, argv);<br>
+    }<br>
+}<br>
+#endif<br>
<br>
 void x265_encoder_log(x265_encoder* enc, int argc, char **argv)<br>
 {<br>
     if (enc)<br>
     {<br>
         Encoder *encoder = static_cast<Encoder*>(enc);<br>
-        x265_stats stats;<br>
+        x265_stats stats;<br>
         encoder->fetchStats(&stats, sizeof(stats));<br>
         int padx = encoder->m_sps.conformanceWind<wbr>ow.rightOffset;<br>
         int pady = encoder->m_sps.conformanceWind<wbr>ow.bottomOffset;<br>
@@ -457,7 +482,13 @@<br>
     &x265_csvlog_frame,<br>
     &x265_csvlog_encode,<br>
     &x265_dither_image,<br>
-    &x265_set_analysis_data<br>
+    &x265_set_analysis_data,<br>
+#if ENABLE_LIBVMAF<br>
+    &x265_calculate_vmafscore,<br>
+    &x265_calculate_vmaf_frameleve<wbr>lscore,<br>
+    &x265_vmaf_encoder_log<br>
+#endif<br>
+<br>
 };<br>
<br>
 typedef const x265_api* (*api_get_func)(int bitDepth);<br>
@@ -751,6 +782,9 @@<br>
                     /* detailed performance statistics */<br>
                     fprintf(csvfp, ", DecideWait (ms), Row0Wait (ms), Wall time (ms), Ref Wait Wall (ms), Total CTU time (ms),"<br>
                         "Stall Time (ms), Total frame time (ms), Avg WPP, Row Blocks");<br>
+#if ENABLE_LIBVMAF<br>
+                    fprintf(csvfp, ", VMAF Frame Score");<br>
+#endif<br>
                 }<br>
                 fprintf(csvfp, "\n");<br>
             }<br>
@@ -759,6 +793,9 @@<br>
                 fputs(summaryCSVHeader, csvfp);<br>
                 if (param->csvLogLevel >= 2 || param->maxCLL || param->maxFALL)<br>
                     fputs("MaxCLL, MaxFALL,", csvfp);<br>
+#if ENABLE_LIBVMAF<br>
+                fputs(" Aggregate VMAF Score,", csvfp);<br>
+#endif<br>
                 fputs(" Version\n", csvfp);<br>
             }<br>
         }<br>
@@ -868,6 +905,9 @@<br>
                                                                                      frameStats->totalFrameTime);<br>
<br>
         fprintf(param->csvfpt, " %.3lf, %d", frameStats->avgWPP, frameStats->countRowBlocks);<br>
+#if ENABLE_LIBVMAF<br>
+        fprintf(param->csvfpt, ", %lf", frameStats->vmafFrameScore);<br>
+#endif<br>
     }<br>
     fprintf(param->csvfpt, "\n");<br>
     fflush(stderr);<br>
@@ -886,7 +926,11 @@<br>
             fputs(summaryCSVHeader, p->csvfpt);<br>
             if (p->csvLogLevel >= 2 || p->maxCLL || p->maxFALL)<br>
                 fputs("MaxCLL, MaxFALL,", p->csvfpt);<br>
+#if ENABLE_LIBVMAF<br>
+            fputs(" Aggregate VMAF score,", p->csvfpt);<br>
+#endif<br>
             fputs(" Version\n",p->csvfpt);<br>
+<br>
         }<br>
         // CLI arguments or other<br>
         if (argc)<br>
@@ -919,7 +963,6 @@<br>
         char buffer[200];<br>
         strftime(buffer, 128, "%c", timeinfo);<br>
         fprintf(p->csvfpt, ", %s, ", buffer);<br>
-<br>
         // elapsed time, fps, bitrate<br>
         fprintf(p->csvfpt, "%.2f, %.2f, %.2f,",<br>
             stats->elapsedEncodeTime, stats->encodedPictureCount / stats->elapsedEncodeTime, stats->bitrate);<br>
@@ -981,7 +1024,11 @@<br>
             fprintf(p->csvfpt, " -, -, -, -, -, -, -,");<br>
         if (p->csvLogLevel >= 2 || p->maxCLL || p->maxFALL)<br>
             fprintf(p->csvfpt, " %-6u, %-6u,", stats->maxCLL, stats->maxFALL);<br>
+#if ENABLE_LIBVMAF<br>
+        fprintf(p->csvfpt, " %lf,", stats->aggregateVmafScore);<br>
+#endif<br>
         fprintf(p->csvfpt, " %s\n", api->version_str);<br>
+<br>
     }<br>
 }<br>
<br>
@@ -1072,4 +1119,318 @@<br>
     }<br>
 }<br>
<br>
+#if ENABLE_LIBVMAF<br>
+/* Read y values of single frame for 8-bit input */<br>
+int read_image_byte(FILE *file, float *buf, int width, int height, int stride)<br>
+{<br>
+    char *byte_ptr = (char *)buf;<br>
+    unsigned char *tmp_buf = 0;<br>
+    int i, j;<br>
+    int ret = 1;<br>
+<br>
+    if (width <= 0 || height <= 0)<br>
+    {<br>
+        goto fail_or_end;<br>
+    }<br>
+<br>
+    if (!(tmp_buf = (unsigned char*)malloc(width)))<br>
+    {<br>
+        goto fail_or_end;<br>
+    }<br>
+<br>
+    for (i = 0; i < height; ++i)<br>
+    {<br>
+        float *row_ptr = (float *)byte_ptr;<br>
+<br>
+        if (fread(tmp_buf, 1, width, file) != (size_t)width)<br>
+        {<br>
+            goto fail_or_end;<br>
+        }<br>
+<br>
+        for (j = 0; j < width; ++j)<br>
+        {<br>
+            row_ptr[j] = tmp_buf[j];<br>
+        }<br>
+<br>
+        byte_ptr += stride;<br>
+    }<br>
+<br>
+    ret = 0;<br>
+<br>
+fail_or_end:<br>
+    free(tmp_buf);<br>
+    return ret;<br>
+}<br>
+/* Read y values of single frame for 10-bit input */<br>
+int read_image_word(FILE *file, float *buf, int width, int height, int stride)<br>
+{<br>
+    char *byte_ptr = (char *)buf;<br>
+    unsigned short *tmp_buf = 0;<br>
+    int i, j;<br>
+    int ret = 1;<br>
+<br>
+    if (width <= 0 || height <= 0)<br>
+    {<br>
+        goto fail_or_end;<br>
+    }<br>
+<br>
+    if (!(tmp_buf = (unsigned short*)malloc(width * 2))) // '*2' to accommodate words<br>
+    {<br>
+        goto fail_or_end;<br>
+    }<br>
+<br>
+    for (i = 0; i < height; ++i)<br>
+    {<br>
+        float *row_ptr = (float *)byte_ptr;<br>
+<br>
+        if (fread(tmp_buf, 2, width, file) != (size_t)width) // '2' for word<br>
+        {<br>
+            goto fail_or_end;<br>
+        }<br>
+<br>
+        for (j = 0; j < width; ++j)<br>
+        {<br>
+            row_ptr[j] = tmp_buf[j] / 4.0; // '/4' to convert from 10 to 8-bit<br>
+        }<br>
+<br>
+        byte_ptr += stride;<br>
+    }<br>
+<br>
+    ret = 0;<br>
+<br>
+fail_or_end:<br>
+    free(tmp_buf);<br>
+    return ret;<br>
+}<br>
+<br>
+int read_frame(float *reference_data, float *distorted_data, float *temp_data, int stride_byte, void *s)<br>
+{<br>
+    x265_vmaf_data *user_data = (x265_vmaf_data *)s;<br>
+    int ret;<br>
+<br>
+    // read reference y<br>
+    if (user_data->internalBitDepth == 8)<br>
+    {<br>
+        ret = read_image_byte(user_data->ref<wbr>erence_file, reference_data, user_data->width, user_data->height, stride_byte);<br>
+    }<br>
+    else if (user_data->internalBitDepth == 10)<br>
+    {<br>
+        ret = read_image_word(user_data->ref<wbr>erence_file, reference_data, user_data->width, user_data->height, stride_byte);<br>
+    }<br>
+    else<br>
+    {<br>
+        x265_log(NULL, X265_LOG_ERROR, "Invalid bitdepth\n");<br>
+        return 1;<br>
+    }<br>
+    if (ret)<br>
+    {<br>
+        if (feof(user_data->reference_fil<wbr>e))<br>
+        {<br>
+            ret = 2; // OK if end of file<br>
+        }<br>
+        return ret;<br>
+    }<br>
+<br>
+    // read distorted y<br>
+    if (user_data->internalBitDepth == 8)<br>
+    {<br>
+        ret = read_image_byte(user_data->dis<wbr>torted_file, distorted_data, user_data->width, user_data->height, stride_byte);<br>
+    }<br>
+    else if (user_data->internalBitDepth == 10)<br>
+    {<br>
+        ret = read_image_word(user_data->dis<wbr>torted_file, distorted_data, user_data->width, user_data->height, stride_byte);<br>
+    }<br>
+    else<br>
+    {<br>
+        x265_log(NULL, X265_LOG_ERROR, "Invalid bitdepth\n");<br>
+        return 1;<br>
+    }<br>
+    if (ret)<br>
+    {<br>
+        if (feof(user_data->distorted_fil<wbr>e))<br>
+        {<br>
+            ret = 2; // OK if end of file<br>
+        }<br>
+        return ret;<br>
+    }<br>
+<br>
+    // reference skip u and v<br>
+    if (user_data->internalBitDepth == 8)<br>
+    {<br>
+        if (fread(temp_data, 1, user_data->offset, user_data->reference_file) != (size_t)user_data->offset)<br>
+        {<br>
+            x265_log(NULL, X265_LOG_ERROR, "reference fread to skip u and v failed.\n");<br>
+            goto fail_or_end;<br>
+        }<br>
+    }<br>
+    else if (user_data->internalBitDepth == 10)<br>
+    {<br>
+        if (fread(temp_data, 2, user_data->offset, user_data->reference_file) != (size_t)user_data->offset)<br>
+        {<br>
+            x265_log(NULL, X265_LOG_ERROR, "reference fread to skip u and v failed.\n");<br>
+            goto fail_or_end;<br>
+        }<br>
+    }<br>
+    else<br>
+    {<br>
+        x265_log(NULL, X265_LOG_ERROR, "Invalid format\n");<br>
+        goto fail_or_end;<br>
+    }<br>
+<br>
+    // distorted skip u and v<br>
+    if (user_data->internalBitDepth == 8)<br>
+    {<br>
+        if (fread(temp_data, 1, user_data->offset, user_data->distorted_file) != (size_t)user_data->offset)<br>
+        {<br>
+            x265_log(NULL, X265_LOG_ERROR, "distorted fread to skip u and v failed.\n");<br>
+            goto fail_or_end;<br>
+        }<br>
+    }<br>
+    else if (user_data->internalBitDepth == 10)<br>
+    {<br>
+        if (fread(temp_data, 2, user_data->offset, user_data->distorted_file) != (size_t)user_data->offset)<br>
+        {<br>
+            x265_log(NULL, X265_LOG_ERROR, "distorted fread to skip u and v failed.\n");<br>
+            goto fail_or_end;<br>
+        }<br>
+    }<br>
+    else<br>
+    {<br>
+        x265_log(NULL, X265_LOG_ERROR, "Invalid format\n");<br>
+        goto fail_or_end;<br>
+    }<br>
+<br>
+<br>
+fail_or_end:<br>
+    return ret;<br>
+}<br>
+<br>
+double x265_calculate_vmafscore(x265_<wbr>param *param, x265_vmaf_data *data)<br>
+{<br>
+    double score;<br>
+<br>
+    data->width = param->sourceWidth;<br>
+    data->height = param->sourceHeight;<br>
+    data->internalBitDepth = param->internalBitDepth;<br>
+<br>
+    if (param->internalCsp == X265_CSP_I420)<br>
+    {<br>
+        if ((param->sourceWidth * param->sourceHeight) % 2 != 0)<br>
+            x265_log(NULL, X265_LOG_ERROR, "Invalid file size\n");<br>
+        data->offset = param->sourceWidth * param->sourceHeight / 2;<br>
+    }<br>
+    else if (param->internalCsp == X265_CSP_I422)<br>
+        data->offset = param->sourceWidth * param->sourceHeight;<br>
+    else if (param->internalCsp == X265_CSP_I444)<br>
+        data->offset = param->sourceWidth * param->sourceHeight * 2;<br>
+    else<br>
+        x265_log(NULL, X265_LOG_ERROR, "Invalid format\n");<br>
+<br>
+    compute_vmaf(&score, vcd->format, data->width, data->height, read_frame, data, vcd->model_path, vcd->log_path, vcd->log_fmt, vcd->disable_clip, vcd->disable_avx, vcd->enable_transform, vcd->phone_model, vcd->psnr, vcd->ssim, vcd->ms_ssim, vcd->pool);<br>
+<br>
+    return score;<br>
+}<br>
+<br>
+int read_frame_10bit(float *reference_data, float *distorted_data, float *temp_data, int stride, void *s)<br>
+{<br>
+    x265_vmaf_framedata *user_data = (x265_vmaf_framedata *)s;<br>
+<br>
+    PicYuv *reference_frame = (PicYuv *)user_data->reference_frame;<br>
+    PicYuv *distorted_frame = (PicYuv *)user_data->distorted_frame;<br>
+<br>
+    if(!user_data->frame_set) {<br>
+<br>
+        int reference_stride = reference_frame->m_stride;<br>
+        int distorted_stride = distorted_frame->m_stride;<br>
+<br>
+        const uint16_t *reference_ptr = (const uint16_t *)reference_frame->m_picOrg[0]<wbr>;<br>
+        const uint16_t *distorted_ptr = (const uint16_t *)distorted_frame->m_picOrg[0]<wbr>;<br>
+<br>
+        temp_data = reference_data;<br>
+<br>
+        int height = user_data->height;<br>
+        int width = user_data->width;<br>
+<br>
+        int i,j;<br>
+        for (i = 0; i < height; i++) {<br>
+            for ( j = 0; j < width; j++) {<br>
+                temp_data[j] = ((float)reference_ptr[j] / 4.0);<br>
+            }<br>
+            reference_ptr += reference_stride;<br>
+            temp_data += stride / sizeof(*temp_data);<br>
+        }<br>
+<br>
+        temp_data = distorted_data;<br>
+        for (i = 0; i < height; i++) {<br>
+            for (j = 0; j < width; j++) {<br>
+                 temp_data[j] = ((float)distorted_ptr[j] / 4.0);<br>
+            }<br>
+            distorted_ptr += distorted_stride;<br>
+            temp_data += stride / sizeof(*temp_data);<br>
+        }<br>
+<br>
+        user_data->frame_set = 1;<br>
+        return 0;<br>
+    }<br>
+    return 2;<br>
+}<br>
+<br>
+int read_frame_8bit(float *reference_data, float *distorted_data, float *temp_data, int stride, void *s)<br>
+{<br>
+    x265_vmaf_framedata *user_data = (x265_vmaf_framedata *)s;<br>
+<br>
+    PicYuv *reference_frame = (PicYuv *)user_data->reference_frame;<br>
+    PicYuv *distorted_frame = (PicYuv *)user_data->distorted_frame;<br>
+<br>
+    if(!user_data->frame_set) {<br>
+<br>
+        int reference_stride = reference_frame->m_stride;<br>
+        int distorted_stride = distorted_frame->m_stride;<br>
+<br>
+        const uint8_t *reference_ptr = (const uint8_t *)reference_frame->m_picOrg[0]<wbr>;<br>
+        const uint8_t *distorted_ptr = (const uint8_t *)distorted_frame->m_picOrg[0]<wbr>;<br>
+<br>
+        temp_data = reference_data;<br>
+<br>
+        int height = user_data->height;<br>
+        int width = user_data->width;<br>
+<br>
+        int i,j;<br>
+        for (i = 0; i < height; i++) {<br>
+            for ( j = 0; j < width; j++) {<br>
+                temp_data[j] = (float)reference_ptr[j];<br>
+            }<br>
+            reference_ptr += reference_stride;<br>
+            temp_data += stride / sizeof(*temp_data);<br>
+        }<br>
+<br>
+        temp_data = distorted_data;<br>
+        for (i = 0; i < height; i++) {<br>
+            for (j = 0; j < width; j++) {<br>
+                 temp_data[j] = (float)distorted_ptr[j];<br>
+            }<br>
+            distorted_ptr += distorted_stride;<br>
+            temp_data += stride / sizeof(*temp_data);<br>
+        }<br>
+<br>
+        user_data->frame_set = 1;<br>
+        return 0;<br>
+    }<br>
+    return 2;<br>
+}<br>
+<br>
+double x265_calculate_vmaf_framelevel<wbr>score(x265_vmaf_framedata *vmafframedata)<br>
+{<br>
+    double score;<br>
+    int (*read_frame)(float *reference_data, float *distorted_data, float *temp_data,<br>
+                      int stride, void *s);<br>
+    if (vmafframedata->internalBitDep<wbr>th == 8)<br>
+        read_frame = read_frame_8bit;<br>
+    else<br>
+        read_frame = read_frame_10bit;<br>
+    compute_vmaf(&score, vcd->format, vmafframedata->width, vmafframedata->height, read_frame, vmafframedata, vcd->model_path, vcd->log_path, vcd->log_fmt, vcd->disable_clip, vcd->disable_avx, vcd->enable_transform, vcd->phone_model, vcd->psnr, vcd->ssim, vcd->ms_ssim, vcd->pool);<br>
+<br>
+    return score;<br>
+}<br>
+#endif<br>
 } /* end namespace or extern "C" */<br>
</div></div>diff -r 04a337abd70d -r 27e3b161cd8b source/encoder/encoder.cpp<br>
--- a/source/encoder/encoder.cpp        Thu Apr 12 15:10:59 2018 +0530<br>
<span>+++ b/source/encoder/encoder.cpp        Tue Feb 13 18:54:50 2018 +0530<br>
@@ -2127,6 +2127,9 @@<br>
 #define ELAPSED_MSEC(start, end) (((double)(end) - (start)) / 1000)<br>
         if (m_param->csvLogLevel >= 2)<br>
         {<br>
+#if ENABLE_LIBVMAF<br>
+            frameStats->vmafFrameScore = curFrame->m_fencPic->m_vmafSco<wbr>re;<br>
+#endif<br>
             frameStats->decideWaitTime = ELAPSED_MSEC(0, curEncoder->m_slicetypeWaitTim<wbr>e);<br>
             frameStats->row0WaitTime = ELAPSED_MSEC(curEncoder->m_sta<wbr>rtCompressTime, curEncoder->m_row0WaitTime);<br>
             frameStats->wallTime = ELAPSED_MSEC(curEncoder->m_row<wbr>0WaitTime, curEncoder->m_endCompressTime)<wbr>;<br>
</span>diff -r 04a337abd70d -r 27e3b161cd8b source/encoder/frameencoder.cp<wbr>p<br>
--- a/source/encoder/frameencoder.<wbr>cpp   Thu Apr 12 15:10:59 2018 +0530<br>
<span>+++ b/source/encoder/frameencoder.<wbr>cpp   Tue Feb 13 18:54:50 2018 +0530<br>
</span>@@ -864,6 +864,9 @@<br>
<span>                 m_frameFilter.processRow(i - m_filterRowDelay);<br>
         }<br>
     }<br>
+#if ENABLE_LIBVMAF<br>
</span>+    vmafFrameLevelScore();<br>
<span>+#endif<br>
<br>
     if (m_param->maxSlices > 1)<br>
     {<br>
</span>@@ -932,7 +935,7 @@<br>
<span>                 updateChecksum(reconPic->m_pi<wbr>cOrg[1], m_checksum[1], height, width, stride, 0, cuHeight);<br>
                 updateChecksum(reconPic->m_pi<wbr>cOrg[2], m_checksum[2], height, width, stride, 0, cuHeight);<br>
             }<br>
-        }<br>
+        }<br>
     } // end of (m_param->maxSlices > 1)<br>
<br>
     if (m_param->rc.bStatWrite)<br>
</span>@@ -1189,7 +1192,7 @@<br>
<span>         m_cuStats.accumulate(m_tld[i]<wbr>.analysis.m_stats[m_jpId], *m_param);<br>
 #endif<br>
<br>
-    m_endFrameTime = x265_mdate();<br>
+    m_endFrameTime = x265_mdate();<br>
 }<br>
<br>
 void FrameEncoder::encodeSlice(uint<wbr>32_t sliceAddr)<br>
</span>@@ -2058,11 +2061,36 @@<br>
         m_nr->nrOffsetDenoise[cat][0] = 0;<br>
     }<br>
 }<br>
+#if ENABLE_LIBVMAF<br>
+void FrameEncoder::vmafFrameLevelSc<wbr>ore()<br>
+{<br>
<span>+    PicYuv *fenc = m_frame->m_fencPic;<br>
+    PicYuv *recon = m_frame->m_reconPic;<br>
+<br>
+    x265_vmaf_framedata *vmafframedata = (x265_vmaf_framedata*)x265_mal<wbr>loc(sizeof(x265_vmaf_framedata<wbr>));<br>
+    if (!vmafframedata)<br>
+    {<br>
+        x265_log(NULL, X265_LOG_ERROR, "vmaf frame data alloc failed\n");<br>
+    }<br>
+<br>
+    vmafframedata->height = fenc->m_picHeight;<br>
+    vmafframedata->width = fenc->m_picWidth;<br>
+    vmafframedata->frame_set = 0;<br>
+    vmafframedata->internalBitDept<wbr>h = m_param->internalBitDepth;<br>
+    vmafframedata->reference_frame = fenc;<br>
+    vmafframedata->distorted_frame = recon;<br>
+<br>
+    fenc->m_vmafScore = x265_calculate_vmaf_framelevel<wbr>score(vmafframedata);<br>
+<br>
+    if (vmafframedata)<br>
+    x265_free(vmafframedata);<br>
+}<br>
+#endif<br>
<br>
</span><span> Frame *FrameEncoder::getEncodedPictu<wbr>re(NALList& output)<br>
 {<br>
     if (m_frame)<br>
-    {<br>
+    {<br>
         /* block here until worker thread completes */<br>
         m_done.wait();<br>
<br>
</span>diff -r 04a337abd70d -r 27e3b161cd8b source/encoder/frameencoder.h<br>
--- a/source/encoder/frameencoder.<wbr>h     Thu Apr 12 15:10:59 2018 +0530<br>
+++ b/source/encoder/frameencoder.<wbr>h     Tue Feb 13 18:54:50 2018 +0530<br>
@@ -240,6 +240,9 @@<br>
     void enqueueRowFilter(int row)  { WaveFront::enqueueRow(row * 2 + 1); }<br>
     void enableRowEncoder(int row)  { WaveFront::enableRow(row * 2 + 0); }<br>
     void enableRowFilter(int row)   { WaveFront::enableRow(row * 2 + 1); }<br>
+#if ENABLE_LIBVMAF<br>
+    void vmafFrameLevelScore();<br>
+#endif<br>
 };<br>
 }<br>
<br>
diff -r 04a337abd70d -r 27e3b161cd8b source/x265.cpp<br>
--- a/source/x265.cpp   Thu Apr 12 15:10:59 2018 +0530<br>
<div><div class="m_-8146764849290315441h5">+++ b/source/x265.cpp   Tue Feb 13 18:54:50 2018 +0530<br>
@@ -75,6 +75,7 @@<br>
     const char* reconPlayCmd;<br>
     const x265_api* api;<br>
     x265_param* param;<br>
+    x265_vmaf_data* vmafData;<br>
     bool bProgress;<br>
     bool bForceY4m;<br>
     bool bDither;<br>
@@ -96,6 +97,7 @@<br>
         reconPlayCmd = NULL;<br>
         api = NULL;<br>
         param = NULL;<br>
+        vmafData = NULL;<br>
         framesToBeEncoded = seek = 0;<br>
         totalbytes = 0;<br>
         bProgress = true;<br>
@@ -216,6 +218,14 @@<br>
         x265_log(NULL, X265_LOG_ERROR, "param alloc failed\n");<br>
         return true;<br>
     }<br>
+#if ENABLE_LIBVMAF<br>
+    vmafData = (x265_vmaf_data*)x265_malloc(s<wbr>izeof(x265_vmaf_data));<br>
+    if(!vmafData)<br>
+    {<br>
+        x265_log(NULL, X265_LOG_ERROR, "vmaf data alloc failed\n");<br>
+        return true;<br>
+    }<br>
+#endif<br>
<br>
     if (api->param_default_preset(par<wbr>am, preset, tune) < 0)<br>
     {<br>
@@ -363,6 +373,7 @@<br>
     info.frameCount = 0;<br>
     getParamAspectRatio(param, info.sarWidth, info.sarHeight);<br>
<br>
+<br>
     this->input = InputFile::open(info, this->bForceY4m);<br>
     if (!this->input || this->input->isFail())<br>
     {<br>
@@ -439,7 +450,30 @@<br>
                     param->sourceWidth, param->sourceHeight, param->fpsNum, param->fpsDenom,<br>
                     x265_source_csp_names[param-><wbr>internalCsp]);<br>
     }<br>
+#if ENABLE_LIBVMAF<br>
+    if (!reconfn)<br>
+    {<br>
+        x265_log(param, X265_LOG_ERROR, "recon file must be specified to get VMAF score, try --help for help\n");<br>
+        return true;<br>
+    }<br>
+    const char *str = strrchr(info.filename, '.');<br>
<br>
+    if (!strcmp(str, ".y4m"))<br>
+    {<br>
+        x265_log(param, X265_LOG_ERROR, "VMAF supports YUV file format only.\n");<br>
+        return true;<br>
+    }<br>
+    if(param->internalCsp == X265_CSP_I420 || param->internalCsp == X265_CSP_I422 || param->internalCsp == X265_CSP_I444)<br>
+    {<br>
+        vmafData->reference_file = x265_fopen(inputfn, "rb");<br>
+        vmafData->distorted_file = x265_fopen(reconfn, "rb");<br>
+    }<br>
+    else<br>
+    {<br>
+        x265_log(param, X265_LOG_ERROR, "VMAF will support only yuv420p, yu422p, yu444p, yuv420p10le, yuv422p10le, yuv444p10le formats.\n");<br>
+        return true;<br>
+    }<br>
+#endif<br>
     this->output = OutputFile::open(outputfn, info);<br>
     if (this->output->isFail())<br>
     {<br>
@@ -555,7 +589,9 @@<br>
<br>
     x265_param* param = cliopt.param;<br>
     const x265_api* api = cliopt.api;<br>
-<br>
+#if ENABLE_LIBVMAF<br>
+    x265_vmaf_data* vmafdata = cliopt.vmafData;<br>
+#endif<br>
     /* This allows muxers to modify bitstream format */<br>
     cliopt.output->setParam(<wbr>param);<br>
<br>
@@ -712,7 +748,7 @@<br>
         if (!numEncoded)<br>
             break;<br>
     }<br>
-<br>
+<br>
     /* clear progress report */<br>
     if (cliopt.bProgress)<br>
         fprintf(stderr, "%*s\r", 80, " ");<br>
@@ -723,7 +759,11 @@<br>
<br>
     api->encoder_get_stats(encode<wbr>r, &stats, sizeof(stats));<br>
     if (param->csvfn && !b_ctrl_c)<br>
+#if ENABLE_LIBVMAF<br>
+        api->vmaf_encoder_log(encoder, argc, argv, param, vmafdata);<br>
+#else<br>
         api->encoder_log(encoder, argc, argv);<br>
+#endif<br>
     api->encoder_close(encoder);<br>
<br>
     int64_t second_largest_pts = 0;<br>
</div></div>diff -r 04a337abd70d -r 27e3b161cd8b source/x265.h<br>
--- a/source/x265.h     Thu Apr 12 15:10:59 2018 +0530<br>
<div class="m_-8146764849290315441HOEnZb"><div class="m_-8146764849290315441h5">+++ b/source/x265.h     Tue Feb 13 18:54:50 2018 +0530<br>
@@ -209,6 +209,7 @@<br>
     x265_cu_stats    cuStats;<br>
     x265_pu_stats    puStats;<br>
     double           totalFrameTime;<br>
+    double           vmafFrameScore;<br>
 } x265_frame_stats;<br>
<br>
 typedef struct x265_ctu_info_t<br>
@@ -536,6 +537,7 @@<br>
     double                elapsedEncodeTime;    /* wall time since encoder was opened */<br>
     double                elapsedVideoTime;     /* encoded picture count / frame rate */<br>
     double                bitrate;              /* accBits / elapsed video time */<br>
+    double                aggregateVmafScore;   /* aggregate VMAF score for input video*/<br>
     uint64_t              accBits;              /* total bits output thus far */<br>
     uint32_t              encodedPictureCount;  /* number of output pictures thus far */<br>
     uint32_t              totalWPFrames;        /* number of uni-directional weighted frames used */<br>
@@ -572,6 +574,47 @@<br>
     float bitrateFactor;<br>
 } x265_zone;<br>
<br>
+/* data to calculate aggregate VMAF score */<br>
+typedef struct x265_vmaf_data<br>
+{<br>
+    int width;<br>
+    int height;<br>
+    size_t offset;<br>
+    int internalBitDepth;<br>
+    FILE *reference_file; /* FILE pointer for input file */<br>
+    FILE *distorted_file; /* FILE pointer for recon file generated*/<br>
+}x265_vmaf_data;<br>
+<br>
+/* data to calculate frame level VMAF score */<br>
+typedef struct x265_vmaf_framedata<br>
+{<br>
+    int width;<br>
+    int height;<br>
+    int frame_set;<br>
+    int internalBitDepth;<br>
+    void *reference_frame; /* points to fenc of particular frame */<br>
+    void *distorted_frame; /* points to recon of particular frame */<br>
+}x265_vmaf_framedata;<br>
+<br>
+/* common data needed to calculate both frame level and video level VMAF scores */<br>
+typedef struct x265_vmaf_commondata<br>
+{<br>
+    char *format;<br>
+    char *model_path;<br>
+    char *log_path;<br>
+    char *log_fmt;<br>
+    int disable_clip;<br>
+    int disable_avx;<br>
+    int enable_transform;<br>
+    int phone_model;<br>
+    int psnr;<br>
+    int ssim;<br>
+    int ms_ssim;<br>
+    char *pool;<br>
+}x265_vmaf_commondata;<br>
+<br>
+static const x265_vmaf_commondata vcd[] = {NULL, (char *)"/usr/local/share/model/vmaf<wbr>_v0.6.1.pkl", NULL, NULL, 0, 0, 0, 0, 0, 0, 0, NULL};<br>
+<br>
 /* x265 input parameters<br>
  *<br>
  * For version safety you may use x265_param_alloc/free() to manage the<br>
@@ -1811,6 +1854,22 @@<br>
 /* In-place downshift from a bit-depth greater than 8 to a bit-depth of 8, using<br>
  * the residual bits to dither each row. */<br>
 void x265_dither_image(x265_picture *, int picWidth, int picHeight, int16_t *errorBuf, int bitDepth);<br>
+#if ENABLE_LIBVMAF<br>
+/* x265_calculate_vmafScore:<br>
+ *    returns VMAF score for the input video.<br>
+ *    This api must be called only after encoding was done. */<br>
+double x265_calculate_vmafscore(x265_<wbr>param*, x265_vmaf_data*);<br>
+<br>
+/* x265_calculate_vmaf_framelevel<wbr>score:<br>
+ *    returns VMAF score for each frame in a given input video. */<br>
+double x265_calculate_vmaf_framelevel<wbr>score(x265_vmaf_framedata*);<br>
+/* x265_vmaf_encoder_log:<br>
+ *       write a line to the configured CSV file.  If a CSV filename was not<br>
+ *       configured, or file open failed, this function will perform no write.<br>
+ *       This api will be called only when ENABLE_LIBVMAF cmake option is set */<br>
+void x265_vmaf_encoder_log(x265_enc<wbr>oder *encoder, int argc, char **argv, x265_param*, x265_vmaf_data*);<br>
+<br>
+#endif<br>
<br>
 #define X265_MAJOR_VERSION 1<br>
<br>
@@ -1864,6 +1923,11 @@<br>
     void          (*csvlog_encode)(const x265_param*, const x265_stats *, int, int, int, char**);<br>
     void          (*dither_image)(x265_picture*, int, int, int16_t*, int);<br>
     int           (*set_analysis_data)(x265_enc<wbr>oder *encoder, x265_analysis_data *analysis_data, int poc, uint32_t cuBytes);<br>
+#if ENABLE_LIBVMAF<br>
+    double        (*calculate_vmafscore)(x265_pa<wbr>ram *, x265_vmaf_data *);<br>
+    double        (*calculate_vmaf_framelevelsco<wbr>re)(x265_vmaf_framedata *);<br>
+    void          (*vmaf_encoder_log)(x265_encod<wbr>er*, int, char**, x265_param *, x265_vmaf_data *);<br>
+#endif<br>
     /* add new pointers to the end, or increment X265_MAJOR_VERSION */<br>
 } x265_api;<br>
<br>
</div></div><br></div></div>______________________________<wbr>_________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org" target="_blank">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" rel="noreferrer" target="_blank">https://mailman.videolan.org/l<wbr>istinfo/x265-devel</a><br>
<br></blockquote></div></div><div class="gmail_extra"><br></div><div class="gmail_extra">Thanks. Pushed to default.</div></div>
<br>______________________________<wbr>_________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" rel="noreferrer" target="_blank">https://mailman.videolan.org/<wbr>listinfo/x265-devel</a><br>
<br></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature">Deepthi</div>
</div>