Permalink
Browse files

Feature/#140 frame sampling (#166)

* Add next_blur_buf and blur_array2, with no memory leak issue.

* Add next_ref_buf, next_dis_buf, blur_array3, blur_array4, no memory leak issue.

* Add motion2 to motion.c.

* Add motion2 to all.c.

* Update VmafFeatureExtractor.

* save point.

* Refactor.

* Add motion2 to combo.c.

* Use motion2 directly from combo in vmaf.cpp.

* Save point: added motion2 to combo for multithreading, but has seg fault.

* Rename blur_array(s).

* Save point; to debug why one thread doesn't terminate.

* Fix not-terminate issue.

* Create interface for n_thread and n_subsample in vmafossexec; update VERSION.

* Enable n_thread in combo.c.

* Enable n_subsample in combo.c; add test cases to VmafossexecQualityRunner.
  • Loading branch information...
li-zhi committed Jun 5, 2018
1 parent 14bcee6 commit 47d0655aff03f40fd5471a24d56c0de852cf3e78
View
@@ -1,5 +1,12 @@
# Change Log
## (6/4/2018) [1.3.6]
**New features:**
- Update libvmaf version to 1.3.6 (to make consistent with VDK version from now on) after compute_vmaf() interface change (added thread and subsample options).
- Add the option to set the number of threads to use in vmafossexec.
- Add the option to subsample frames to save computation in vmafossexec.
## (5/23/2018) [1.3.5]
**New features:**
View
@@ -479,8 +479,8 @@ This copies the library header `libvmaf.h` under `usr/local/include`, library `l
```
int compute_vmaf(double* vmaf_score, char* fmt, int width, int height, int (*read_frame)(float *ref_data, float *main_data, float *temp_data,
int stride, void *user_data), void *user_data, char *model_path, char *log_path, char *log_fmt, int disable_clip,
int disable_avx, int enable_transform, int phone_model, int do_psnr, int do_ssim, int do_ms_ssim, char *pool_method);
int stride, void *user_data), void *user_data, char *model_path, char *log_path, char *log_fmt, int disable_clip, int disable_avx,
int enable_transform, int phone_model, int do_psnr, int do_ssim, int do_ms_ssim, char *pool_method, int thread, int subsample);
```
Here, `read_frame` is a callback function which can be used to pass data from a program to VMAF. `user_data` is a program specific data that can be used by the callback function. For sample usage of `compute_vmaf`, refer to [`wrapper/src/main.cpp`](wrapper/src/main.cpp).
View
@@ -1,2 +1,2 @@
VMAF Development Kit (VDK) Version 1.3.5
VMAF Version 0.6.3
VMAF Development Kit (VDK) Version 1.3.6
VMAF Version 0.6.1
View
@@ -43,9 +43,12 @@ int compute_ansnr(const float *ref, const float *dis, int w, int h, int ref_stri
int compute_vif(const float *ref, const float *dis, int w, int h, int ref_stride, int dis_stride, double *score, double *score_num, double *score_den, double *scores);
int compute_motion(const float *ref, const float *dis, int w, int h, int ref_stride, int dis_stride, double *score);
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
int all(int (*read_frame)(float *ref_data, float *main_data, float *temp_data, int stride, void *user_data), void *user_data, int w, int h, const char *fmt)
{
double score = 0;
double score2 = 0;
double scores[4*2];
double score_num = 0;
double score_den = 0;
@@ -55,13 +58,18 @@ int all(int (*read_frame)(float *ref_data, float *main_data, float *temp_data, i
float *prev_blur_buf = 0;
float *blur_buf = 0;
float *next_ref_buf = 0;
float *next_dis_buf = 0;
float *next_blur_buf = 0;
float *temp_buf = 0;
size_t data_sz;
int stride;
double peak;
double psnr_max;
int ret = 1;
bool next_frame_read;
int global_frm_idx = 0; // map to thread_data->frm_idx in combo.c
if (w <= 0 || h <= 0 || (size_t)w > ALIGN_FLOOR(INT_MAX) / sizeof(float))
{
@@ -98,7 +106,6 @@ int all(int (*read_frame)(float *ref_data, float *main_data, float *temp_data, i
goto fail_or_end;
}
// prev_blur_buf, blur_buf for motion only
if (!(prev_blur_buf = aligned_malloc(data_sz, MAX_ALIGN)))
{
printf("error: aligned_malloc failed for prev_blur_buf.\n");
@@ -111,6 +118,24 @@ int all(int (*read_frame)(float *ref_data, float *main_data, float *temp_data, i
fflush(stdout);
goto fail_or_end;
}
if (!(next_ref_buf = aligned_malloc(data_sz, MAX_ALIGN)))
{
printf("error: aligned_malloc failed for next_ref_buf.\n");
fflush(stdout);
goto fail_or_end;
}
if (!(next_dis_buf = aligned_malloc(data_sz, MAX_ALIGN)))
{
printf("error: aligned_malloc failed for next_dis_buf.\n");
fflush(stdout);
goto fail_or_end;
}
if (!(next_blur_buf = aligned_malloc(data_sz, MAX_ALIGN)))
{
printf("error: aligned_malloc failed for next_blur_buf.\n");
fflush(stdout);
goto fail_or_end;
}
// use temp_buf for convolution_f32_c, and fread u and v
if (!(temp_buf = aligned_malloc(data_sz * 2, MAX_ALIGN)))
@@ -120,25 +145,74 @@ int all(int (*read_frame)(float *ref_data, float *main_data, float *temp_data, i
goto fail_or_end;
}
int frm_idx = 0;
int frm_idx = -1;
while (1)
{
ret = read_frame(ref_buf, dis_buf, temp_buf, stride, user_data);
// the next frame
frm_idx = global_frm_idx;
global_frm_idx++;
if (frm_idx == 0)
{
ret = read_frame(ref_buf, dis_buf, temp_buf, stride, user_data);
if (ret == 1)
{
goto fail_or_end;
}
if (ret == 2)
{
break;
}
// ===============================================================
// offset pixel by OPT_RANGE_PIXEL_OFFSET
// ===============================================================
offset_image(ref_buf, OPT_RANGE_PIXEL_OFFSET, w, h, stride);
offset_image(dis_buf, OPT_RANGE_PIXEL_OFFSET, w, h, stride);
// ===============================================================
// filter
// apply filtering (to eliminate effects film grain)
// stride input to convolution_f32_c is in terms of (sizeof(float) bytes)
// since stride = ALIGN_CEIL(w * sizeof(float)), stride divides sizeof(float)
// ===============================================================
convolution_f32_c(FILTER_5, 5, ref_buf, blur_buf, temp_buf, w, h, stride / sizeof(float), stride / sizeof(float));
}
ret = read_frame(next_ref_buf, next_dis_buf, temp_buf, stride, user_data);
if (ret == 1)
{
goto fail_or_end;
}
if (ret == 2)
{
break;
next_frame_read = false;
}
else
{
next_frame_read = true;
}
// ===============================================================
// offset pixel by OPT_RANGE_PIXEL_OFFSET
// ===============================================================
offset_image(ref_buf, OPT_RANGE_PIXEL_OFFSET, w, h, stride);
offset_image(dis_buf, OPT_RANGE_PIXEL_OFFSET, w, h, stride);
if (next_frame_read)
{
offset_image(next_ref_buf, OPT_RANGE_PIXEL_OFFSET, w, h, stride);
offset_image(next_dis_buf, OPT_RANGE_PIXEL_OFFSET, w, h, stride);
}
// ===============================================================
// filter
// apply filtering (to eliminate effects film grain)
// stride input to convolution_f32_c is in terms of (sizeof(float) bytes)
// since stride = ALIGN_CEIL(w * sizeof(float)), stride divides sizeof(float)
// ===============================================================
if (next_frame_read)
{
convolution_f32_c(FILTER_5, 5, next_ref_buf, next_blur_buf, temp_buf, w, h, stride / sizeof(float), stride / sizeof(float));
}
/* =========== adm ============== */
if ((ret = compute_adm(ref_buf, dis_buf, w, h, stride, stride, &score, &score_num, &score_den, scores, ADM_BORDER_FACTOR)))
@@ -172,36 +246,43 @@ int all(int (*read_frame)(float *ref_data, float *main_data, float *temp_data, i
/* =========== motion ============== */
// filter
// apply filtering (to eliminate effects film grain)
// stride input to convolution_f32_c is in terms of (sizeof(float) bytes)
// since stride = ALIGN_CEIL(w * sizeof(float)), stride divides sizeof(float)
convolution_f32_c(FILTER_5, 5, ref_buf, blur_buf, temp_buf, w, h, stride / sizeof(float), stride / sizeof(float));
// compute
if (frm_idx == 0)
{
score = 0.0;
score2 = 0.0;
}
else
{
if ((ret = compute_motion(prev_blur_buf, blur_buf, w, h, stride, stride, &score)))
{
printf("error: compute_motion failed.\n");
printf("error: compute_motion (prev) failed.\n");
fflush(stdout);
goto fail_or_end;
}
}
// copy to prev_buf
memcpy(prev_blur_buf, blur_buf, data_sz);
if (next_frame_read)
{
if ((ret = compute_motion(blur_buf, next_blur_buf, w, h, stride, stride, &score2)))
{
printf("error: compute_motion (next) failed.\n");
fflush(stdout);
goto fail_or_end;
}
score2 = MIN(score, score2);
}
else
{
score2 = score;
}
}
// print
printf("motion: %d %f\n", frm_idx, score);
printf("motion2: %d %f\n", frm_idx, score2);
fflush(stdout);
/* =========== vif ============== */
// compute vif last, because its input ref/dis might be offset by -128
if ((ret = compute_vif(ref_buf, dis_buf, w, h, stride, stride, &score, &score_num, &score_den, scores)))
{
@@ -218,7 +299,17 @@ int all(int (*read_frame)(float *ref_data, float *main_data, float *temp_data, i
}
fflush(stdout);
frm_idx++;
// copy to prev_buf
memcpy(prev_blur_buf, blur_buf, data_sz);
memcpy(ref_buf, next_ref_buf, data_sz);
memcpy(dis_buf, next_dis_buf, data_sz);
memcpy(blur_buf, next_blur_buf, data_sz);
if (!next_frame_read)
{
break;
}
}
ret = 0;
@@ -229,6 +320,10 @@ int all(int (*read_frame)(float *ref_data, float *main_data, float *temp_data, i
aligned_free(dis_buf);
aligned_free(prev_blur_buf);
aligned_free(next_ref_buf);
aligned_free(next_dis_buf);
aligned_free(next_blur_buf);
aligned_free(blur_buf);
aligned_free(temp_buf);
Oops, something went wrong.

4 comments on commit 47d0655

@LigH-de

This comment has been minimized.

Show comment
Hide comment
@LigH-de

LigH-de Jun 5, 2018

Changing the API of compute_vmaf breaks compatibility with ffmpeg, they have to catch up this regression.

LigH-de replied Jun 5, 2018

Changing the API of compute_vmaf breaks compatibility with ffmpeg, they have to catch up this regression.

@li-zhi

This comment has been minimized.

Show comment
Hide comment
@li-zhi

li-zhi Jun 5, 2018

Contributor

@LigH-de I have updated the libvmaf version number here:
https://github.com/Netflix/vmaf/blob/master/wrapper/libvmaf.pc

Is there anything else I need to do?

Contributor

li-zhi replied Jun 5, 2018

@LigH-de I have updated the libvmaf version number here:
https://github.com/Netflix/vmaf/blob/master/wrapper/libvmaf.pc

Is there anything else I need to do?

@LigH-de

This comment has been minimized.

Show comment
Hide comment
@LigH-de

LigH-de Jun 5, 2018

I notified ffmpeg in their trac as well (ticket 7248).

LigH-de replied Jun 5, 2018

I notified ffmpeg in their trac as well (ticket 7248).

@li-zhi

This comment has been minimized.

Show comment
Hide comment
@li-zhi

li-zhi Jun 5, 2018

Contributor

Thanks!

Contributor

li-zhi replied Jun 5, 2018

Thanks!

Please sign in to comment.