1 /**
2 *
3 * Copyright 2016-2020 Netflix, Inc.
4 *
5 * Licensed under the BSD+Patent License (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * https://opensource.org/licenses/BSDplusPatent
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include <errno.h>
20 #include <stdint.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include "mem.h"
25 #include "picture.h"
26 #include "ref.h"
27
28 #define DATA_ALIGN 32
29
vmaf_picture_alloc(VmafPicture * pic,enum VmafPixelFormat pix_fmt,unsigned bpc,unsigned w,unsigned h)30 int vmaf_picture_alloc(VmafPicture *pic, enum VmafPixelFormat pix_fmt,
31 unsigned bpc, unsigned w, unsigned h)
32 {
33 if (!pic) return -EINVAL;
34 if (!pix_fmt) return -EINVAL;
35 if (bpc < 8 || bpc > 16) return -EINVAL;
36
37 memset(pic, 0, sizeof(*pic));
38 pic->pix_fmt = pix_fmt;
39 pic->bpc = bpc;
40 const int ss_hor = pic->pix_fmt != VMAF_PIX_FMT_YUV444P;
41 const int ss_ver = pic->pix_fmt == VMAF_PIX_FMT_YUV420P;
42 pic->w[0] = w;
43 pic->w[1] = pic->w[2] = w >> ss_hor;
44 pic->h[0] = h;
45 pic->h[1] = pic->h[2] = h >> ss_ver;
46 if (pic->pix_fmt == VMAF_PIX_FMT_YUV400P)
47 pic->w[1] = pic->w[2] = pic->h[1] = pic->h[2] = 0;
48
49 const int aligned_y = (pic->w[0] + DATA_ALIGN - 1) & ~(DATA_ALIGN - 1);
50 const int aligned_c = (pic->w[1] + DATA_ALIGN - 1) & ~(DATA_ALIGN - 1);
51 const int hbd = pic->bpc > 8;
52 pic->stride[0] = aligned_y << hbd;
53 pic->stride[1] = pic->stride[2] = aligned_c << hbd;
54 const size_t y_sz = pic->stride[0] * pic->h[0];
55 const size_t uv_sz = pic->stride[1] * pic->h[1];
56 const size_t pic_size = y_sz + 2 * uv_sz;
57
58 uint8_t *data = aligned_malloc(pic_size, DATA_ALIGN);
59 if (!data) goto fail;
60 memset(data, 0, pic_size);
61 pic->data[0] = data;
62 pic->data[1] = data + y_sz;
63 pic->data[2] = data + y_sz + uv_sz;
64 if (pic->pix_fmt == VMAF_PIX_FMT_YUV400P)
65 pic->data[1] = pic->data[2] = NULL;
66
67 int err = vmaf_ref_init(&pic->ref);
68 if (err) goto free_data;
69
70 return 0;
71
72 free_data:
73 aligned_free(data);
74 fail:
75 return -ENOMEM;
76 }
77
vmaf_picture_ref(VmafPicture * dst,VmafPicture * src)78 int vmaf_picture_ref(VmafPicture *dst, VmafPicture *src) {
79 if (!dst || !src) return -EINVAL;
80
81 memcpy(dst, src, sizeof(*src));
82 vmaf_ref_fetch_increment(src->ref);
83 return 0;
84 }
85
vmaf_picture_unref(VmafPicture * pic)86 int vmaf_picture_unref(VmafPicture *pic) {
87 if (!pic) return -EINVAL;
88 if (!pic->ref) return -EINVAL;
89
90 vmaf_ref_fetch_decrement(pic->ref);
91 if (vmaf_ref_load(pic->ref) == 0) {
92 aligned_free(pic->data[0]);
93 vmaf_ref_close(pic->ref);
94 }
95 memset(pic, 0, sizeof(*pic));
96 return 0;
97 }
98