123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896 |
- /*
- * Copyright 2011 The LibYuv Project Authors. All rights reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
- #include "libyuv/scale.h"
- #include <assert.h>
- #include <string.h>
- #include "libyuv/cpu_id.h"
- #include "libyuv/planar_functions.h" // For CopyPlane
- #include "libyuv/row.h"
- #include "libyuv/scale_row.h"
- #ifdef __cplusplus
- namespace libyuv {
- extern "C" {
- #endif
- static __inline int Abs(int v) {
- return v >= 0 ? v : -v;
- }
- #define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s)
- // Scale plane, 1/2
- // This is an optimized version for scaling down a plane to 1/2 of
- // its original size.
- static void ScalePlaneDown2(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- int src_stride,
- int dst_stride,
- const uint8_t* src_ptr,
- uint8_t* dst_ptr,
- enum FilterMode filtering) {
- int y;
- void (*ScaleRowDown2)(const uint8_t* src_ptr, ptrdiff_t src_stride,
- uint8_t* dst_ptr, int dst_width) =
- filtering == kFilterNone
- ? ScaleRowDown2_C
- : (filtering == kFilterLinear ? ScaleRowDown2Linear_C
- : ScaleRowDown2Box_C);
- int row_stride = src_stride << 1;
- (void)src_width;
- (void)src_height;
- if (!filtering) {
- src_ptr += src_stride; // Point to odd rows.
- src_stride = 0;
- }
- #if defined(HAS_SCALEROWDOWN2_NEON)
- if (TestCpuFlag(kCpuHasNEON)) {
- ScaleRowDown2 =
- filtering == kFilterNone
- ? ScaleRowDown2_Any_NEON
- : (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_NEON
- : ScaleRowDown2Box_Any_NEON);
- if (IS_ALIGNED(dst_width, 16)) {
- ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_NEON
- : (filtering == kFilterLinear
- ? ScaleRowDown2Linear_NEON
- : ScaleRowDown2Box_NEON);
- }
- }
- #endif
- #if defined(HAS_SCALEROWDOWN2_SSSE3)
- if (TestCpuFlag(kCpuHasSSSE3)) {
- ScaleRowDown2 =
- filtering == kFilterNone
- ? ScaleRowDown2_Any_SSSE3
- : (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_SSSE3
- : ScaleRowDown2Box_Any_SSSE3);
- if (IS_ALIGNED(dst_width, 16)) {
- ScaleRowDown2 =
- filtering == kFilterNone
- ? ScaleRowDown2_SSSE3
- : (filtering == kFilterLinear ? ScaleRowDown2Linear_SSSE3
- : ScaleRowDown2Box_SSSE3);
- }
- }
- #endif
- #if defined(HAS_SCALEROWDOWN2_AVX2)
- if (TestCpuFlag(kCpuHasAVX2)) {
- ScaleRowDown2 =
- filtering == kFilterNone
- ? ScaleRowDown2_Any_AVX2
- : (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_AVX2
- : ScaleRowDown2Box_Any_AVX2);
- if (IS_ALIGNED(dst_width, 32)) {
- ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_AVX2
- : (filtering == kFilterLinear
- ? ScaleRowDown2Linear_AVX2
- : ScaleRowDown2Box_AVX2);
- }
- }
- #endif
- #if defined(HAS_SCALEROWDOWN2_MSA)
- if (TestCpuFlag(kCpuHasMSA)) {
- ScaleRowDown2 =
- filtering == kFilterNone
- ? ScaleRowDown2_Any_MSA
- : (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_MSA
- : ScaleRowDown2Box_Any_MSA);
- if (IS_ALIGNED(dst_width, 32)) {
- ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_MSA
- : (filtering == kFilterLinear
- ? ScaleRowDown2Linear_MSA
- : ScaleRowDown2Box_MSA);
- }
- }
- #endif
- #if defined(HAS_SCALEROWDOWN2_MMI)
- if (TestCpuFlag(kCpuHasMMI)) {
- ScaleRowDown2 =
- filtering == kFilterNone
- ? ScaleRowDown2_Any_MMI
- : (filtering == kFilterLinear ? ScaleRowDown2Linear_Any_MMI
- : ScaleRowDown2Box_Any_MMI);
- if (IS_ALIGNED(dst_width, 8)) {
- ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_MMI
- : (filtering == kFilterLinear
- ? ScaleRowDown2Linear_MMI
- : ScaleRowDown2Box_MMI);
- }
- }
- #endif
- if (filtering == kFilterLinear) {
- src_stride = 0;
- }
- // TODO(fbarchard): Loop through source height to allow odd height.
- for (y = 0; y < dst_height; ++y) {
- ScaleRowDown2(src_ptr, src_stride, dst_ptr, dst_width);
- src_ptr += row_stride;
- dst_ptr += dst_stride;
- }
- }
- static void ScalePlaneDown2_16(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- int src_stride,
- int dst_stride,
- const uint16_t* src_ptr,
- uint16_t* dst_ptr,
- enum FilterMode filtering) {
- int y;
- void (*ScaleRowDown2)(const uint16_t* src_ptr, ptrdiff_t src_stride,
- uint16_t* dst_ptr, int dst_width) =
- filtering == kFilterNone
- ? ScaleRowDown2_16_C
- : (filtering == kFilterLinear ? ScaleRowDown2Linear_16_C
- : ScaleRowDown2Box_16_C);
- int row_stride = src_stride << 1;
- (void)src_width;
- (void)src_height;
- if (!filtering) {
- src_ptr += src_stride; // Point to odd rows.
- src_stride = 0;
- }
- #if defined(HAS_SCALEROWDOWN2_16_NEON)
- if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 16)) {
- ScaleRowDown2 =
- filtering ? ScaleRowDown2Box_16_NEON : ScaleRowDown2_16_NEON;
- }
- #endif
- #if defined(HAS_SCALEROWDOWN2_16_SSE2)
- if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 16)) {
- ScaleRowDown2 =
- filtering == kFilterNone
- ? ScaleRowDown2_16_SSE2
- : (filtering == kFilterLinear ? ScaleRowDown2Linear_16_SSE2
- : ScaleRowDown2Box_16_SSE2);
- }
- #endif
- #if defined(HAS_SCALEROWDOWN2_16_MMI)
- if (TestCpuFlag(kCpuHasMMI) && IS_ALIGNED(dst_width, 4)) {
- ScaleRowDown2 = filtering == kFilterNone ? ScaleRowDown2_16_MMI
- : (filtering == kFilterLinear
- ? ScaleRowDown2Linear_16_MMI
- : ScaleRowDown2Box_16_MMI);
- }
- #endif
- if (filtering == kFilterLinear) {
- src_stride = 0;
- }
- // TODO(fbarchard): Loop through source height to allow odd height.
- for (y = 0; y < dst_height; ++y) {
- ScaleRowDown2(src_ptr, src_stride, dst_ptr, dst_width);
- src_ptr += row_stride;
- dst_ptr += dst_stride;
- }
- }
- // Scale plane, 1/4
- // This is an optimized version for scaling down a plane to 1/4 of
- // its original size.
- static void ScalePlaneDown4(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- int src_stride,
- int dst_stride,
- const uint8_t* src_ptr,
- uint8_t* dst_ptr,
- enum FilterMode filtering) {
- int y;
- void (*ScaleRowDown4)(const uint8_t* src_ptr, ptrdiff_t src_stride,
- uint8_t* dst_ptr, int dst_width) =
- filtering ? ScaleRowDown4Box_C : ScaleRowDown4_C;
- int row_stride = src_stride << 2;
- (void)src_width;
- (void)src_height;
- if (!filtering) {
- src_ptr += src_stride * 2; // Point to row 2.
- src_stride = 0;
- }
- #if defined(HAS_SCALEROWDOWN4_NEON)
- if (TestCpuFlag(kCpuHasNEON)) {
- ScaleRowDown4 =
- filtering ? ScaleRowDown4Box_Any_NEON : ScaleRowDown4_Any_NEON;
- if (IS_ALIGNED(dst_width, 8)) {
- ScaleRowDown4 = filtering ? ScaleRowDown4Box_NEON : ScaleRowDown4_NEON;
- }
- }
- #endif
- #if defined(HAS_SCALEROWDOWN4_SSSE3)
- if (TestCpuFlag(kCpuHasSSSE3)) {
- ScaleRowDown4 =
- filtering ? ScaleRowDown4Box_Any_SSSE3 : ScaleRowDown4_Any_SSSE3;
- if (IS_ALIGNED(dst_width, 8)) {
- ScaleRowDown4 = filtering ? ScaleRowDown4Box_SSSE3 : ScaleRowDown4_SSSE3;
- }
- }
- #endif
- #if defined(HAS_SCALEROWDOWN4_AVX2)
- if (TestCpuFlag(kCpuHasAVX2)) {
- ScaleRowDown4 =
- filtering ? ScaleRowDown4Box_Any_AVX2 : ScaleRowDown4_Any_AVX2;
- if (IS_ALIGNED(dst_width, 16)) {
- ScaleRowDown4 = filtering ? ScaleRowDown4Box_AVX2 : ScaleRowDown4_AVX2;
- }
- }
- #endif
- #if defined(HAS_SCALEROWDOWN4_MSA)
- if (TestCpuFlag(kCpuHasMSA)) {
- ScaleRowDown4 =
- filtering ? ScaleRowDown4Box_Any_MSA : ScaleRowDown4_Any_MSA;
- if (IS_ALIGNED(dst_width, 16)) {
- ScaleRowDown4 = filtering ? ScaleRowDown4Box_MSA : ScaleRowDown4_MSA;
- }
- }
- #endif
- #if defined(HAS_SCALEROWDOWN4_MMI)
- if (TestCpuFlag(kCpuHasMMI)) {
- ScaleRowDown4 =
- filtering ? ScaleRowDown4Box_Any_MMI : ScaleRowDown4_Any_MMI;
- if (IS_ALIGNED(dst_width, 8)) {
- ScaleRowDown4 = filtering ? ScaleRowDown4Box_MMI : ScaleRowDown4_MMI;
- }
- }
- #endif
- if (filtering == kFilterLinear) {
- src_stride = 0;
- }
- for (y = 0; y < dst_height; ++y) {
- ScaleRowDown4(src_ptr, src_stride, dst_ptr, dst_width);
- src_ptr += row_stride;
- dst_ptr += dst_stride;
- }
- }
- static void ScalePlaneDown4_16(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- int src_stride,
- int dst_stride,
- const uint16_t* src_ptr,
- uint16_t* dst_ptr,
- enum FilterMode filtering) {
- int y;
- void (*ScaleRowDown4)(const uint16_t* src_ptr, ptrdiff_t src_stride,
- uint16_t* dst_ptr, int dst_width) =
- filtering ? ScaleRowDown4Box_16_C : ScaleRowDown4_16_C;
- int row_stride = src_stride << 2;
- (void)src_width;
- (void)src_height;
- if (!filtering) {
- src_ptr += src_stride * 2; // Point to row 2.
- src_stride = 0;
- }
- #if defined(HAS_SCALEROWDOWN4_16_NEON)
- if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(dst_width, 8)) {
- ScaleRowDown4 =
- filtering ? ScaleRowDown4Box_16_NEON : ScaleRowDown4_16_NEON;
- }
- #endif
- #if defined(HAS_SCALEROWDOWN4_16_SSE2)
- if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) {
- ScaleRowDown4 =
- filtering ? ScaleRowDown4Box_16_SSE2 : ScaleRowDown4_16_SSE2;
- }
- #endif
- #if defined(HAS_SCALEROWDOWN4_16_MMI)
- if (TestCpuFlag(kCpuHasMMI) && IS_ALIGNED(dst_width, 8)) {
- ScaleRowDown4 = filtering ? ScaleRowDown4Box_16_MMI : ScaleRowDown4_16_MMI;
- }
- #endif
- if (filtering == kFilterLinear) {
- src_stride = 0;
- }
- for (y = 0; y < dst_height; ++y) {
- ScaleRowDown4(src_ptr, src_stride, dst_ptr, dst_width);
- src_ptr += row_stride;
- dst_ptr += dst_stride;
- }
- }
- // Scale plane down, 3/4
- static void ScalePlaneDown34(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- int src_stride,
- int dst_stride,
- const uint8_t* src_ptr,
- uint8_t* dst_ptr,
- enum FilterMode filtering) {
- int y;
- void (*ScaleRowDown34_0)(const uint8_t* src_ptr, ptrdiff_t src_stride,
- uint8_t* dst_ptr, int dst_width);
- void (*ScaleRowDown34_1)(const uint8_t* src_ptr, ptrdiff_t src_stride,
- uint8_t* dst_ptr, int dst_width);
- const int filter_stride = (filtering == kFilterLinear) ? 0 : src_stride;
- (void)src_width;
- (void)src_height;
- assert(dst_width % 3 == 0);
- if (!filtering) {
- ScaleRowDown34_0 = ScaleRowDown34_C;
- ScaleRowDown34_1 = ScaleRowDown34_C;
- } else {
- ScaleRowDown34_0 = ScaleRowDown34_0_Box_C;
- ScaleRowDown34_1 = ScaleRowDown34_1_Box_C;
- }
- #if defined(HAS_SCALEROWDOWN34_NEON)
- if (TestCpuFlag(kCpuHasNEON)) {
- if (!filtering) {
- ScaleRowDown34_0 = ScaleRowDown34_Any_NEON;
- ScaleRowDown34_1 = ScaleRowDown34_Any_NEON;
- } else {
- ScaleRowDown34_0 = ScaleRowDown34_0_Box_Any_NEON;
- ScaleRowDown34_1 = ScaleRowDown34_1_Box_Any_NEON;
- }
- if (dst_width % 24 == 0) {
- if (!filtering) {
- ScaleRowDown34_0 = ScaleRowDown34_NEON;
- ScaleRowDown34_1 = ScaleRowDown34_NEON;
- } else {
- ScaleRowDown34_0 = ScaleRowDown34_0_Box_NEON;
- ScaleRowDown34_1 = ScaleRowDown34_1_Box_NEON;
- }
- }
- }
- #endif
- #if defined(HAS_SCALEROWDOWN34_MSA)
- if (TestCpuFlag(kCpuHasMSA)) {
- if (!filtering) {
- ScaleRowDown34_0 = ScaleRowDown34_Any_MSA;
- ScaleRowDown34_1 = ScaleRowDown34_Any_MSA;
- } else {
- ScaleRowDown34_0 = ScaleRowDown34_0_Box_Any_MSA;
- ScaleRowDown34_1 = ScaleRowDown34_1_Box_Any_MSA;
- }
- if (dst_width % 48 == 0) {
- if (!filtering) {
- ScaleRowDown34_0 = ScaleRowDown34_MSA;
- ScaleRowDown34_1 = ScaleRowDown34_MSA;
- } else {
- ScaleRowDown34_0 = ScaleRowDown34_0_Box_MSA;
- ScaleRowDown34_1 = ScaleRowDown34_1_Box_MSA;
- }
- }
- }
- #endif
- #if defined(HAS_SCALEROWDOWN34_SSSE3)
- if (TestCpuFlag(kCpuHasSSSE3)) {
- if (!filtering) {
- ScaleRowDown34_0 = ScaleRowDown34_Any_SSSE3;
- ScaleRowDown34_1 = ScaleRowDown34_Any_SSSE3;
- } else {
- ScaleRowDown34_0 = ScaleRowDown34_0_Box_Any_SSSE3;
- ScaleRowDown34_1 = ScaleRowDown34_1_Box_Any_SSSE3;
- }
- if (dst_width % 24 == 0) {
- if (!filtering) {
- ScaleRowDown34_0 = ScaleRowDown34_SSSE3;
- ScaleRowDown34_1 = ScaleRowDown34_SSSE3;
- } else {
- ScaleRowDown34_0 = ScaleRowDown34_0_Box_SSSE3;
- ScaleRowDown34_1 = ScaleRowDown34_1_Box_SSSE3;
- }
- }
- }
- #endif
- for (y = 0; y < dst_height - 2; y += 3) {
- ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width);
- src_ptr += src_stride;
- dst_ptr += dst_stride;
- ScaleRowDown34_1(src_ptr, filter_stride, dst_ptr, dst_width);
- src_ptr += src_stride;
- dst_ptr += dst_stride;
- ScaleRowDown34_0(src_ptr + src_stride, -filter_stride, dst_ptr, dst_width);
- src_ptr += src_stride * 2;
- dst_ptr += dst_stride;
- }
- // Remainder 1 or 2 rows with last row vertically unfiltered
- if ((dst_height % 3) == 2) {
- ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width);
- src_ptr += src_stride;
- dst_ptr += dst_stride;
- ScaleRowDown34_1(src_ptr, 0, dst_ptr, dst_width);
- } else if ((dst_height % 3) == 1) {
- ScaleRowDown34_0(src_ptr, 0, dst_ptr, dst_width);
- }
- }
- static void ScalePlaneDown34_16(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- int src_stride,
- int dst_stride,
- const uint16_t* src_ptr,
- uint16_t* dst_ptr,
- enum FilterMode filtering) {
- int y;
- void (*ScaleRowDown34_0)(const uint16_t* src_ptr, ptrdiff_t src_stride,
- uint16_t* dst_ptr, int dst_width);
- void (*ScaleRowDown34_1)(const uint16_t* src_ptr, ptrdiff_t src_stride,
- uint16_t* dst_ptr, int dst_width);
- const int filter_stride = (filtering == kFilterLinear) ? 0 : src_stride;
- (void)src_width;
- (void)src_height;
- assert(dst_width % 3 == 0);
- if (!filtering) {
- ScaleRowDown34_0 = ScaleRowDown34_16_C;
- ScaleRowDown34_1 = ScaleRowDown34_16_C;
- } else {
- ScaleRowDown34_0 = ScaleRowDown34_0_Box_16_C;
- ScaleRowDown34_1 = ScaleRowDown34_1_Box_16_C;
- }
- #if defined(HAS_SCALEROWDOWN34_16_NEON)
- if (TestCpuFlag(kCpuHasNEON) && (dst_width % 24 == 0)) {
- if (!filtering) {
- ScaleRowDown34_0 = ScaleRowDown34_16_NEON;
- ScaleRowDown34_1 = ScaleRowDown34_16_NEON;
- } else {
- ScaleRowDown34_0 = ScaleRowDown34_0_Box_16_NEON;
- ScaleRowDown34_1 = ScaleRowDown34_1_Box_16_NEON;
- }
- }
- #endif
- #if defined(HAS_SCALEROWDOWN34_16_SSSE3)
- if (TestCpuFlag(kCpuHasSSSE3) && (dst_width % 24 == 0)) {
- if (!filtering) {
- ScaleRowDown34_0 = ScaleRowDown34_16_SSSE3;
- ScaleRowDown34_1 = ScaleRowDown34_16_SSSE3;
- } else {
- ScaleRowDown34_0 = ScaleRowDown34_0_Box_16_SSSE3;
- ScaleRowDown34_1 = ScaleRowDown34_1_Box_16_SSSE3;
- }
- }
- #endif
- for (y = 0; y < dst_height - 2; y += 3) {
- ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width);
- src_ptr += src_stride;
- dst_ptr += dst_stride;
- ScaleRowDown34_1(src_ptr, filter_stride, dst_ptr, dst_width);
- src_ptr += src_stride;
- dst_ptr += dst_stride;
- ScaleRowDown34_0(src_ptr + src_stride, -filter_stride, dst_ptr, dst_width);
- src_ptr += src_stride * 2;
- dst_ptr += dst_stride;
- }
- // Remainder 1 or 2 rows with last row vertically unfiltered
- if ((dst_height % 3) == 2) {
- ScaleRowDown34_0(src_ptr, filter_stride, dst_ptr, dst_width);
- src_ptr += src_stride;
- dst_ptr += dst_stride;
- ScaleRowDown34_1(src_ptr, 0, dst_ptr, dst_width);
- } else if ((dst_height % 3) == 1) {
- ScaleRowDown34_0(src_ptr, 0, dst_ptr, dst_width);
- }
- }
- // Scale plane, 3/8
- // This is an optimized version for scaling down a plane to 3/8
- // of its original size.
- //
- // Uses box filter arranges like this
- // aaabbbcc -> abc
- // aaabbbcc def
- // aaabbbcc ghi
- // dddeeeff
- // dddeeeff
- // dddeeeff
- // ggghhhii
- // ggghhhii
- // Boxes are 3x3, 2x3, 3x2 and 2x2
- static void ScalePlaneDown38(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- int src_stride,
- int dst_stride,
- const uint8_t* src_ptr,
- uint8_t* dst_ptr,
- enum FilterMode filtering) {
- int y;
- void (*ScaleRowDown38_3)(const uint8_t* src_ptr, ptrdiff_t src_stride,
- uint8_t* dst_ptr, int dst_width);
- void (*ScaleRowDown38_2)(const uint8_t* src_ptr, ptrdiff_t src_stride,
- uint8_t* dst_ptr, int dst_width);
- const int filter_stride = (filtering == kFilterLinear) ? 0 : src_stride;
- assert(dst_width % 3 == 0);
- (void)src_width;
- (void)src_height;
- if (!filtering) {
- ScaleRowDown38_3 = ScaleRowDown38_C;
- ScaleRowDown38_2 = ScaleRowDown38_C;
- } else {
- ScaleRowDown38_3 = ScaleRowDown38_3_Box_C;
- ScaleRowDown38_2 = ScaleRowDown38_2_Box_C;
- }
- #if defined(HAS_SCALEROWDOWN38_NEON)
- if (TestCpuFlag(kCpuHasNEON)) {
- if (!filtering) {
- ScaleRowDown38_3 = ScaleRowDown38_Any_NEON;
- ScaleRowDown38_2 = ScaleRowDown38_Any_NEON;
- } else {
- ScaleRowDown38_3 = ScaleRowDown38_3_Box_Any_NEON;
- ScaleRowDown38_2 = ScaleRowDown38_2_Box_Any_NEON;
- }
- if (dst_width % 12 == 0) {
- if (!filtering) {
- ScaleRowDown38_3 = ScaleRowDown38_NEON;
- ScaleRowDown38_2 = ScaleRowDown38_NEON;
- } else {
- ScaleRowDown38_3 = ScaleRowDown38_3_Box_NEON;
- ScaleRowDown38_2 = ScaleRowDown38_2_Box_NEON;
- }
- }
- }
- #endif
- #if defined(HAS_SCALEROWDOWN38_SSSE3)
- if (TestCpuFlag(kCpuHasSSSE3)) {
- if (!filtering) {
- ScaleRowDown38_3 = ScaleRowDown38_Any_SSSE3;
- ScaleRowDown38_2 = ScaleRowDown38_Any_SSSE3;
- } else {
- ScaleRowDown38_3 = ScaleRowDown38_3_Box_Any_SSSE3;
- ScaleRowDown38_2 = ScaleRowDown38_2_Box_Any_SSSE3;
- }
- if (dst_width % 12 == 0 && !filtering) {
- ScaleRowDown38_3 = ScaleRowDown38_SSSE3;
- ScaleRowDown38_2 = ScaleRowDown38_SSSE3;
- }
- if (dst_width % 6 == 0 && filtering) {
- ScaleRowDown38_3 = ScaleRowDown38_3_Box_SSSE3;
- ScaleRowDown38_2 = ScaleRowDown38_2_Box_SSSE3;
- }
- }
- #endif
- #if defined(HAS_SCALEROWDOWN38_MSA)
- if (TestCpuFlag(kCpuHasMSA)) {
- if (!filtering) {
- ScaleRowDown38_3 = ScaleRowDown38_Any_MSA;
- ScaleRowDown38_2 = ScaleRowDown38_Any_MSA;
- } else {
- ScaleRowDown38_3 = ScaleRowDown38_3_Box_Any_MSA;
- ScaleRowDown38_2 = ScaleRowDown38_2_Box_Any_MSA;
- }
- if (dst_width % 12 == 0) {
- if (!filtering) {
- ScaleRowDown38_3 = ScaleRowDown38_MSA;
- ScaleRowDown38_2 = ScaleRowDown38_MSA;
- } else {
- ScaleRowDown38_3 = ScaleRowDown38_3_Box_MSA;
- ScaleRowDown38_2 = ScaleRowDown38_2_Box_MSA;
- }
- }
- }
- #endif
- for (y = 0; y < dst_height - 2; y += 3) {
- ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width);
- src_ptr += src_stride * 3;
- dst_ptr += dst_stride;
- ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width);
- src_ptr += src_stride * 3;
- dst_ptr += dst_stride;
- ScaleRowDown38_2(src_ptr, filter_stride, dst_ptr, dst_width);
- src_ptr += src_stride * 2;
- dst_ptr += dst_stride;
- }
- // Remainder 1 or 2 rows with last row vertically unfiltered
- if ((dst_height % 3) == 2) {
- ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width);
- src_ptr += src_stride * 3;
- dst_ptr += dst_stride;
- ScaleRowDown38_3(src_ptr, 0, dst_ptr, dst_width);
- } else if ((dst_height % 3) == 1) {
- ScaleRowDown38_3(src_ptr, 0, dst_ptr, dst_width);
- }
- }
- static void ScalePlaneDown38_16(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- int src_stride,
- int dst_stride,
- const uint16_t* src_ptr,
- uint16_t* dst_ptr,
- enum FilterMode filtering) {
- int y;
- void (*ScaleRowDown38_3)(const uint16_t* src_ptr, ptrdiff_t src_stride,
- uint16_t* dst_ptr, int dst_width);
- void (*ScaleRowDown38_2)(const uint16_t* src_ptr, ptrdiff_t src_stride,
- uint16_t* dst_ptr, int dst_width);
- const int filter_stride = (filtering == kFilterLinear) ? 0 : src_stride;
- (void)src_width;
- (void)src_height;
- assert(dst_width % 3 == 0);
- if (!filtering) {
- ScaleRowDown38_3 = ScaleRowDown38_16_C;
- ScaleRowDown38_2 = ScaleRowDown38_16_C;
- } else {
- ScaleRowDown38_3 = ScaleRowDown38_3_Box_16_C;
- ScaleRowDown38_2 = ScaleRowDown38_2_Box_16_C;
- }
- #if defined(HAS_SCALEROWDOWN38_16_NEON)
- if (TestCpuFlag(kCpuHasNEON) && (dst_width % 12 == 0)) {
- if (!filtering) {
- ScaleRowDown38_3 = ScaleRowDown38_16_NEON;
- ScaleRowDown38_2 = ScaleRowDown38_16_NEON;
- } else {
- ScaleRowDown38_3 = ScaleRowDown38_3_Box_16_NEON;
- ScaleRowDown38_2 = ScaleRowDown38_2_Box_16_NEON;
- }
- }
- #endif
- #if defined(HAS_SCALEROWDOWN38_16_SSSE3)
- if (TestCpuFlag(kCpuHasSSSE3) && (dst_width % 24 == 0)) {
- if (!filtering) {
- ScaleRowDown38_3 = ScaleRowDown38_16_SSSE3;
- ScaleRowDown38_2 = ScaleRowDown38_16_SSSE3;
- } else {
- ScaleRowDown38_3 = ScaleRowDown38_3_Box_16_SSSE3;
- ScaleRowDown38_2 = ScaleRowDown38_2_Box_16_SSSE3;
- }
- }
- #endif
- for (y = 0; y < dst_height - 2; y += 3) {
- ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width);
- src_ptr += src_stride * 3;
- dst_ptr += dst_stride;
- ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width);
- src_ptr += src_stride * 3;
- dst_ptr += dst_stride;
- ScaleRowDown38_2(src_ptr, filter_stride, dst_ptr, dst_width);
- src_ptr += src_stride * 2;
- dst_ptr += dst_stride;
- }
- // Remainder 1 or 2 rows with last row vertically unfiltered
- if ((dst_height % 3) == 2) {
- ScaleRowDown38_3(src_ptr, filter_stride, dst_ptr, dst_width);
- src_ptr += src_stride * 3;
- dst_ptr += dst_stride;
- ScaleRowDown38_3(src_ptr, 0, dst_ptr, dst_width);
- } else if ((dst_height % 3) == 1) {
- ScaleRowDown38_3(src_ptr, 0, dst_ptr, dst_width);
- }
- }
- #define MIN1(x) ((x) < 1 ? 1 : (x))
- static __inline uint32_t SumPixels(int iboxwidth, const uint16_t* src_ptr) {
- uint32_t sum = 0u;
- int x;
- assert(iboxwidth > 0);
- for (x = 0; x < iboxwidth; ++x) {
- sum += src_ptr[x];
- }
- return sum;
- }
- static __inline uint32_t SumPixels_16(int iboxwidth, const uint32_t* src_ptr) {
- uint32_t sum = 0u;
- int x;
- assert(iboxwidth > 0);
- for (x = 0; x < iboxwidth; ++x) {
- sum += src_ptr[x];
- }
- return sum;
- }
- static void ScaleAddCols2_C(int dst_width,
- int boxheight,
- int x,
- int dx,
- const uint16_t* src_ptr,
- uint8_t* dst_ptr) {
- #ifdef __clang_analyzer__
- *dst_ptr = 0;
- #else
- int i;
- int scaletbl[2];
- int minboxwidth = dx >> 16;
- int boxwidth;
- scaletbl[0] = 65536 / (MIN1(minboxwidth) * boxheight);
- scaletbl[1] = 65536 / (MIN1(minboxwidth + 1) * boxheight);
- for (i = 0; i < dst_width; ++i) {
- int ix = x >> 16;
- x += dx;
- boxwidth = MIN1((x >> 16) - ix);
- *dst_ptr++ =
- SumPixels(boxwidth, src_ptr + ix) * scaletbl[boxwidth - minboxwidth] >>
- 16;
- }
- #endif
- }
- static void ScaleAddCols2_16_C(int dst_width,
- int boxheight,
- int x,
- int dx,
- const uint32_t* src_ptr,
- uint16_t* dst_ptr) {
- #ifdef __clang_analyzer__
- * dst_ptr = 0;
- #else
- int i;
- int scaletbl[2];
- int minboxwidth = dx >> 16;
- int boxwidth;
- scaletbl[0] = 65536 / (MIN1(minboxwidth) * boxheight);
- scaletbl[1] = 65536 / (MIN1(minboxwidth + 1) * boxheight);
- for (i = 0; i < dst_width; ++i) {
- int ix = x >> 16;
- x += dx;
- boxwidth = MIN1((x >> 16) - ix);
- *dst_ptr++ = SumPixels_16(boxwidth, src_ptr + ix) *
- scaletbl[boxwidth - minboxwidth] >>
- 16;
- }
- #endif
- }
- static void ScaleAddCols0_C(int dst_width,
- int boxheight,
- int x,
- int dx,
- const uint16_t* src_ptr,
- uint8_t* dst_ptr) {
- int scaleval = 65536 / boxheight;
- int i;
- (void)dx;
- src_ptr += (x >> 16);
- for (i = 0; i < dst_width; ++i) {
- *dst_ptr++ = src_ptr[i] * scaleval >> 16;
- }
- }
- static void ScaleAddCols1_C(int dst_width,
- int boxheight,
- int x,
- int dx,
- const uint16_t* src_ptr,
- uint8_t* dst_ptr) {
- int boxwidth = MIN1(dx >> 16);
- int scaleval = 65536 / (boxwidth * boxheight);
- int i;
- x >>= 16;
- for (i = 0; i < dst_width; ++i) {
- *dst_ptr++ = SumPixels(boxwidth, src_ptr + x) * scaleval >> 16;
- x += boxwidth;
- }
- }
- static void ScaleAddCols1_16_C(int dst_width,
- int boxheight,
- int x,
- int dx,
- const uint32_t* src_ptr,
- uint16_t* dst_ptr) {
- int boxwidth = MIN1(dx >> 16);
- int scaleval = 65536 / (boxwidth * boxheight);
- int i;
- for (i = 0; i < dst_width; ++i) {
- *dst_ptr++ = SumPixels_16(boxwidth, src_ptr + x) * scaleval >> 16;
- x += boxwidth;
- }
- }
- // Scale plane down to any dimensions, with interpolation.
- // (boxfilter).
- //
- // Same method as SimpleScale, which is fixed point, outputting
- // one pixel of destination using fixed point (16.16) to step
- // through source, sampling a box of pixel with simple
- // averaging.
- static void ScalePlaneBox(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- int src_stride,
- int dst_stride,
- const uint8_t* src_ptr,
- uint8_t* dst_ptr) {
- int j, k;
- // Initial source x/y coordinate and step values as 16.16 fixed point.
- int x = 0;
- int y = 0;
- int dx = 0;
- int dy = 0;
- const int max_y = (src_height << 16);
- ScaleSlope(src_width, src_height, dst_width, dst_height, kFilterBox, &x, &y,
- &dx, &dy);
- src_width = Abs(src_width);
- {
- // Allocate a row buffer of uint16_t.
- align_buffer_64(row16, src_width * 2);
- void (*ScaleAddCols)(int dst_width, int boxheight, int x, int dx,
- const uint16_t* src_ptr, uint8_t* dst_ptr) =
- (dx & 0xffff) ? ScaleAddCols2_C
- : ((dx != 0x10000) ? ScaleAddCols1_C : ScaleAddCols0_C);
- void (*ScaleAddRow)(const uint8_t* src_ptr, uint16_t* dst_ptr,
- int src_width) = ScaleAddRow_C;
- #if defined(HAS_SCALEADDROW_SSE2)
- if (TestCpuFlag(kCpuHasSSE2)) {
- ScaleAddRow = ScaleAddRow_Any_SSE2;
- if (IS_ALIGNED(src_width, 16)) {
- ScaleAddRow = ScaleAddRow_SSE2;
- }
- }
- #endif
- #if defined(HAS_SCALEADDROW_AVX2)
- if (TestCpuFlag(kCpuHasAVX2)) {
- ScaleAddRow = ScaleAddRow_Any_AVX2;
- if (IS_ALIGNED(src_width, 32)) {
- ScaleAddRow = ScaleAddRow_AVX2;
- }
- }
- #endif
- #if defined(HAS_SCALEADDROW_NEON)
- if (TestCpuFlag(kCpuHasNEON)) {
- ScaleAddRow = ScaleAddRow_Any_NEON;
- if (IS_ALIGNED(src_width, 16)) {
- ScaleAddRow = ScaleAddRow_NEON;
- }
- }
- #endif
- #if defined(HAS_SCALEADDROW_MSA)
- if (TestCpuFlag(kCpuHasMSA)) {
- ScaleAddRow = ScaleAddRow_Any_MSA;
- if (IS_ALIGNED(src_width, 16)) {
- ScaleAddRow = ScaleAddRow_MSA;
- }
- }
- #endif
- #if defined(HAS_SCALEADDROW_MMI)
- if (TestCpuFlag(kCpuHasMMI)) {
- ScaleAddRow = ScaleAddRow_Any_MMI;
- if (IS_ALIGNED(src_width, 8)) {
- ScaleAddRow = ScaleAddRow_MMI;
- }
- }
- #endif
- for (j = 0; j < dst_height; ++j) {
- int boxheight;
- int iy = y >> 16;
- const uint8_t* src = src_ptr + iy * src_stride;
- y += dy;
- if (y > max_y) {
- y = max_y;
- }
- boxheight = MIN1((y >> 16) - iy);
- memset(row16, 0, src_width * 2);
- for (k = 0; k < boxheight; ++k) {
- ScaleAddRow(src, (uint16_t*)(row16), src_width);
- src += src_stride;
- }
- ScaleAddCols(dst_width, boxheight, x, dx, (uint16_t*)(row16), dst_ptr);
- dst_ptr += dst_stride;
- }
- free_aligned_buffer_64(row16);
- }
- }
- static void ScalePlaneBox_16(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- int src_stride,
- int dst_stride,
- const uint16_t* src_ptr,
- uint16_t* dst_ptr) {
- int j, k;
- // Initial source x/y coordinate and step values as 16.16 fixed point.
- int x = 0;
- int y = 0;
- int dx = 0;
- int dy = 0;
- const int max_y = (src_height << 16);
- ScaleSlope(src_width, src_height, dst_width, dst_height, kFilterBox, &x, &y,
- &dx, &dy);
- src_width = Abs(src_width);
- {
- // Allocate a row buffer of uint32_t.
- align_buffer_64(row32, src_width * 4);
- void (*ScaleAddCols)(int dst_width, int boxheight, int x, int dx,
- const uint32_t* src_ptr, uint16_t* dst_ptr) =
- (dx & 0xffff) ? ScaleAddCols2_16_C : ScaleAddCols1_16_C;
- void (*ScaleAddRow)(const uint16_t* src_ptr, uint32_t* dst_ptr,
- int src_width) = ScaleAddRow_16_C;
- #if defined(HAS_SCALEADDROW_16_SSE2)
- if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(src_width, 16)) {
- ScaleAddRow = ScaleAddRow_16_SSE2;
- }
- #endif
- #if defined(HAS_SCALEADDROW_16_MMI)
- if (TestCpuFlag(kCpuHasMMI) && IS_ALIGNED(src_width, 4)) {
- ScaleAddRow = ScaleAddRow_16_MMI;
- }
- #endif
- for (j = 0; j < dst_height; ++j) {
- int boxheight;
- int iy = y >> 16;
- const uint16_t* src = src_ptr + iy * src_stride;
- y += dy;
- if (y > max_y) {
- y = max_y;
- }
- boxheight = MIN1((y >> 16) - iy);
- memset(row32, 0, src_width * 4);
- for (k = 0; k < boxheight; ++k) {
- ScaleAddRow(src, (uint32_t*)(row32), src_width);
- src += src_stride;
- }
- ScaleAddCols(dst_width, boxheight, x, dx, (uint32_t*)(row32), dst_ptr);
- dst_ptr += dst_stride;
- }
- free_aligned_buffer_64(row32);
- }
- }
- // Scale plane down with bilinear interpolation.
- void ScalePlaneBilinearDown(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- int src_stride,
- int dst_stride,
- const uint8_t* src_ptr,
- uint8_t* dst_ptr,
- enum FilterMode filtering) {
- // Initial source x/y coordinate and step values as 16.16 fixed point.
- int x = 0;
- int y = 0;
- int dx = 0;
- int dy = 0;
- // TODO(fbarchard): Consider not allocating row buffer for kFilterLinear.
- // Allocate a row buffer.
- align_buffer_64(row, src_width);
- const int max_y = (src_height - 1) << 16;
- int j;
- void (*ScaleFilterCols)(uint8_t * dst_ptr, const uint8_t* src_ptr,
- int dst_width, int x, int dx) =
- (src_width >= 32768) ? ScaleFilterCols64_C : ScaleFilterCols_C;
- void (*InterpolateRow)(uint8_t * dst_ptr, const uint8_t* src_ptr,
- ptrdiff_t src_stride, int dst_width,
- int source_y_fraction) = InterpolateRow_C;
- ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y,
- &dx, &dy);
- src_width = Abs(src_width);
- #if defined(HAS_INTERPOLATEROW_SSSE3)
- if (TestCpuFlag(kCpuHasSSSE3)) {
- InterpolateRow = InterpolateRow_Any_SSSE3;
- if (IS_ALIGNED(src_width, 16)) {
- InterpolateRow = InterpolateRow_SSSE3;
- }
- }
- #endif
- #if defined(HAS_INTERPOLATEROW_AVX2)
- if (TestCpuFlag(kCpuHasAVX2)) {
- InterpolateRow = InterpolateRow_Any_AVX2;
- if (IS_ALIGNED(src_width, 32)) {
- InterpolateRow = InterpolateRow_AVX2;
- }
- }
- #endif
- #if defined(HAS_INTERPOLATEROW_NEON)
- if (TestCpuFlag(kCpuHasNEON)) {
- InterpolateRow = InterpolateRow_Any_NEON;
- if (IS_ALIGNED(src_width, 16)) {
- InterpolateRow = InterpolateRow_NEON;
- }
- }
- #endif
- #if defined(HAS_INTERPOLATEROW_MSA)
- if (TestCpuFlag(kCpuHasMSA)) {
- InterpolateRow = InterpolateRow_Any_MSA;
- if (IS_ALIGNED(src_width, 32)) {
- InterpolateRow = InterpolateRow_MSA;
- }
- }
- #endif
- #if defined(HAS_INTERPOLATEROW_MMI)
- if (TestCpuFlag(kCpuHasMMI)) {
- InterpolateRow = InterpolateRow_Any_MMI;
- if (IS_ALIGNED(src_width, 16)) {
- InterpolateRow = InterpolateRow_MMI;
- }
- }
- #endif
- #if defined(HAS_SCALEFILTERCOLS_SSSE3)
- if (TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) {
- ScaleFilterCols = ScaleFilterCols_SSSE3;
- }
- #endif
- #if defined(HAS_SCALEFILTERCOLS_NEON)
- if (TestCpuFlag(kCpuHasNEON) && src_width < 32768) {
- ScaleFilterCols = ScaleFilterCols_Any_NEON;
- if (IS_ALIGNED(dst_width, 8)) {
- ScaleFilterCols = ScaleFilterCols_NEON;
- }
- }
- #endif
- #if defined(HAS_SCALEFILTERCOLS_MSA)
- if (TestCpuFlag(kCpuHasMSA) && src_width < 32768) {
- ScaleFilterCols = ScaleFilterCols_Any_MSA;
- if (IS_ALIGNED(dst_width, 16)) {
- ScaleFilterCols = ScaleFilterCols_MSA;
- }
- }
- #endif
- if (y > max_y) {
- y = max_y;
- }
- for (j = 0; j < dst_height; ++j) {
- int yi = y >> 16;
- const uint8_t* src = src_ptr + yi * src_stride;
- if (filtering == kFilterLinear) {
- ScaleFilterCols(dst_ptr, src, dst_width, x, dx);
- } else {
- int yf = (y >> 8) & 255;
- InterpolateRow(row, src, src_stride, src_width, yf);
- ScaleFilterCols(dst_ptr, row, dst_width, x, dx);
- }
- dst_ptr += dst_stride;
- y += dy;
- if (y > max_y) {
- y = max_y;
- }
- }
- free_aligned_buffer_64(row);
- }
- void ScalePlaneBilinearDown_16(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- int src_stride,
- int dst_stride,
- const uint16_t* src_ptr,
- uint16_t* dst_ptr,
- enum FilterMode filtering) {
- // Initial source x/y coordinate and step values as 16.16 fixed point.
- int x = 0;
- int y = 0;
- int dx = 0;
- int dy = 0;
- // TODO(fbarchard): Consider not allocating row buffer for kFilterLinear.
- // Allocate a row buffer.
- align_buffer_64(row, src_width * 2);
- const int max_y = (src_height - 1) << 16;
- int j;
- void (*ScaleFilterCols)(uint16_t * dst_ptr, const uint16_t* src_ptr,
- int dst_width, int x, int dx) =
- (src_width >= 32768) ? ScaleFilterCols64_16_C : ScaleFilterCols_16_C;
- void (*InterpolateRow)(uint16_t * dst_ptr, const uint16_t* src_ptr,
- ptrdiff_t src_stride, int dst_width,
- int source_y_fraction) = InterpolateRow_16_C;
- ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y,
- &dx, &dy);
- src_width = Abs(src_width);
- #if defined(HAS_INTERPOLATEROW_16_SSE2)
- if (TestCpuFlag(kCpuHasSSE2)) {
- InterpolateRow = InterpolateRow_Any_16_SSE2;
- if (IS_ALIGNED(src_width, 16)) {
- InterpolateRow = InterpolateRow_16_SSE2;
- }
- }
- #endif
- #if defined(HAS_INTERPOLATEROW_16_SSSE3)
- if (TestCpuFlag(kCpuHasSSSE3)) {
- InterpolateRow = InterpolateRow_Any_16_SSSE3;
- if (IS_ALIGNED(src_width, 16)) {
- InterpolateRow = InterpolateRow_16_SSSE3;
- }
- }
- #endif
- #if defined(HAS_INTERPOLATEROW_16_AVX2)
- if (TestCpuFlag(kCpuHasAVX2)) {
- InterpolateRow = InterpolateRow_Any_16_AVX2;
- if (IS_ALIGNED(src_width, 32)) {
- InterpolateRow = InterpolateRow_16_AVX2;
- }
- }
- #endif
- #if defined(HAS_INTERPOLATEROW_16_NEON)
- if (TestCpuFlag(kCpuHasNEON)) {
- InterpolateRow = InterpolateRow_Any_16_NEON;
- if (IS_ALIGNED(src_width, 16)) {
- InterpolateRow = InterpolateRow_16_NEON;
- }
- }
- #endif
- #if defined(HAS_SCALEFILTERCOLS_16_SSSE3)
- if (TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) {
- ScaleFilterCols = ScaleFilterCols_16_SSSE3;
- }
- #endif
- if (y > max_y) {
- y = max_y;
- }
- for (j = 0; j < dst_height; ++j) {
- int yi = y >> 16;
- const uint16_t* src = src_ptr + yi * src_stride;
- if (filtering == kFilterLinear) {
- ScaleFilterCols(dst_ptr, src, dst_width, x, dx);
- } else {
- int yf = (y >> 8) & 255;
- InterpolateRow((uint16_t*)row, src, src_stride, src_width, yf);
- ScaleFilterCols(dst_ptr, (uint16_t*)row, dst_width, x, dx);
- }
- dst_ptr += dst_stride;
- y += dy;
- if (y > max_y) {
- y = max_y;
- }
- }
- free_aligned_buffer_64(row);
- }
- // Scale up down with bilinear interpolation.
- void ScalePlaneBilinearUp(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- int src_stride,
- int dst_stride,
- const uint8_t* src_ptr,
- uint8_t* dst_ptr,
- enum FilterMode filtering) {
- int j;
- // Initial source x/y coordinate and step values as 16.16 fixed point.
- int x = 0;
- int y = 0;
- int dx = 0;
- int dy = 0;
- const int max_y = (src_height - 1) << 16;
- void (*InterpolateRow)(uint8_t * dst_ptr, const uint8_t* src_ptr,
- ptrdiff_t src_stride, int dst_width,
- int source_y_fraction) = InterpolateRow_C;
- void (*ScaleFilterCols)(uint8_t * dst_ptr, const uint8_t* src_ptr,
- int dst_width, int x, int dx) =
- filtering ? ScaleFilterCols_C : ScaleCols_C;
- ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y,
- &dx, &dy);
- src_width = Abs(src_width);
- #if defined(HAS_INTERPOLATEROW_SSSE3)
- if (TestCpuFlag(kCpuHasSSSE3)) {
- InterpolateRow = InterpolateRow_Any_SSSE3;
- if (IS_ALIGNED(dst_width, 16)) {
- InterpolateRow = InterpolateRow_SSSE3;
- }
- }
- #endif
- #if defined(HAS_INTERPOLATEROW_AVX2)
- if (TestCpuFlag(kCpuHasAVX2)) {
- InterpolateRow = InterpolateRow_Any_AVX2;
- if (IS_ALIGNED(dst_width, 32)) {
- InterpolateRow = InterpolateRow_AVX2;
- }
- }
- #endif
- #if defined(HAS_INTERPOLATEROW_NEON)
- if (TestCpuFlag(kCpuHasNEON)) {
- InterpolateRow = InterpolateRow_Any_NEON;
- if (IS_ALIGNED(dst_width, 16)) {
- InterpolateRow = InterpolateRow_NEON;
- }
- }
- #endif
- if (filtering && src_width >= 32768) {
- ScaleFilterCols = ScaleFilterCols64_C;
- }
- #if defined(HAS_SCALEFILTERCOLS_SSSE3)
- if (filtering && TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) {
- ScaleFilterCols = ScaleFilterCols_SSSE3;
- }
- #endif
- #if defined(HAS_SCALEFILTERCOLS_NEON)
- if (filtering && TestCpuFlag(kCpuHasNEON) && src_width < 32768) {
- ScaleFilterCols = ScaleFilterCols_Any_NEON;
- if (IS_ALIGNED(dst_width, 8)) {
- ScaleFilterCols = ScaleFilterCols_NEON;
- }
- }
- #endif
- #if defined(HAS_SCALEFILTERCOLS_MSA)
- if (filtering && TestCpuFlag(kCpuHasMSA) && src_width < 32768) {
- ScaleFilterCols = ScaleFilterCols_Any_MSA;
- if (IS_ALIGNED(dst_width, 16)) {
- ScaleFilterCols = ScaleFilterCols_MSA;
- }
- }
- #endif
- if (!filtering && src_width * 2 == dst_width && x < 0x8000) {
- ScaleFilterCols = ScaleColsUp2_C;
- #if defined(HAS_SCALECOLS_SSE2)
- if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) {
- ScaleFilterCols = ScaleColsUp2_SSE2;
- }
- #endif
- #if defined(HAS_SCALECOLS_MMI)
- if (TestCpuFlag(kCpuHasMMI) && IS_ALIGNED(dst_width, 8)) {
- ScaleFilterCols = ScaleColsUp2_MMI;
- }
- #endif
- }
- if (y > max_y) {
- y = max_y;
- }
- {
- int yi = y >> 16;
- const uint8_t* src = src_ptr + yi * src_stride;
- // Allocate 2 row buffers.
- const int kRowSize = (dst_width + 31) & ~31;
- align_buffer_64(row, kRowSize * 2);
- uint8_t* rowptr = row;
- int rowstride = kRowSize;
- int lasty = yi;
- ScaleFilterCols(rowptr, src, dst_width, x, dx);
- if (src_height > 1) {
- src += src_stride;
- }
- ScaleFilterCols(rowptr + rowstride, src, dst_width, x, dx);
- src += src_stride;
- for (j = 0; j < dst_height; ++j) {
- yi = y >> 16;
- if (yi != lasty) {
- if (y > max_y) {
- y = max_y;
- yi = y >> 16;
- src = src_ptr + yi * src_stride;
- }
- if (yi != lasty) {
- ScaleFilterCols(rowptr, src, dst_width, x, dx);
- rowptr += rowstride;
- rowstride = -rowstride;
- lasty = yi;
- src += src_stride;
- }
- }
- if (filtering == kFilterLinear) {
- InterpolateRow(dst_ptr, rowptr, 0, dst_width, 0);
- } else {
- int yf = (y >> 8) & 255;
- InterpolateRow(dst_ptr, rowptr, rowstride, dst_width, yf);
- }
- dst_ptr += dst_stride;
- y += dy;
- }
- free_aligned_buffer_64(row);
- }
- }
- void ScalePlaneBilinearUp_16(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- int src_stride,
- int dst_stride,
- const uint16_t* src_ptr,
- uint16_t* dst_ptr,
- enum FilterMode filtering) {
- int j;
- // Initial source x/y coordinate and step values as 16.16 fixed point.
- int x = 0;
- int y = 0;
- int dx = 0;
- int dy = 0;
- const int max_y = (src_height - 1) << 16;
- void (*InterpolateRow)(uint16_t * dst_ptr, const uint16_t* src_ptr,
- ptrdiff_t src_stride, int dst_width,
- int source_y_fraction) = InterpolateRow_16_C;
- void (*ScaleFilterCols)(uint16_t * dst_ptr, const uint16_t* src_ptr,
- int dst_width, int x, int dx) =
- filtering ? ScaleFilterCols_16_C : ScaleCols_16_C;
- ScaleSlope(src_width, src_height, dst_width, dst_height, filtering, &x, &y,
- &dx, &dy);
- src_width = Abs(src_width);
- #if defined(HAS_INTERPOLATEROW_16_SSE2)
- if (TestCpuFlag(kCpuHasSSE2)) {
- InterpolateRow = InterpolateRow_Any_16_SSE2;
- if (IS_ALIGNED(dst_width, 16)) {
- InterpolateRow = InterpolateRow_16_SSE2;
- }
- }
- #endif
- #if defined(HAS_INTERPOLATEROW_16_SSSE3)
- if (TestCpuFlag(kCpuHasSSSE3)) {
- InterpolateRow = InterpolateRow_Any_16_SSSE3;
- if (IS_ALIGNED(dst_width, 16)) {
- InterpolateRow = InterpolateRow_16_SSSE3;
- }
- }
- #endif
- #if defined(HAS_INTERPOLATEROW_16_AVX2)
- if (TestCpuFlag(kCpuHasAVX2)) {
- InterpolateRow = InterpolateRow_Any_16_AVX2;
- if (IS_ALIGNED(dst_width, 32)) {
- InterpolateRow = InterpolateRow_16_AVX2;
- }
- }
- #endif
- #if defined(HAS_INTERPOLATEROW_16_NEON)
- if (TestCpuFlag(kCpuHasNEON)) {
- InterpolateRow = InterpolateRow_Any_16_NEON;
- if (IS_ALIGNED(dst_width, 16)) {
- InterpolateRow = InterpolateRow_16_NEON;
- }
- }
- #endif
- if (filtering && src_width >= 32768) {
- ScaleFilterCols = ScaleFilterCols64_16_C;
- }
- #if defined(HAS_SCALEFILTERCOLS_16_SSSE3)
- if (filtering && TestCpuFlag(kCpuHasSSSE3) && src_width < 32768) {
- ScaleFilterCols = ScaleFilterCols_16_SSSE3;
- }
- #endif
- if (!filtering && src_width * 2 == dst_width && x < 0x8000) {
- ScaleFilterCols = ScaleColsUp2_16_C;
- #if defined(HAS_SCALECOLS_16_SSE2)
- if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) {
- ScaleFilterCols = ScaleColsUp2_16_SSE2;
- }
- #endif
- #if defined(HAS_SCALECOLS_16_MMI)
- if (TestCpuFlag(kCpuHasMMI) && IS_ALIGNED(dst_width, 8)) {
- ScaleFilterCols = ScaleColsUp2_16_MMI;
- }
- #endif
- }
- if (y > max_y) {
- y = max_y;
- }
- {
- int yi = y >> 16;
- const uint16_t* src = src_ptr + yi * src_stride;
- // Allocate 2 row buffers.
- const int kRowSize = (dst_width + 31) & ~31;
- align_buffer_64(row, kRowSize * 4);
- uint16_t* rowptr = (uint16_t*)row;
- int rowstride = kRowSize;
- int lasty = yi;
- ScaleFilterCols(rowptr, src, dst_width, x, dx);
- if (src_height > 1) {
- src += src_stride;
- }
- ScaleFilterCols(rowptr + rowstride, src, dst_width, x, dx);
- src += src_stride;
- for (j = 0; j < dst_height; ++j) {
- yi = y >> 16;
- if (yi != lasty) {
- if (y > max_y) {
- y = max_y;
- yi = y >> 16;
- src = src_ptr + yi * src_stride;
- }
- if (yi != lasty) {
- ScaleFilterCols(rowptr, src, dst_width, x, dx);
- rowptr += rowstride;
- rowstride = -rowstride;
- lasty = yi;
- src += src_stride;
- }
- }
- if (filtering == kFilterLinear) {
- InterpolateRow(dst_ptr, rowptr, 0, dst_width, 0);
- } else {
- int yf = (y >> 8) & 255;
- InterpolateRow(dst_ptr, rowptr, rowstride, dst_width, yf);
- }
- dst_ptr += dst_stride;
- y += dy;
- }
- free_aligned_buffer_64(row);
- }
- }
- // Scale Plane to/from any dimensions, without interpolation.
- // Fixed point math is used for performance: The upper 16 bits
- // of x and dx is the integer part of the source position and
- // the lower 16 bits are the fixed decimal part.
- static void ScalePlaneSimple(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- int src_stride,
- int dst_stride,
- const uint8_t* src_ptr,
- uint8_t* dst_ptr) {
- int i;
- void (*ScaleCols)(uint8_t * dst_ptr, const uint8_t* src_ptr, int dst_width,
- int x, int dx) = ScaleCols_C;
- // Initial source x/y coordinate and step values as 16.16 fixed point.
- int x = 0;
- int y = 0;
- int dx = 0;
- int dy = 0;
- ScaleSlope(src_width, src_height, dst_width, dst_height, kFilterNone, &x, &y,
- &dx, &dy);
- src_width = Abs(src_width);
- if (src_width * 2 == dst_width && x < 0x8000) {
- ScaleCols = ScaleColsUp2_C;
- #if defined(HAS_SCALECOLS_SSE2)
- if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) {
- ScaleCols = ScaleColsUp2_SSE2;
- }
- #endif
- #if defined(HAS_SCALECOLS_MMI)
- if (TestCpuFlag(kCpuHasMMI) && IS_ALIGNED(dst_width, 8)) {
- ScaleCols = ScaleColsUp2_MMI;
- }
- #endif
- }
- for (i = 0; i < dst_height; ++i) {
- ScaleCols(dst_ptr, src_ptr + (y >> 16) * src_stride, dst_width, x, dx);
- dst_ptr += dst_stride;
- y += dy;
- }
- }
- static void ScalePlaneSimple_16(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- int src_stride,
- int dst_stride,
- const uint16_t* src_ptr,
- uint16_t* dst_ptr) {
- int i;
- void (*ScaleCols)(uint16_t * dst_ptr, const uint16_t* src_ptr, int dst_width,
- int x, int dx) = ScaleCols_16_C;
- // Initial source x/y coordinate and step values as 16.16 fixed point.
- int x = 0;
- int y = 0;
- int dx = 0;
- int dy = 0;
- ScaleSlope(src_width, src_height, dst_width, dst_height, kFilterNone, &x, &y,
- &dx, &dy);
- src_width = Abs(src_width);
- if (src_width * 2 == dst_width && x < 0x8000) {
- ScaleCols = ScaleColsUp2_16_C;
- #if defined(HAS_SCALECOLS_16_SSE2)
- if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(dst_width, 8)) {
- ScaleCols = ScaleColsUp2_16_SSE2;
- }
- #endif
- #if defined(HAS_SCALECOLS_16_MMI)
- if (TestCpuFlag(kCpuHasMMI) && IS_ALIGNED(dst_width, 8)) {
- ScaleCols = ScaleColsUp2_16_MMI;
- }
- #endif
- }
- for (i = 0; i < dst_height; ++i) {
- ScaleCols(dst_ptr, src_ptr + (y >> 16) * src_stride, dst_width, x, dx);
- dst_ptr += dst_stride;
- y += dy;
- }
- }
- // Scale a plane.
- // This function dispatches to a specialized scaler based on scale factor.
- LIBYUV_API
- void ScalePlane(const uint8_t* src,
- int src_stride,
- int src_width,
- int src_height,
- uint8_t* dst,
- int dst_stride,
- int dst_width,
- int dst_height,
- enum FilterMode filtering) {
- // Simplify filtering when possible.
- filtering = ScaleFilterReduce(src_width, src_height, dst_width, dst_height,
- filtering);
- // Negative height means invert the image.
- if (src_height < 0) {
- src_height = -src_height;
- src = src + (src_height - 1) * src_stride;
- src_stride = -src_stride;
- }
- // Use specialized scales to improve performance for common resolutions.
- // For example, all the 1/2 scalings will use ScalePlaneDown2()
- if (dst_width == src_width && dst_height == src_height) {
- // Straight copy.
- CopyPlane(src, src_stride, dst, dst_stride, dst_width, dst_height);
- return;
- }
- if (dst_width == src_width && filtering != kFilterBox) {
- int dy = FixedDiv(src_height, dst_height);
- // Arbitrary scale vertically, but unscaled horizontally.
- ScalePlaneVertical(src_height, dst_width, dst_height, src_stride,
- dst_stride, src, dst, 0, 0, dy, 1, filtering);
- return;
- }
- if (dst_width <= Abs(src_width) && dst_height <= src_height) {
- // Scale down.
- if (4 * dst_width == 3 * src_width && 4 * dst_height == 3 * src_height) {
- // optimized, 3/4
- ScalePlaneDown34(src_width, src_height, dst_width, dst_height, src_stride,
- dst_stride, src, dst, filtering);
- return;
- }
- if (2 * dst_width == src_width && 2 * dst_height == src_height) {
- // optimized, 1/2
- ScalePlaneDown2(src_width, src_height, dst_width, dst_height, src_stride,
- dst_stride, src, dst, filtering);
- return;
- }
- // 3/8 rounded up for odd sized chroma height.
- if (8 * dst_width == 3 * src_width && 8 * dst_height == 3 * src_height) {
- // optimized, 3/8
- ScalePlaneDown38(src_width, src_height, dst_width, dst_height, src_stride,
- dst_stride, src, dst, filtering);
- return;
- }
- if (4 * dst_width == src_width && 4 * dst_height == src_height &&
- (filtering == kFilterBox || filtering == kFilterNone)) {
- // optimized, 1/4
- ScalePlaneDown4(src_width, src_height, dst_width, dst_height, src_stride,
- dst_stride, src, dst, filtering);
- return;
- }
- }
- if (filtering == kFilterBox && dst_height * 2 < src_height) {
- ScalePlaneBox(src_width, src_height, dst_width, dst_height, src_stride,
- dst_stride, src, dst);
- return;
- }
- if (filtering && dst_height > src_height) {
- ScalePlaneBilinearUp(src_width, src_height, dst_width, dst_height,
- src_stride, dst_stride, src, dst, filtering);
- return;
- }
- if (filtering) {
- ScalePlaneBilinearDown(src_width, src_height, dst_width, dst_height,
- src_stride, dst_stride, src, dst, filtering);
- return;
- }
- ScalePlaneSimple(src_width, src_height, dst_width, dst_height, src_stride,
- dst_stride, src, dst);
- }
- LIBYUV_API
- void ScalePlane_16(const uint16_t* src,
- int src_stride,
- int src_width,
- int src_height,
- uint16_t* dst,
- int dst_stride,
- int dst_width,
- int dst_height,
- enum FilterMode filtering) {
- // Simplify filtering when possible.
- filtering = ScaleFilterReduce(src_width, src_height, dst_width, dst_height,
- filtering);
- // Negative height means invert the image.
- if (src_height < 0) {
- src_height = -src_height;
- src = src + (src_height - 1) * src_stride;
- src_stride = -src_stride;
- }
- // Use specialized scales to improve performance for common resolutions.
- // For example, all the 1/2 scalings will use ScalePlaneDown2()
- if (dst_width == src_width && dst_height == src_height) {
- // Straight copy.
- CopyPlane_16(src, src_stride, dst, dst_stride, dst_width, dst_height);
- return;
- }
- if (dst_width == src_width && filtering != kFilterBox) {
- int dy = FixedDiv(src_height, dst_height);
- // Arbitrary scale vertically, but unscaled vertically.
- ScalePlaneVertical_16(src_height, dst_width, dst_height, src_stride,
- dst_stride, src, dst, 0, 0, dy, 1, filtering);
- return;
- }
- if (dst_width <= Abs(src_width) && dst_height <= src_height) {
- // Scale down.
- if (4 * dst_width == 3 * src_width && 4 * dst_height == 3 * src_height) {
- // optimized, 3/4
- ScalePlaneDown34_16(src_width, src_height, dst_width, dst_height,
- src_stride, dst_stride, src, dst, filtering);
- return;
- }
- if (2 * dst_width == src_width && 2 * dst_height == src_height) {
- // optimized, 1/2
- ScalePlaneDown2_16(src_width, src_height, dst_width, dst_height,
- src_stride, dst_stride, src, dst, filtering);
- return;
- }
- // 3/8 rounded up for odd sized chroma height.
- if (8 * dst_width == 3 * src_width && 8 * dst_height == 3 * src_height) {
- // optimized, 3/8
- ScalePlaneDown38_16(src_width, src_height, dst_width, dst_height,
- src_stride, dst_stride, src, dst, filtering);
- return;
- }
- if (4 * dst_width == src_width && 4 * dst_height == src_height &&
- (filtering == kFilterBox || filtering == kFilterNone)) {
- // optimized, 1/4
- ScalePlaneDown4_16(src_width, src_height, dst_width, dst_height,
- src_stride, dst_stride, src, dst, filtering);
- return;
- }
- }
- if (filtering == kFilterBox && dst_height * 2 < src_height) {
- ScalePlaneBox_16(src_width, src_height, dst_width, dst_height, src_stride,
- dst_stride, src, dst);
- return;
- }
- if (filtering && dst_height > src_height) {
- ScalePlaneBilinearUp_16(src_width, src_height, dst_width, dst_height,
- src_stride, dst_stride, src, dst, filtering);
- return;
- }
- if (filtering) {
- ScalePlaneBilinearDown_16(src_width, src_height, dst_width, dst_height,
- src_stride, dst_stride, src, dst, filtering);
- return;
- }
- ScalePlaneSimple_16(src_width, src_height, dst_width, dst_height, src_stride,
- dst_stride, src, dst);
- }
- // Scale an I420 image.
- // This function in turn calls a scaling function for each plane.
- LIBYUV_API
- int I420Scale(const uint8_t* src_y,
- int src_stride_y,
- const uint8_t* src_u,
- int src_stride_u,
- const uint8_t* src_v,
- int src_stride_v,
- int src_width,
- int src_height,
- uint8_t* dst_y,
- int dst_stride_y,
- uint8_t* dst_u,
- int dst_stride_u,
- uint8_t* dst_v,
- int dst_stride_v,
- int dst_width,
- int dst_height,
- enum FilterMode filtering) {
- int src_halfwidth = SUBSAMPLE(src_width, 1, 1);
- int src_halfheight = SUBSAMPLE(src_height, 1, 1);
- int dst_halfwidth = SUBSAMPLE(dst_width, 1, 1);
- int dst_halfheight = SUBSAMPLE(dst_height, 1, 1);
- if (!src_y || !src_u || !src_v || src_width == 0 || src_height == 0 ||
- src_width > 32768 || src_height > 32768 || !dst_y || !dst_u || !dst_v ||
- dst_width <= 0 || dst_height <= 0) {
- return -1;
- }
- ScalePlane(src_y, src_stride_y, src_width, src_height, dst_y, dst_stride_y,
- dst_width, dst_height, filtering);
- ScalePlane(src_u, src_stride_u, src_halfwidth, src_halfheight, dst_u,
- dst_stride_u, dst_halfwidth, dst_halfheight, filtering);
- ScalePlane(src_v, src_stride_v, src_halfwidth, src_halfheight, dst_v,
- dst_stride_v, dst_halfwidth, dst_halfheight, filtering);
- return 0;
- }
- LIBYUV_API
- int I420Scale_16(const uint16_t* src_y,
- int src_stride_y,
- const uint16_t* src_u,
- int src_stride_u,
- const uint16_t* src_v,
- int src_stride_v,
- int src_width,
- int src_height,
- uint16_t* dst_y,
- int dst_stride_y,
- uint16_t* dst_u,
- int dst_stride_u,
- uint16_t* dst_v,
- int dst_stride_v,
- int dst_width,
- int dst_height,
- enum FilterMode filtering) {
- int src_halfwidth = SUBSAMPLE(src_width, 1, 1);
- int src_halfheight = SUBSAMPLE(src_height, 1, 1);
- int dst_halfwidth = SUBSAMPLE(dst_width, 1, 1);
- int dst_halfheight = SUBSAMPLE(dst_height, 1, 1);
- if (!src_y || !src_u || !src_v || src_width == 0 || src_height == 0 ||
- src_width > 32768 || src_height > 32768 || !dst_y || !dst_u || !dst_v ||
- dst_width <= 0 || dst_height <= 0) {
- return -1;
- }
- ScalePlane_16(src_y, src_stride_y, src_width, src_height, dst_y, dst_stride_y,
- dst_width, dst_height, filtering);
- ScalePlane_16(src_u, src_stride_u, src_halfwidth, src_halfheight, dst_u,
- dst_stride_u, dst_halfwidth, dst_halfheight, filtering);
- ScalePlane_16(src_v, src_stride_v, src_halfwidth, src_halfheight, dst_v,
- dst_stride_v, dst_halfwidth, dst_halfheight, filtering);
- return 0;
- }
- // Scale an I444 image.
- // This function in turn calls a scaling function for each plane.
- LIBYUV_API
- int I444Scale(const uint8_t* src_y,
- int src_stride_y,
- const uint8_t* src_u,
- int src_stride_u,
- const uint8_t* src_v,
- int src_stride_v,
- int src_width,
- int src_height,
- uint8_t* dst_y,
- int dst_stride_y,
- uint8_t* dst_u,
- int dst_stride_u,
- uint8_t* dst_v,
- int dst_stride_v,
- int dst_width,
- int dst_height,
- enum FilterMode filtering) {
- if (!src_y || !src_u || !src_v || src_width == 0 || src_height == 0 ||
- src_width > 32768 || src_height > 32768 || !dst_y || !dst_u || !dst_v ||
- dst_width <= 0 || dst_height <= 0) {
- return -1;
- }
- ScalePlane(src_y, src_stride_y, src_width, src_height, dst_y, dst_stride_y,
- dst_width, dst_height, filtering);
- ScalePlane(src_u, src_stride_u, src_width, src_height, dst_u, dst_stride_u,
- dst_width, dst_height, filtering);
- ScalePlane(src_v, src_stride_v, src_width, src_height, dst_v, dst_stride_v,
- dst_width, dst_height, filtering);
- return 0;
- }
- LIBYUV_API
- int I444Scale_16(const uint16_t* src_y,
- int src_stride_y,
- const uint16_t* src_u,
- int src_stride_u,
- const uint16_t* src_v,
- int src_stride_v,
- int src_width,
- int src_height,
- uint16_t* dst_y,
- int dst_stride_y,
- uint16_t* dst_u,
- int dst_stride_u,
- uint16_t* dst_v,
- int dst_stride_v,
- int dst_width,
- int dst_height,
- enum FilterMode filtering) {
- if (!src_y || !src_u || !src_v || src_width == 0 || src_height == 0 ||
- src_width > 32768 || src_height > 32768 || !dst_y || !dst_u || !dst_v ||
- dst_width <= 0 || dst_height <= 0) {
- return -1;
- }
- ScalePlane_16(src_y, src_stride_y, src_width, src_height, dst_y, dst_stride_y,
- dst_width, dst_height, filtering);
- ScalePlane_16(src_u, src_stride_u, src_width, src_height, dst_u, dst_stride_u,
- dst_width, dst_height, filtering);
- ScalePlane_16(src_v, src_stride_v, src_width, src_height, dst_v, dst_stride_v,
- dst_width, dst_height, filtering);
- return 0;
- }
- // Deprecated api
- LIBYUV_API
- int Scale(const uint8_t* src_y,
- const uint8_t* src_u,
- const uint8_t* src_v,
- int src_stride_y,
- int src_stride_u,
- int src_stride_v,
- int src_width,
- int src_height,
- uint8_t* dst_y,
- uint8_t* dst_u,
- uint8_t* dst_v,
- int dst_stride_y,
- int dst_stride_u,
- int dst_stride_v,
- int dst_width,
- int dst_height,
- LIBYUV_BOOL interpolate) {
- return I420Scale(src_y, src_stride_y, src_u, src_stride_u, src_v,
- src_stride_v, src_width, src_height, dst_y, dst_stride_y,
- dst_u, dst_stride_u, dst_v, dst_stride_v, dst_width,
- dst_height, interpolate ? kFilterBox : kFilterNone);
- }
- #ifdef __cplusplus
- } // extern "C"
- } // namespace libyuv
- #endif
|