static int fetch_picture()

in libvmaf/tools/vmaf.c [71:167]


static int fetch_picture(video_input *vid, VmafPicture *pic, int depth)
{
    int ret;
    video_input_ycbcr ycbcr;
    video_input_info info;

    ret = video_input_fetch_frame(vid, ycbcr, NULL);
    if (ret < 1) return !ret;

    video_input_get_info(vid, &info);
    ret = vmaf_picture_alloc(pic, pix_fmt_map(info.pixel_fmt), depth,
                             info.pic_w, info.pic_h);

    if (ret) {
        fprintf(stderr, "problem allocating picture.\n");
        return -1;
    }

    if (info.depth == depth) {
        if (info.depth == 8) {
            for (unsigned i = 0; i < 3; i++) {
                int xdec = i&&!(info.pixel_fmt&1);
                int ydec = i&&!(info.pixel_fmt&2);
                uint8_t *ycbcr_data = ycbcr[i].data +
                    (info.pic_y >> ydec) * ycbcr[i].stride +
                    (info.pic_x >> xdec);
                uint8_t *pic_data = pic->data[i];

                for (unsigned j = 0; j < pic->h[i]; j++) {
                    memcpy(pic_data, ycbcr_data, sizeof(*pic_data) * pic->w[i]);
                    pic_data += pic->stride[i];
                    ycbcr_data += ycbcr[i].stride;
                }
            }
        } else {
            for (unsigned i = 0; i < 3; i++) {
                int xdec = i&&!(info.pixel_fmt&1);
                int ydec = i&&!(info.pixel_fmt&2);
                uint16_t *ycbcr_data = (uint16_t*) ycbcr[i].data +
                    (info.pic_y >> ydec) * (ycbcr[i].stride / 2) +
                    (info.pic_x >> xdec);
                uint16_t *pic_data = pic->data[i];

                for (unsigned j = 0; j < pic->h[i]; j++) {
                    memcpy(pic_data, ycbcr_data, sizeof(*pic_data) * pic->w[i]);
                    pic_data += pic->stride[i] / 2;
                    ycbcr_data += ycbcr[i].stride / 2;
                }
            }
        }
    } else if (depth > 8) {
        // unequal bit-depth
        // therefore depth must be > 8 since we do not support depth < 8
        int left_shift = depth - info.depth;
        if (info.depth == 8) {
            for (unsigned i = 0; i < 3; i++) {
                int xdec = i&&!(info.pixel_fmt&1);
                int ydec = i&&!(info.pixel_fmt&2);
                uint8_t *ycbcr_data = ycbcr[i].data +
                    (info.pic_y >> ydec) * ycbcr[i].stride +
                    (info.pic_x >> xdec);
                uint16_t *pic_data = (uint16_t*)pic->data[i];

                for (unsigned j = 0; j < pic->h[i]; j++) {
                    for (unsigned k = 0; k < pic->w[i]; k++) {
                        pic_data[k] = ycbcr_data[k] << left_shift;
                    }
                    pic_data += pic->stride[i] / 2;
                    ycbcr_data += ycbcr[i].stride;
                }
            }
        } else {
            for (unsigned i = 0; i < 3; i++) {
                int xdec = i&&!(info.pixel_fmt&1);
                int ydec = i&&!(info.pixel_fmt&2);
                uint16_t *ycbcr_data = (uint16_t*) ycbcr[i].data +
                    (info.pic_y >> ydec) * (ycbcr[i].stride / 2) +
                    (info.pic_x >> xdec);
                uint16_t *pic_data = pic->data[i];

                for (unsigned j = 0; j < pic->h[i]; j++) {
                    for (unsigned k = 0; k < pic->w[i]; k++) {
                        pic_data[k] = ycbcr_data[k] << left_shift;
                    }
                    pic_data += pic->stride[i] / 2;
                    ycbcr_data += ycbcr[i].stride / 2;
                }
            }
        }
        
    } else {
        fprintf(stderr, "expect depth > 8\n");
        return -1;
    }

    return 0;
}