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