1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * This file is part of FFmpeg. 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cabdff1aSopenharmony_ci * Lesser General Public License for more details. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17cabdff1aSopenharmony_ci */ 18cabdff1aSopenharmony_ci 19cabdff1aSopenharmony_ci/** 20cabdff1aSopenharmony_ci * @file 21cabdff1aSopenharmony_ci * misc image utilities 22cabdff1aSopenharmony_ci */ 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci#include "avassert.h" 25cabdff1aSopenharmony_ci#include "common.h" 26cabdff1aSopenharmony_ci#include "imgutils.h" 27cabdff1aSopenharmony_ci#include "imgutils_internal.h" 28cabdff1aSopenharmony_ci#include "internal.h" 29cabdff1aSopenharmony_ci#include "intreadwrite.h" 30cabdff1aSopenharmony_ci#include "log.h" 31cabdff1aSopenharmony_ci#include "mathematics.h" 32cabdff1aSopenharmony_ci#include "pixdesc.h" 33cabdff1aSopenharmony_ci#include "rational.h" 34cabdff1aSopenharmony_ci 35cabdff1aSopenharmony_civoid av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4], 36cabdff1aSopenharmony_ci const AVPixFmtDescriptor *pixdesc) 37cabdff1aSopenharmony_ci{ 38cabdff1aSopenharmony_ci int i; 39cabdff1aSopenharmony_ci memset(max_pixsteps, 0, 4*sizeof(max_pixsteps[0])); 40cabdff1aSopenharmony_ci if (max_pixstep_comps) 41cabdff1aSopenharmony_ci memset(max_pixstep_comps, 0, 4*sizeof(max_pixstep_comps[0])); 42cabdff1aSopenharmony_ci 43cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) { 44cabdff1aSopenharmony_ci const AVComponentDescriptor *comp = &(pixdesc->comp[i]); 45cabdff1aSopenharmony_ci if (comp->step > max_pixsteps[comp->plane]) { 46cabdff1aSopenharmony_ci max_pixsteps[comp->plane] = comp->step; 47cabdff1aSopenharmony_ci if (max_pixstep_comps) 48cabdff1aSopenharmony_ci max_pixstep_comps[comp->plane] = i; 49cabdff1aSopenharmony_ci } 50cabdff1aSopenharmony_ci } 51cabdff1aSopenharmony_ci} 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_cistatic inline 54cabdff1aSopenharmony_ciint image_get_linesize(int width, int plane, 55cabdff1aSopenharmony_ci int max_step, int max_step_comp, 56cabdff1aSopenharmony_ci const AVPixFmtDescriptor *desc) 57cabdff1aSopenharmony_ci{ 58cabdff1aSopenharmony_ci int s, shifted_w, linesize; 59cabdff1aSopenharmony_ci 60cabdff1aSopenharmony_ci if (!desc) 61cabdff1aSopenharmony_ci return AVERROR(EINVAL); 62cabdff1aSopenharmony_ci 63cabdff1aSopenharmony_ci if (width < 0) 64cabdff1aSopenharmony_ci return AVERROR(EINVAL); 65cabdff1aSopenharmony_ci s = (max_step_comp == 1 || max_step_comp == 2) ? desc->log2_chroma_w : 0; 66cabdff1aSopenharmony_ci shifted_w = ((width + (1 << s) - 1)) >> s; 67cabdff1aSopenharmony_ci if (shifted_w && max_step > INT_MAX / shifted_w) 68cabdff1aSopenharmony_ci return AVERROR(EINVAL); 69cabdff1aSopenharmony_ci linesize = max_step * shifted_w; 70cabdff1aSopenharmony_ci 71cabdff1aSopenharmony_ci if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) 72cabdff1aSopenharmony_ci linesize = (linesize + 7) >> 3; 73cabdff1aSopenharmony_ci return linesize; 74cabdff1aSopenharmony_ci} 75cabdff1aSopenharmony_ci 76cabdff1aSopenharmony_ciint av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane) 77cabdff1aSopenharmony_ci{ 78cabdff1aSopenharmony_ci const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); 79cabdff1aSopenharmony_ci int max_step [4]; /* max pixel step for each plane */ 80cabdff1aSopenharmony_ci int max_step_comp[4]; /* the component for each plane which has the max pixel step */ 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_ci if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL) 83cabdff1aSopenharmony_ci return AVERROR(EINVAL); 84cabdff1aSopenharmony_ci 85cabdff1aSopenharmony_ci av_image_fill_max_pixsteps(max_step, max_step_comp, desc); 86cabdff1aSopenharmony_ci return image_get_linesize(width, plane, max_step[plane], max_step_comp[plane], desc); 87cabdff1aSopenharmony_ci} 88cabdff1aSopenharmony_ci 89cabdff1aSopenharmony_ciint av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width) 90cabdff1aSopenharmony_ci{ 91cabdff1aSopenharmony_ci int i, ret; 92cabdff1aSopenharmony_ci const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); 93cabdff1aSopenharmony_ci int max_step [4]; /* max pixel step for each plane */ 94cabdff1aSopenharmony_ci int max_step_comp[4]; /* the component for each plane which has the max pixel step */ 95cabdff1aSopenharmony_ci 96cabdff1aSopenharmony_ci memset(linesizes, 0, 4*sizeof(linesizes[0])); 97cabdff1aSopenharmony_ci 98cabdff1aSopenharmony_ci if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL) 99cabdff1aSopenharmony_ci return AVERROR(EINVAL); 100cabdff1aSopenharmony_ci 101cabdff1aSopenharmony_ci av_image_fill_max_pixsteps(max_step, max_step_comp, desc); 102cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) { 103cabdff1aSopenharmony_ci if ((ret = image_get_linesize(width, i, max_step[i], max_step_comp[i], desc)) < 0) 104cabdff1aSopenharmony_ci return ret; 105cabdff1aSopenharmony_ci linesizes[i] = ret; 106cabdff1aSopenharmony_ci } 107cabdff1aSopenharmony_ci 108cabdff1aSopenharmony_ci return 0; 109cabdff1aSopenharmony_ci} 110cabdff1aSopenharmony_ci 111cabdff1aSopenharmony_ciint av_image_fill_plane_sizes(size_t sizes[4], enum AVPixelFormat pix_fmt, 112cabdff1aSopenharmony_ci int height, const ptrdiff_t linesizes[4]) 113cabdff1aSopenharmony_ci{ 114cabdff1aSopenharmony_ci int i, has_plane[4] = { 0 }; 115cabdff1aSopenharmony_ci 116cabdff1aSopenharmony_ci const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); 117cabdff1aSopenharmony_ci memset(sizes , 0, sizeof(sizes[0])*4); 118cabdff1aSopenharmony_ci 119cabdff1aSopenharmony_ci if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL) 120cabdff1aSopenharmony_ci return AVERROR(EINVAL); 121cabdff1aSopenharmony_ci 122cabdff1aSopenharmony_ci if (linesizes[0] > SIZE_MAX / height) 123cabdff1aSopenharmony_ci return AVERROR(EINVAL); 124cabdff1aSopenharmony_ci sizes[0] = linesizes[0] * (size_t)height; 125cabdff1aSopenharmony_ci 126cabdff1aSopenharmony_ci if (desc->flags & AV_PIX_FMT_FLAG_PAL) { 127cabdff1aSopenharmony_ci sizes[1] = 256 * 4; /* palette is stored here as 256 32 bits words */ 128cabdff1aSopenharmony_ci return 0; 129cabdff1aSopenharmony_ci } 130cabdff1aSopenharmony_ci 131cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) 132cabdff1aSopenharmony_ci has_plane[desc->comp[i].plane] = 1; 133cabdff1aSopenharmony_ci 134cabdff1aSopenharmony_ci for (i = 1; i < 4 && has_plane[i]; i++) { 135cabdff1aSopenharmony_ci int h, s = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; 136cabdff1aSopenharmony_ci h = (height + (1 << s) - 1) >> s; 137cabdff1aSopenharmony_ci if (linesizes[i] > SIZE_MAX / h) 138cabdff1aSopenharmony_ci return AVERROR(EINVAL); 139cabdff1aSopenharmony_ci sizes[i] = (size_t)h * linesizes[i]; 140cabdff1aSopenharmony_ci } 141cabdff1aSopenharmony_ci 142cabdff1aSopenharmony_ci return 0; 143cabdff1aSopenharmony_ci} 144cabdff1aSopenharmony_ci 145cabdff1aSopenharmony_ciint av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int height, 146cabdff1aSopenharmony_ci uint8_t *ptr, const int linesizes[4]) 147cabdff1aSopenharmony_ci{ 148cabdff1aSopenharmony_ci int i, ret; 149cabdff1aSopenharmony_ci ptrdiff_t linesizes1[4]; 150cabdff1aSopenharmony_ci size_t sizes[4]; 151cabdff1aSopenharmony_ci 152cabdff1aSopenharmony_ci memset(data , 0, sizeof(data[0])*4); 153cabdff1aSopenharmony_ci 154cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) 155cabdff1aSopenharmony_ci linesizes1[i] = linesizes[i]; 156cabdff1aSopenharmony_ci 157cabdff1aSopenharmony_ci ret = av_image_fill_plane_sizes(sizes, pix_fmt, height, linesizes1); 158cabdff1aSopenharmony_ci if (ret < 0) 159cabdff1aSopenharmony_ci return ret; 160cabdff1aSopenharmony_ci 161cabdff1aSopenharmony_ci ret = 0; 162cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) { 163cabdff1aSopenharmony_ci if (sizes[i] > INT_MAX - ret) 164cabdff1aSopenharmony_ci return AVERROR(EINVAL); 165cabdff1aSopenharmony_ci ret += sizes[i]; 166cabdff1aSopenharmony_ci } 167cabdff1aSopenharmony_ci 168cabdff1aSopenharmony_ci if (!ptr) 169cabdff1aSopenharmony_ci return ret; 170cabdff1aSopenharmony_ci 171cabdff1aSopenharmony_ci data[0] = ptr; 172cabdff1aSopenharmony_ci for (i = 1; i < 4 && sizes[i]; i++) 173cabdff1aSopenharmony_ci data[i] = data[i - 1] + sizes[i - 1]; 174cabdff1aSopenharmony_ci 175cabdff1aSopenharmony_ci return ret; 176cabdff1aSopenharmony_ci} 177cabdff1aSopenharmony_ci 178cabdff1aSopenharmony_ciint avpriv_set_systematic_pal2(uint32_t pal[256], enum AVPixelFormat pix_fmt) 179cabdff1aSopenharmony_ci{ 180cabdff1aSopenharmony_ci int i; 181cabdff1aSopenharmony_ci 182cabdff1aSopenharmony_ci for (i = 0; i < 256; i++) { 183cabdff1aSopenharmony_ci int r, g, b; 184cabdff1aSopenharmony_ci 185cabdff1aSopenharmony_ci switch (pix_fmt) { 186cabdff1aSopenharmony_ci case AV_PIX_FMT_RGB8: 187cabdff1aSopenharmony_ci r = (i>>5 )*36; 188cabdff1aSopenharmony_ci g = ((i>>2)&7)*36; 189cabdff1aSopenharmony_ci b = (i&3 )*85; 190cabdff1aSopenharmony_ci break; 191cabdff1aSopenharmony_ci case AV_PIX_FMT_BGR8: 192cabdff1aSopenharmony_ci b = (i>>6 )*85; 193cabdff1aSopenharmony_ci g = ((i>>3)&7)*36; 194cabdff1aSopenharmony_ci r = (i&7 )*36; 195cabdff1aSopenharmony_ci break; 196cabdff1aSopenharmony_ci case AV_PIX_FMT_RGB4_BYTE: 197cabdff1aSopenharmony_ci r = (i>>3 )*255; 198cabdff1aSopenharmony_ci g = ((i>>1)&3)*85; 199cabdff1aSopenharmony_ci b = (i&1 )*255; 200cabdff1aSopenharmony_ci break; 201cabdff1aSopenharmony_ci case AV_PIX_FMT_BGR4_BYTE: 202cabdff1aSopenharmony_ci b = (i>>3 )*255; 203cabdff1aSopenharmony_ci g = ((i>>1)&3)*85; 204cabdff1aSopenharmony_ci r = (i&1 )*255; 205cabdff1aSopenharmony_ci break; 206cabdff1aSopenharmony_ci case AV_PIX_FMT_GRAY8: 207cabdff1aSopenharmony_ci r = b = g = i; 208cabdff1aSopenharmony_ci break; 209cabdff1aSopenharmony_ci default: 210cabdff1aSopenharmony_ci return AVERROR(EINVAL); 211cabdff1aSopenharmony_ci } 212cabdff1aSopenharmony_ci pal[i] = b + (g << 8) + (r << 16) + (0xFFU << 24); 213cabdff1aSopenharmony_ci } 214cabdff1aSopenharmony_ci 215cabdff1aSopenharmony_ci return 0; 216cabdff1aSopenharmony_ci} 217cabdff1aSopenharmony_ci 218cabdff1aSopenharmony_ciint av_image_alloc(uint8_t *pointers[4], int linesizes[4], 219cabdff1aSopenharmony_ci int w, int h, enum AVPixelFormat pix_fmt, int align) 220cabdff1aSopenharmony_ci{ 221cabdff1aSopenharmony_ci const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); 222cabdff1aSopenharmony_ci int i, ret; 223cabdff1aSopenharmony_ci ptrdiff_t linesizes1[4]; 224cabdff1aSopenharmony_ci size_t total_size, sizes[4]; 225cabdff1aSopenharmony_ci uint8_t *buf; 226cabdff1aSopenharmony_ci 227cabdff1aSopenharmony_ci if (!desc) 228cabdff1aSopenharmony_ci return AVERROR(EINVAL); 229cabdff1aSopenharmony_ci 230cabdff1aSopenharmony_ci if ((ret = av_image_check_size(w, h, 0, NULL)) < 0) 231cabdff1aSopenharmony_ci return ret; 232cabdff1aSopenharmony_ci if ((ret = av_image_fill_linesizes(linesizes, pix_fmt, align>7 ? FFALIGN(w, 8) : w)) < 0) 233cabdff1aSopenharmony_ci return ret; 234cabdff1aSopenharmony_ci 235cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) { 236cabdff1aSopenharmony_ci linesizes[i] = FFALIGN(linesizes[i], align); 237cabdff1aSopenharmony_ci linesizes1[i] = linesizes[i]; 238cabdff1aSopenharmony_ci } 239cabdff1aSopenharmony_ci 240cabdff1aSopenharmony_ci if ((ret = av_image_fill_plane_sizes(sizes, pix_fmt, h, linesizes1)) < 0) 241cabdff1aSopenharmony_ci return ret; 242cabdff1aSopenharmony_ci total_size = align; 243cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) { 244cabdff1aSopenharmony_ci if (total_size > SIZE_MAX - sizes[i]) 245cabdff1aSopenharmony_ci return AVERROR(EINVAL); 246cabdff1aSopenharmony_ci total_size += sizes[i]; 247cabdff1aSopenharmony_ci } 248cabdff1aSopenharmony_ci buf = av_malloc(total_size); 249cabdff1aSopenharmony_ci if (!buf) 250cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 251cabdff1aSopenharmony_ci if ((ret = av_image_fill_pointers(pointers, pix_fmt, h, buf, linesizes)) < 0) { 252cabdff1aSopenharmony_ci av_free(buf); 253cabdff1aSopenharmony_ci return ret; 254cabdff1aSopenharmony_ci } 255cabdff1aSopenharmony_ci if (desc->flags & AV_PIX_FMT_FLAG_PAL) { 256cabdff1aSopenharmony_ci avpriv_set_systematic_pal2((uint32_t*)pointers[1], pix_fmt); 257cabdff1aSopenharmony_ci if (align < 4) { 258cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Formats with a palette require a minimum alignment of 4\n"); 259cabdff1aSopenharmony_ci av_free(buf); 260cabdff1aSopenharmony_ci return AVERROR(EINVAL); 261cabdff1aSopenharmony_ci } 262cabdff1aSopenharmony_ci } 263cabdff1aSopenharmony_ci 264cabdff1aSopenharmony_ci if (desc->flags & AV_PIX_FMT_FLAG_PAL && pointers[1] && 265cabdff1aSopenharmony_ci pointers[1] - pointers[0] > linesizes[0] * h) { 266cabdff1aSopenharmony_ci /* zero-initialize the padding before the palette */ 267cabdff1aSopenharmony_ci memset(pointers[0] + linesizes[0] * h, 0, 268cabdff1aSopenharmony_ci pointers[1] - pointers[0] - linesizes[0] * h); 269cabdff1aSopenharmony_ci } 270cabdff1aSopenharmony_ci 271cabdff1aSopenharmony_ci return ret; 272cabdff1aSopenharmony_ci} 273cabdff1aSopenharmony_ci 274cabdff1aSopenharmony_citypedef struct ImgUtils { 275cabdff1aSopenharmony_ci const AVClass *class; 276cabdff1aSopenharmony_ci int log_offset; 277cabdff1aSopenharmony_ci void *log_ctx; 278cabdff1aSopenharmony_ci} ImgUtils; 279cabdff1aSopenharmony_ci 280cabdff1aSopenharmony_cistatic const AVClass imgutils_class = { 281cabdff1aSopenharmony_ci .class_name = "IMGUTILS", 282cabdff1aSopenharmony_ci .item_name = av_default_item_name, 283cabdff1aSopenharmony_ci .option = NULL, 284cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 285cabdff1aSopenharmony_ci .log_level_offset_offset = offsetof(ImgUtils, log_offset), 286cabdff1aSopenharmony_ci .parent_log_context_offset = offsetof(ImgUtils, log_ctx), 287cabdff1aSopenharmony_ci}; 288cabdff1aSopenharmony_ci 289cabdff1aSopenharmony_ciint av_image_check_size2(unsigned int w, unsigned int h, int64_t max_pixels, enum AVPixelFormat pix_fmt, int log_offset, void *log_ctx) 290cabdff1aSopenharmony_ci{ 291cabdff1aSopenharmony_ci ImgUtils imgutils = { 292cabdff1aSopenharmony_ci .class = &imgutils_class, 293cabdff1aSopenharmony_ci .log_offset = log_offset, 294cabdff1aSopenharmony_ci .log_ctx = log_ctx, 295cabdff1aSopenharmony_ci }; 296cabdff1aSopenharmony_ci int64_t stride = av_image_get_linesize(pix_fmt, w, 0); 297cabdff1aSopenharmony_ci if (stride <= 0) 298cabdff1aSopenharmony_ci stride = 8LL*w; 299cabdff1aSopenharmony_ci stride += 128*8; 300cabdff1aSopenharmony_ci 301cabdff1aSopenharmony_ci if ((int)w<=0 || (int)h<=0 || stride >= INT_MAX || stride*(uint64_t)(h+128) >= INT_MAX) { 302cabdff1aSopenharmony_ci av_log(&imgutils, AV_LOG_ERROR, "Picture size %ux%u is invalid\n", w, h); 303cabdff1aSopenharmony_ci return AVERROR(EINVAL); 304cabdff1aSopenharmony_ci } 305cabdff1aSopenharmony_ci 306cabdff1aSopenharmony_ci if (max_pixels < INT64_MAX) { 307cabdff1aSopenharmony_ci if (w*(int64_t)h > max_pixels) { 308cabdff1aSopenharmony_ci av_log(&imgutils, AV_LOG_ERROR, 309cabdff1aSopenharmony_ci "Picture size %ux%u exceeds specified max pixel count %"PRId64", see the documentation if you wish to increase it\n", 310cabdff1aSopenharmony_ci w, h, max_pixels); 311cabdff1aSopenharmony_ci return AVERROR(EINVAL); 312cabdff1aSopenharmony_ci } 313cabdff1aSopenharmony_ci } 314cabdff1aSopenharmony_ci 315cabdff1aSopenharmony_ci return 0; 316cabdff1aSopenharmony_ci} 317cabdff1aSopenharmony_ci 318cabdff1aSopenharmony_ciint av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx) 319cabdff1aSopenharmony_ci{ 320cabdff1aSopenharmony_ci return av_image_check_size2(w, h, INT64_MAX, AV_PIX_FMT_NONE, log_offset, log_ctx); 321cabdff1aSopenharmony_ci} 322cabdff1aSopenharmony_ci 323cabdff1aSopenharmony_ciint av_image_check_sar(unsigned int w, unsigned int h, AVRational sar) 324cabdff1aSopenharmony_ci{ 325cabdff1aSopenharmony_ci int64_t scaled_dim; 326cabdff1aSopenharmony_ci 327cabdff1aSopenharmony_ci if (sar.den <= 0 || sar.num < 0) 328cabdff1aSopenharmony_ci return AVERROR(EINVAL); 329cabdff1aSopenharmony_ci 330cabdff1aSopenharmony_ci if (!sar.num || sar.num == sar.den) 331cabdff1aSopenharmony_ci return 0; 332cabdff1aSopenharmony_ci 333cabdff1aSopenharmony_ci if (sar.num < sar.den) 334cabdff1aSopenharmony_ci scaled_dim = av_rescale_rnd(w, sar.num, sar.den, AV_ROUND_ZERO); 335cabdff1aSopenharmony_ci else 336cabdff1aSopenharmony_ci scaled_dim = av_rescale_rnd(h, sar.den, sar.num, AV_ROUND_ZERO); 337cabdff1aSopenharmony_ci 338cabdff1aSopenharmony_ci if (scaled_dim > 0) 339cabdff1aSopenharmony_ci return 0; 340cabdff1aSopenharmony_ci 341cabdff1aSopenharmony_ci return AVERROR(EINVAL); 342cabdff1aSopenharmony_ci} 343cabdff1aSopenharmony_ci 344cabdff1aSopenharmony_cistatic void image_copy_plane(uint8_t *dst, ptrdiff_t dst_linesize, 345cabdff1aSopenharmony_ci const uint8_t *src, ptrdiff_t src_linesize, 346cabdff1aSopenharmony_ci ptrdiff_t bytewidth, int height) 347cabdff1aSopenharmony_ci{ 348cabdff1aSopenharmony_ci if (!dst || !src) 349cabdff1aSopenharmony_ci return; 350cabdff1aSopenharmony_ci av_assert0(FFABS(src_linesize) >= bytewidth); 351cabdff1aSopenharmony_ci av_assert0(FFABS(dst_linesize) >= bytewidth); 352cabdff1aSopenharmony_ci for (;height > 0; height--) { 353cabdff1aSopenharmony_ci memcpy(dst, src, bytewidth); 354cabdff1aSopenharmony_ci dst += dst_linesize; 355cabdff1aSopenharmony_ci src += src_linesize; 356cabdff1aSopenharmony_ci } 357cabdff1aSopenharmony_ci} 358cabdff1aSopenharmony_ci 359cabdff1aSopenharmony_civoid av_image_copy_plane_uc_from(uint8_t *dst, ptrdiff_t dst_linesize, 360cabdff1aSopenharmony_ci const uint8_t *src, ptrdiff_t src_linesize, 361cabdff1aSopenharmony_ci ptrdiff_t bytewidth, int height) 362cabdff1aSopenharmony_ci{ 363cabdff1aSopenharmony_ci int ret = -1; 364cabdff1aSopenharmony_ci 365cabdff1aSopenharmony_ci#if ARCH_X86 366cabdff1aSopenharmony_ci ret = ff_image_copy_plane_uc_from_x86(dst, dst_linesize, src, src_linesize, 367cabdff1aSopenharmony_ci bytewidth, height); 368cabdff1aSopenharmony_ci#endif 369cabdff1aSopenharmony_ci 370cabdff1aSopenharmony_ci if (ret < 0) 371cabdff1aSopenharmony_ci image_copy_plane(dst, dst_linesize, src, src_linesize, bytewidth, height); 372cabdff1aSopenharmony_ci} 373cabdff1aSopenharmony_ci 374cabdff1aSopenharmony_civoid av_image_copy_plane(uint8_t *dst, int dst_linesize, 375cabdff1aSopenharmony_ci const uint8_t *src, int src_linesize, 376cabdff1aSopenharmony_ci int bytewidth, int height) 377cabdff1aSopenharmony_ci{ 378cabdff1aSopenharmony_ci image_copy_plane(dst, dst_linesize, src, src_linesize, bytewidth, height); 379cabdff1aSopenharmony_ci} 380cabdff1aSopenharmony_ci 381cabdff1aSopenharmony_cistatic void image_copy(uint8_t *dst_data[4], const ptrdiff_t dst_linesizes[4], 382cabdff1aSopenharmony_ci const uint8_t *src_data[4], const ptrdiff_t src_linesizes[4], 383cabdff1aSopenharmony_ci enum AVPixelFormat pix_fmt, int width, int height, 384cabdff1aSopenharmony_ci void (*copy_plane)(uint8_t *, ptrdiff_t, const uint8_t *, 385cabdff1aSopenharmony_ci ptrdiff_t, ptrdiff_t, int)) 386cabdff1aSopenharmony_ci{ 387cabdff1aSopenharmony_ci const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); 388cabdff1aSopenharmony_ci 389cabdff1aSopenharmony_ci if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL) 390cabdff1aSopenharmony_ci return; 391cabdff1aSopenharmony_ci 392cabdff1aSopenharmony_ci if (desc->flags & AV_PIX_FMT_FLAG_PAL) { 393cabdff1aSopenharmony_ci copy_plane(dst_data[0], dst_linesizes[0], 394cabdff1aSopenharmony_ci src_data[0], src_linesizes[0], 395cabdff1aSopenharmony_ci width, height); 396cabdff1aSopenharmony_ci /* copy the palette */ 397cabdff1aSopenharmony_ci if ((desc->flags & AV_PIX_FMT_FLAG_PAL) || (dst_data[1] && src_data[1])) 398cabdff1aSopenharmony_ci memcpy(dst_data[1], src_data[1], 4*256); 399cabdff1aSopenharmony_ci } else { 400cabdff1aSopenharmony_ci int i, planes_nb = 0; 401cabdff1aSopenharmony_ci 402cabdff1aSopenharmony_ci for (i = 0; i < desc->nb_components; i++) 403cabdff1aSopenharmony_ci planes_nb = FFMAX(planes_nb, desc->comp[i].plane + 1); 404cabdff1aSopenharmony_ci 405cabdff1aSopenharmony_ci for (i = 0; i < planes_nb; i++) { 406cabdff1aSopenharmony_ci int h = height; 407cabdff1aSopenharmony_ci ptrdiff_t bwidth = av_image_get_linesize(pix_fmt, width, i); 408cabdff1aSopenharmony_ci if (bwidth < 0) { 409cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "av_image_get_linesize failed\n"); 410cabdff1aSopenharmony_ci return; 411cabdff1aSopenharmony_ci } 412cabdff1aSopenharmony_ci if (i == 1 || i == 2) { 413cabdff1aSopenharmony_ci h = AV_CEIL_RSHIFT(height, desc->log2_chroma_h); 414cabdff1aSopenharmony_ci } 415cabdff1aSopenharmony_ci copy_plane(dst_data[i], dst_linesizes[i], 416cabdff1aSopenharmony_ci src_data[i], src_linesizes[i], 417cabdff1aSopenharmony_ci bwidth, h); 418cabdff1aSopenharmony_ci } 419cabdff1aSopenharmony_ci } 420cabdff1aSopenharmony_ci} 421cabdff1aSopenharmony_ci 422cabdff1aSopenharmony_civoid av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4], 423cabdff1aSopenharmony_ci const uint8_t *src_data[4], const int src_linesizes[4], 424cabdff1aSopenharmony_ci enum AVPixelFormat pix_fmt, int width, int height) 425cabdff1aSopenharmony_ci{ 426cabdff1aSopenharmony_ci ptrdiff_t dst_linesizes1[4], src_linesizes1[4]; 427cabdff1aSopenharmony_ci int i; 428cabdff1aSopenharmony_ci 429cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) { 430cabdff1aSopenharmony_ci dst_linesizes1[i] = dst_linesizes[i]; 431cabdff1aSopenharmony_ci src_linesizes1[i] = src_linesizes[i]; 432cabdff1aSopenharmony_ci } 433cabdff1aSopenharmony_ci 434cabdff1aSopenharmony_ci image_copy(dst_data, dst_linesizes1, src_data, src_linesizes1, pix_fmt, 435cabdff1aSopenharmony_ci width, height, image_copy_plane); 436cabdff1aSopenharmony_ci} 437cabdff1aSopenharmony_ci 438cabdff1aSopenharmony_civoid av_image_copy_uc_from(uint8_t *dst_data[4], const ptrdiff_t dst_linesizes[4], 439cabdff1aSopenharmony_ci const uint8_t *src_data[4], const ptrdiff_t src_linesizes[4], 440cabdff1aSopenharmony_ci enum AVPixelFormat pix_fmt, int width, int height) 441cabdff1aSopenharmony_ci{ 442cabdff1aSopenharmony_ci image_copy(dst_data, dst_linesizes, src_data, src_linesizes, pix_fmt, 443cabdff1aSopenharmony_ci width, height, av_image_copy_plane_uc_from); 444cabdff1aSopenharmony_ci} 445cabdff1aSopenharmony_ci 446cabdff1aSopenharmony_ciint av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4], 447cabdff1aSopenharmony_ci const uint8_t *src, enum AVPixelFormat pix_fmt, 448cabdff1aSopenharmony_ci int width, int height, int align) 449cabdff1aSopenharmony_ci{ 450cabdff1aSopenharmony_ci int ret, i; 451cabdff1aSopenharmony_ci 452cabdff1aSopenharmony_ci ret = av_image_check_size(width, height, 0, NULL); 453cabdff1aSopenharmony_ci if (ret < 0) 454cabdff1aSopenharmony_ci return ret; 455cabdff1aSopenharmony_ci 456cabdff1aSopenharmony_ci ret = av_image_fill_linesizes(dst_linesize, pix_fmt, width); 457cabdff1aSopenharmony_ci if (ret < 0) 458cabdff1aSopenharmony_ci return ret; 459cabdff1aSopenharmony_ci 460cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) 461cabdff1aSopenharmony_ci dst_linesize[i] = FFALIGN(dst_linesize[i], align); 462cabdff1aSopenharmony_ci 463cabdff1aSopenharmony_ci return av_image_fill_pointers(dst_data, pix_fmt, height, (uint8_t *)src, dst_linesize); 464cabdff1aSopenharmony_ci} 465cabdff1aSopenharmony_ci 466cabdff1aSopenharmony_ciint av_image_get_buffer_size(enum AVPixelFormat pix_fmt, 467cabdff1aSopenharmony_ci int width, int height, int align) 468cabdff1aSopenharmony_ci{ 469cabdff1aSopenharmony_ci int ret, i; 470cabdff1aSopenharmony_ci int linesize[4]; 471cabdff1aSopenharmony_ci ptrdiff_t aligned_linesize[4]; 472cabdff1aSopenharmony_ci size_t sizes[4]; 473cabdff1aSopenharmony_ci const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); 474cabdff1aSopenharmony_ci if (!desc) 475cabdff1aSopenharmony_ci return AVERROR(EINVAL); 476cabdff1aSopenharmony_ci 477cabdff1aSopenharmony_ci ret = av_image_check_size(width, height, 0, NULL); 478cabdff1aSopenharmony_ci if (ret < 0) 479cabdff1aSopenharmony_ci return ret; 480cabdff1aSopenharmony_ci 481cabdff1aSopenharmony_ci ret = av_image_fill_linesizes(linesize, pix_fmt, width); 482cabdff1aSopenharmony_ci if (ret < 0) 483cabdff1aSopenharmony_ci return ret; 484cabdff1aSopenharmony_ci 485cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) 486cabdff1aSopenharmony_ci aligned_linesize[i] = FFALIGN(linesize[i], align); 487cabdff1aSopenharmony_ci 488cabdff1aSopenharmony_ci ret = av_image_fill_plane_sizes(sizes, pix_fmt, height, aligned_linesize); 489cabdff1aSopenharmony_ci if (ret < 0) 490cabdff1aSopenharmony_ci return ret; 491cabdff1aSopenharmony_ci 492cabdff1aSopenharmony_ci ret = 0; 493cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) { 494cabdff1aSopenharmony_ci if (sizes[i] > INT_MAX - ret) 495cabdff1aSopenharmony_ci return AVERROR(EINVAL); 496cabdff1aSopenharmony_ci ret += sizes[i]; 497cabdff1aSopenharmony_ci } 498cabdff1aSopenharmony_ci return ret; 499cabdff1aSopenharmony_ci} 500cabdff1aSopenharmony_ci 501cabdff1aSopenharmony_ciint av_image_copy_to_buffer(uint8_t *dst, int dst_size, 502cabdff1aSopenharmony_ci const uint8_t * const src_data[4], 503cabdff1aSopenharmony_ci const int src_linesize[4], 504cabdff1aSopenharmony_ci enum AVPixelFormat pix_fmt, 505cabdff1aSopenharmony_ci int width, int height, int align) 506cabdff1aSopenharmony_ci{ 507cabdff1aSopenharmony_ci int i, j, nb_planes = 0, linesize[4]; 508cabdff1aSopenharmony_ci int size = av_image_get_buffer_size(pix_fmt, width, height, align); 509cabdff1aSopenharmony_ci const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); 510cabdff1aSopenharmony_ci int ret; 511cabdff1aSopenharmony_ci 512cabdff1aSopenharmony_ci if (size > dst_size || size < 0 || !desc) 513cabdff1aSopenharmony_ci return AVERROR(EINVAL); 514cabdff1aSopenharmony_ci 515cabdff1aSopenharmony_ci for (i = 0; i < desc->nb_components; i++) 516cabdff1aSopenharmony_ci nb_planes = FFMAX(desc->comp[i].plane, nb_planes); 517cabdff1aSopenharmony_ci 518cabdff1aSopenharmony_ci nb_planes++; 519cabdff1aSopenharmony_ci 520cabdff1aSopenharmony_ci ret = av_image_fill_linesizes(linesize, pix_fmt, width); 521cabdff1aSopenharmony_ci av_assert0(ret >= 0); // was checked previously 522cabdff1aSopenharmony_ci 523cabdff1aSopenharmony_ci for (i = 0; i < nb_planes; i++) { 524cabdff1aSopenharmony_ci int h, shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; 525cabdff1aSopenharmony_ci const uint8_t *src = src_data[i]; 526cabdff1aSopenharmony_ci h = (height + (1 << shift) - 1) >> shift; 527cabdff1aSopenharmony_ci 528cabdff1aSopenharmony_ci for (j = 0; j < h; j++) { 529cabdff1aSopenharmony_ci memcpy(dst, src, linesize[i]); 530cabdff1aSopenharmony_ci dst += FFALIGN(linesize[i], align); 531cabdff1aSopenharmony_ci src += src_linesize[i]; 532cabdff1aSopenharmony_ci } 533cabdff1aSopenharmony_ci } 534cabdff1aSopenharmony_ci 535cabdff1aSopenharmony_ci if (desc->flags & AV_PIX_FMT_FLAG_PAL) { 536cabdff1aSopenharmony_ci uint32_t *d32 = (uint32_t *)dst; 537cabdff1aSopenharmony_ci 538cabdff1aSopenharmony_ci for (i = 0; i<256; i++) 539cabdff1aSopenharmony_ci AV_WL32(d32 + i, AV_RN32(src_data[1] + 4*i)); 540cabdff1aSopenharmony_ci } 541cabdff1aSopenharmony_ci 542cabdff1aSopenharmony_ci return size; 543cabdff1aSopenharmony_ci} 544cabdff1aSopenharmony_ci 545cabdff1aSopenharmony_ci// Fill dst[0..dst_size] with the bytes in clear[0..clear_size]. The clear 546cabdff1aSopenharmony_ci// bytes are repeated until dst_size is reached. If dst_size is unaligned (i.e. 547cabdff1aSopenharmony_ci// dst_size%clear_size!=0), the remaining data will be filled with the beginning 548cabdff1aSopenharmony_ci// of the clear data only. 549cabdff1aSopenharmony_cistatic void memset_bytes(uint8_t *dst, size_t dst_size, uint8_t *clear, 550cabdff1aSopenharmony_ci size_t clear_size) 551cabdff1aSopenharmony_ci{ 552cabdff1aSopenharmony_ci int same = 1; 553cabdff1aSopenharmony_ci int i; 554cabdff1aSopenharmony_ci 555cabdff1aSopenharmony_ci if (!clear_size) 556cabdff1aSopenharmony_ci return; 557cabdff1aSopenharmony_ci 558cabdff1aSopenharmony_ci // Reduce to memset() if possible. 559cabdff1aSopenharmony_ci for (i = 0; i < clear_size; i++) { 560cabdff1aSopenharmony_ci if (clear[i] != clear[0]) { 561cabdff1aSopenharmony_ci same = 0; 562cabdff1aSopenharmony_ci break; 563cabdff1aSopenharmony_ci } 564cabdff1aSopenharmony_ci } 565cabdff1aSopenharmony_ci if (same) 566cabdff1aSopenharmony_ci clear_size = 1; 567cabdff1aSopenharmony_ci 568cabdff1aSopenharmony_ci if (clear_size == 1) { 569cabdff1aSopenharmony_ci memset(dst, clear[0], dst_size); 570cabdff1aSopenharmony_ci } else { 571cabdff1aSopenharmony_ci if (clear_size > dst_size) 572cabdff1aSopenharmony_ci clear_size = dst_size; 573cabdff1aSopenharmony_ci memcpy(dst, clear, clear_size); 574cabdff1aSopenharmony_ci av_memcpy_backptr(dst + clear_size, clear_size, dst_size - clear_size); 575cabdff1aSopenharmony_ci } 576cabdff1aSopenharmony_ci} 577cabdff1aSopenharmony_ci 578cabdff1aSopenharmony_ci// Maximum size in bytes of a plane element (usually a pixel, or multiple pixels 579cabdff1aSopenharmony_ci// if it's a subsampled packed format). 580cabdff1aSopenharmony_ci#define MAX_BLOCK_SIZE 32 581cabdff1aSopenharmony_ci 582cabdff1aSopenharmony_ciint av_image_fill_black(uint8_t *dst_data[4], const ptrdiff_t dst_linesize[4], 583cabdff1aSopenharmony_ci enum AVPixelFormat pix_fmt, enum AVColorRange range, 584cabdff1aSopenharmony_ci int width, int height) 585cabdff1aSopenharmony_ci{ 586cabdff1aSopenharmony_ci const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); 587cabdff1aSopenharmony_ci int nb_planes = av_pix_fmt_count_planes(pix_fmt); 588cabdff1aSopenharmony_ci // A pixel or a group of pixels on each plane, with a value that represents black. 589cabdff1aSopenharmony_ci // Consider e.g. AV_PIX_FMT_UYVY422 for non-trivial cases. 590cabdff1aSopenharmony_ci uint8_t clear_block[4][MAX_BLOCK_SIZE] = {{0}}; // clear padding with 0 591cabdff1aSopenharmony_ci int clear_block_size[4] = {0}; 592cabdff1aSopenharmony_ci ptrdiff_t plane_line_bytes[4] = {0}; 593cabdff1aSopenharmony_ci int rgb, limited; 594cabdff1aSopenharmony_ci int plane, c; 595cabdff1aSopenharmony_ci 596cabdff1aSopenharmony_ci if (!desc || nb_planes < 1 || nb_planes > 4 || desc->flags & AV_PIX_FMT_FLAG_HWACCEL) 597cabdff1aSopenharmony_ci return AVERROR(EINVAL); 598cabdff1aSopenharmony_ci 599cabdff1aSopenharmony_ci rgb = !!(desc->flags & AV_PIX_FMT_FLAG_RGB); 600cabdff1aSopenharmony_ci limited = !rgb && range != AVCOL_RANGE_JPEG; 601cabdff1aSopenharmony_ci 602cabdff1aSopenharmony_ci if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) { 603cabdff1aSopenharmony_ci ptrdiff_t bytewidth = av_image_get_linesize(pix_fmt, width, 0); 604cabdff1aSopenharmony_ci uint8_t *data; 605cabdff1aSopenharmony_ci int mono = pix_fmt == AV_PIX_FMT_MONOWHITE || pix_fmt == AV_PIX_FMT_MONOBLACK; 606cabdff1aSopenharmony_ci int fill = pix_fmt == AV_PIX_FMT_MONOWHITE ? 0xFF : 0; 607cabdff1aSopenharmony_ci if (nb_planes != 1 || !(rgb || mono) || bytewidth < 1) 608cabdff1aSopenharmony_ci return AVERROR(EINVAL); 609cabdff1aSopenharmony_ci 610cabdff1aSopenharmony_ci if (!dst_data) 611cabdff1aSopenharmony_ci return 0; 612cabdff1aSopenharmony_ci 613cabdff1aSopenharmony_ci data = dst_data[0]; 614cabdff1aSopenharmony_ci 615cabdff1aSopenharmony_ci // (Bitstream + alpha will be handled incorrectly - it'll remain transparent.) 616cabdff1aSopenharmony_ci for (;height > 0; height--) { 617cabdff1aSopenharmony_ci memset(data, fill, bytewidth); 618cabdff1aSopenharmony_ci data += dst_linesize[0]; 619cabdff1aSopenharmony_ci } 620cabdff1aSopenharmony_ci return 0; 621cabdff1aSopenharmony_ci } 622cabdff1aSopenharmony_ci 623cabdff1aSopenharmony_ci for (c = 0; c < desc->nb_components; c++) { 624cabdff1aSopenharmony_ci const AVComponentDescriptor comp = desc->comp[c]; 625cabdff1aSopenharmony_ci 626cabdff1aSopenharmony_ci // We try to operate on entire non-subsampled pixel groups (for 627cabdff1aSopenharmony_ci // AV_PIX_FMT_UYVY422 this would mean two consecutive pixels). 628cabdff1aSopenharmony_ci clear_block_size[comp.plane] = FFMAX(clear_block_size[comp.plane], comp.step); 629cabdff1aSopenharmony_ci 630cabdff1aSopenharmony_ci if (clear_block_size[comp.plane] > MAX_BLOCK_SIZE) 631cabdff1aSopenharmony_ci return AVERROR(EINVAL); 632cabdff1aSopenharmony_ci } 633cabdff1aSopenharmony_ci 634cabdff1aSopenharmony_ci // Create a byte array for clearing 1 pixel (sometimes several pixels). 635cabdff1aSopenharmony_ci for (c = 0; c < desc->nb_components; c++) { 636cabdff1aSopenharmony_ci const AVComponentDescriptor comp = desc->comp[c]; 637cabdff1aSopenharmony_ci // (Multiple pixels happen e.g. with AV_PIX_FMT_UYVY422.) 638cabdff1aSopenharmony_ci int w = clear_block_size[comp.plane] / comp.step; 639cabdff1aSopenharmony_ci uint8_t *c_data[4]; 640cabdff1aSopenharmony_ci const int c_linesize[4] = {0}; 641cabdff1aSopenharmony_ci uint16_t src_array[MAX_BLOCK_SIZE]; 642cabdff1aSopenharmony_ci uint16_t src = 0; 643cabdff1aSopenharmony_ci int x; 644cabdff1aSopenharmony_ci 645cabdff1aSopenharmony_ci if (comp.depth > 16) 646cabdff1aSopenharmony_ci return AVERROR(EINVAL); 647cabdff1aSopenharmony_ci if (!rgb && comp.depth < 8) 648cabdff1aSopenharmony_ci return AVERROR(EINVAL); 649cabdff1aSopenharmony_ci if (w < 1) 650cabdff1aSopenharmony_ci return AVERROR(EINVAL); 651cabdff1aSopenharmony_ci 652cabdff1aSopenharmony_ci if (c == 0 && limited) { 653cabdff1aSopenharmony_ci src = 16 << (comp.depth - 8); 654cabdff1aSopenharmony_ci } else if ((c == 1 || c == 2) && !rgb) { 655cabdff1aSopenharmony_ci src = 128 << (comp.depth - 8); 656cabdff1aSopenharmony_ci } else if (c == 3) { 657cabdff1aSopenharmony_ci // (Assume even limited YUV uses full range alpha.) 658cabdff1aSopenharmony_ci src = (1 << comp.depth) - 1; 659cabdff1aSopenharmony_ci } 660cabdff1aSopenharmony_ci 661cabdff1aSopenharmony_ci for (x = 0; x < w; x++) 662cabdff1aSopenharmony_ci src_array[x] = src; 663cabdff1aSopenharmony_ci 664cabdff1aSopenharmony_ci for (x = 0; x < 4; x++) 665cabdff1aSopenharmony_ci c_data[x] = &clear_block[x][0]; 666cabdff1aSopenharmony_ci 667cabdff1aSopenharmony_ci av_write_image_line(src_array, c_data, c_linesize, desc, 0, 0, c, w); 668cabdff1aSopenharmony_ci } 669cabdff1aSopenharmony_ci 670cabdff1aSopenharmony_ci for (plane = 0; plane < nb_planes; plane++) { 671cabdff1aSopenharmony_ci plane_line_bytes[plane] = av_image_get_linesize(pix_fmt, width, plane); 672cabdff1aSopenharmony_ci if (plane_line_bytes[plane] < 0) 673cabdff1aSopenharmony_ci return AVERROR(EINVAL); 674cabdff1aSopenharmony_ci } 675cabdff1aSopenharmony_ci 676cabdff1aSopenharmony_ci if (!dst_data) 677cabdff1aSopenharmony_ci return 0; 678cabdff1aSopenharmony_ci 679cabdff1aSopenharmony_ci for (plane = 0; plane < nb_planes; plane++) { 680cabdff1aSopenharmony_ci size_t bytewidth = plane_line_bytes[plane]; 681cabdff1aSopenharmony_ci uint8_t *data = dst_data[plane]; 682cabdff1aSopenharmony_ci int chroma_div = plane == 1 || plane == 2 ? desc->log2_chroma_h : 0; 683cabdff1aSopenharmony_ci int plane_h = ((height + ( 1 << chroma_div) - 1)) >> chroma_div; 684cabdff1aSopenharmony_ci 685cabdff1aSopenharmony_ci for (; plane_h > 0; plane_h--) { 686cabdff1aSopenharmony_ci memset_bytes(data, bytewidth, &clear_block[plane][0], clear_block_size[plane]); 687cabdff1aSopenharmony_ci data += dst_linesize[plane]; 688cabdff1aSopenharmony_ci } 689cabdff1aSopenharmony_ci } 690cabdff1aSopenharmony_ci 691cabdff1aSopenharmony_ci return 0; 692cabdff1aSopenharmony_ci} 693