vf_waveform.c 155 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209
  1. /*
  2. * Copyright (c) 2012-2016 Paul B Mahol
  3. * Copyright (c) 2013 Marton Balint
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * FFmpeg is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #include "libavutil/avassert.h"
  22. #include "libavutil/opt.h"
  23. #include "libavutil/parseutils.h"
  24. #include "libavutil/pixdesc.h"
  25. #include "libavutil/xga_font_data.h"
  26. #include "avfilter.h"
  27. #include "formats.h"
  28. #include "internal.h"
  29. #include "video.h"
  30. typedef struct ThreadData {
  31. AVFrame *in;
  32. AVFrame *out;
  33. int component;
  34. int offset_y;
  35. int offset_x;
  36. } ThreadData;
  37. enum FilterType {
  38. LOWPASS,
  39. FLAT,
  40. AFLAT,
  41. CHROMA,
  42. COLOR,
  43. ACOLOR,
  44. XFLAT,
  45. NB_FILTERS
  46. };
  47. enum DisplayType {
  48. OVERLAY,
  49. STACK,
  50. PARADE,
  51. NB_DISPLAYS
  52. };
  53. enum ScaleType {
  54. DIGITAL,
  55. MILLIVOLTS,
  56. IRE,
  57. NB_SCALES
  58. };
  59. typedef struct GraticuleLine {
  60. const char *name;
  61. uint16_t pos;
  62. } GraticuleLine;
  63. typedef struct GraticuleLines {
  64. struct GraticuleLine line[4];
  65. } GraticuleLines;
  66. typedef struct WaveformContext {
  67. const AVClass *class;
  68. int mode;
  69. int acomp;
  70. int dcomp;
  71. int ncomp;
  72. int pcomp;
  73. uint8_t bg_color[4];
  74. float fintensity;
  75. int intensity;
  76. int mirror;
  77. int display;
  78. int envelope;
  79. int graticule;
  80. float opacity;
  81. float bgopacity;
  82. int estart[4];
  83. int eend[4];
  84. int *emax[4][4];
  85. int *emin[4][4];
  86. int *peak;
  87. int filter;
  88. int flags;
  89. int bits;
  90. int max;
  91. int size;
  92. int scale;
  93. uint8_t grat_yuva_color[4];
  94. int shift_w[4], shift_h[4];
  95. GraticuleLines *glines;
  96. int nb_glines;
  97. int rgb;
  98. int (*waveform_slice)(AVFilterContext *ctx, void *arg,
  99. int jobnr, int nb_jobs);
  100. void (*graticulef)(struct WaveformContext *s, AVFrame *out);
  101. const AVPixFmtDescriptor *desc;
  102. const AVPixFmtDescriptor *odesc;
  103. } WaveformContext;
  104. #define OFFSET(x) offsetof(WaveformContext, x)
  105. #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
  106. static const AVOption waveform_options[] = {
  107. { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "mode" },
  108. { "m", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "mode" },
  109. { "row", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" },
  110. { "column", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode" },
  111. { "intensity", "set intensity", OFFSET(fintensity), AV_OPT_TYPE_FLOAT, {.dbl=0.04}, 0, 1, FLAGS },
  112. { "i", "set intensity", OFFSET(fintensity), AV_OPT_TYPE_FLOAT, {.dbl=0.04}, 0, 1, FLAGS },
  113. { "mirror", "set mirroring", OFFSET(mirror), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
  114. { "r", "set mirroring", OFFSET(mirror), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
  115. { "display", "set display mode", OFFSET(display), AV_OPT_TYPE_INT, {.i64=STACK}, 0, NB_DISPLAYS-1, FLAGS, "display" },
  116. { "d", "set display mode", OFFSET(display), AV_OPT_TYPE_INT, {.i64=STACK}, 0, NB_DISPLAYS-1, FLAGS, "display" },
  117. { "overlay", NULL, 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY}, 0, 0, FLAGS, "display" },
  118. { "stack", NULL, 0, AV_OPT_TYPE_CONST, {.i64=STACK}, 0, 0, FLAGS, "display" },
  119. { "parade", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PARADE}, 0, 0, FLAGS, "display" },
  120. { "components", "set components to display", OFFSET(pcomp), AV_OPT_TYPE_INT, {.i64=1}, 1, 15, FLAGS },
  121. { "c", "set components to display", OFFSET(pcomp), AV_OPT_TYPE_INT, {.i64=1}, 1, 15, FLAGS },
  122. { "envelope", "set envelope to display", OFFSET(envelope), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "envelope" },
  123. { "e", "set envelope to display", OFFSET(envelope), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "envelope" },
  124. { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "envelope" },
  125. { "instant", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "envelope" },
  126. { "peak", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "envelope" },
  127. { "peak+instant", NULL, 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, FLAGS, "envelope" },
  128. { "filter", "set filter", OFFSET(filter), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_FILTERS-1, FLAGS, "filter" },
  129. { "f", "set filter", OFFSET(filter), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_FILTERS-1, FLAGS, "filter" },
  130. { "lowpass", NULL, 0, AV_OPT_TYPE_CONST, {.i64=LOWPASS}, 0, 0, FLAGS, "filter" },
  131. { "flat" , NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAT}, 0, 0, FLAGS, "filter" },
  132. { "aflat" , NULL, 0, AV_OPT_TYPE_CONST, {.i64=AFLAT}, 0, 0, FLAGS, "filter" },
  133. { "chroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64=CHROMA}, 0, 0, FLAGS, "filter" },
  134. { "color", NULL, 0, AV_OPT_TYPE_CONST, {.i64=COLOR}, 0, 0, FLAGS, "filter" },
  135. { "acolor", NULL, 0, AV_OPT_TYPE_CONST, {.i64=ACOLOR}, 0, 0, FLAGS, "filter" },
  136. { "xflat", NULL, 0, AV_OPT_TYPE_CONST, {.i64=XFLAT}, 0, 0, FLAGS, "filter" },
  137. { "graticule", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "graticule" },
  138. { "g", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "graticule" },
  139. { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "graticule" },
  140. { "green", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "graticule" },
  141. { "orange", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "graticule" },
  142. { "opacity", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS },
  143. { "o", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS },
  144. { "flags", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=1}, 0, 3, FLAGS, "flags" },
  145. { "fl", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=1}, 0, 3, FLAGS, "flags" },
  146. { "numbers", "draw numbers", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "flags" },
  147. { "dots", "draw dots instead of lines", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "flags" },
  148. { "scale", "set scale", OFFSET(scale), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_SCALES-1, FLAGS, "scale" },
  149. { "s", "set scale", OFFSET(scale), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_SCALES-1, FLAGS, "scale" },
  150. { "digital", NULL, 0, AV_OPT_TYPE_CONST, {.i64=DIGITAL}, 0, 0, FLAGS, "scale" },
  151. { "millivolts", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MILLIVOLTS}, 0, 0, FLAGS, "scale" },
  152. { "ire", NULL, 0, AV_OPT_TYPE_CONST, {.i64=IRE}, 0, 0, FLAGS, "scale" },
  153. { "bgopacity", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS },
  154. { "b", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS },
  155. { NULL }
  156. };
  157. AVFILTER_DEFINE_CLASS(waveform);
  158. static const enum AVPixelFormat in_lowpass_pix_fmts[] = {
  159. AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP,
  160. AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12,
  161. AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P,
  162. AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P,
  163. AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P,
  164. AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUVJ420P,
  165. AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P,
  166. AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA420P,
  167. AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12,
  168. AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV420P9,
  169. AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA420P9,
  170. AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10,
  171. AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA420P10,
  172. AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV440P12,
  173. AV_PIX_FMT_NONE
  174. };
  175. static const enum AVPixelFormat in_color_pix_fmts[] = {
  176. AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP,
  177. AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12,
  178. AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P,
  179. AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P,
  180. AV_PIX_FMT_YUV411P,
  181. AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUVJ420P,
  182. AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P,
  183. AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA420P,
  184. AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV420P9,
  185. AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA420P9,
  186. AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10,
  187. AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA420P10,
  188. AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV440P12,
  189. AV_PIX_FMT_NONE
  190. };
  191. static const enum AVPixelFormat in_flat_pix_fmts[] = {
  192. AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P,
  193. AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P,
  194. AV_PIX_FMT_YUV411P,
  195. AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUVJ420P,
  196. AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P,
  197. AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA420P,
  198. AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV420P9,
  199. AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA420P9,
  200. AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10,
  201. AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA420P10,
  202. AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV440P12,
  203. AV_PIX_FMT_NONE
  204. };
  205. static const enum AVPixelFormat out_rgb8_lowpass_pix_fmts[] = {
  206. AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP,
  207. AV_PIX_FMT_NONE
  208. };
  209. static const enum AVPixelFormat out_rgb9_lowpass_pix_fmts[] = {
  210. AV_PIX_FMT_GBRP9,
  211. AV_PIX_FMT_NONE
  212. };
  213. static const enum AVPixelFormat out_rgb10_lowpass_pix_fmts[] = {
  214. AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10,
  215. AV_PIX_FMT_NONE
  216. };
  217. static const enum AVPixelFormat out_rgb12_lowpass_pix_fmts[] = {
  218. AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12,
  219. AV_PIX_FMT_NONE
  220. };
  221. static const enum AVPixelFormat out_yuv8_lowpass_pix_fmts[] = {
  222. AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVA444P,
  223. AV_PIX_FMT_NONE
  224. };
  225. static const enum AVPixelFormat out_yuv9_lowpass_pix_fmts[] = {
  226. AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUVA444P9,
  227. AV_PIX_FMT_NONE
  228. };
  229. static const enum AVPixelFormat out_yuv10_lowpass_pix_fmts[] = {
  230. AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUVA444P10,
  231. AV_PIX_FMT_NONE
  232. };
  233. static const enum AVPixelFormat out_yuv12_lowpass_pix_fmts[] = {
  234. AV_PIX_FMT_YUV444P12,
  235. AV_PIX_FMT_NONE
  236. };
  237. static const enum AVPixelFormat out_gray8_lowpass_pix_fmts[] = {
  238. AV_PIX_FMT_GRAY8,
  239. AV_PIX_FMT_NONE
  240. };
  241. static const enum AVPixelFormat out_gray9_lowpass_pix_fmts[] = {
  242. AV_PIX_FMT_GRAY9,
  243. AV_PIX_FMT_NONE
  244. };
  245. static const enum AVPixelFormat out_gray10_lowpass_pix_fmts[] = {
  246. AV_PIX_FMT_GRAY10,
  247. AV_PIX_FMT_NONE
  248. };
  249. static const enum AVPixelFormat out_gray12_lowpass_pix_fmts[] = {
  250. AV_PIX_FMT_GRAY12,
  251. AV_PIX_FMT_NONE
  252. };
  253. static const enum AVPixelFormat flat_pix_fmts[] = {
  254. AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P,
  255. AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV444P10,
  256. AV_PIX_FMT_YUV444P12,
  257. AV_PIX_FMT_NONE
  258. };
  259. static int query_formats(AVFilterContext *ctx)
  260. {
  261. WaveformContext *s = ctx->priv;
  262. const enum AVPixelFormat *out_pix_fmts;
  263. const enum AVPixelFormat *in_pix_fmts;
  264. const AVPixFmtDescriptor *desc;
  265. AVFilterFormats *avff;
  266. int depth, rgb, i, ret, ncomp;
  267. if (!ctx->inputs[0]->in_formats ||
  268. !ctx->inputs[0]->in_formats->nb_formats) {
  269. return AVERROR(EAGAIN);
  270. }
  271. switch (s->filter) {
  272. case LOWPASS: in_pix_fmts = in_lowpass_pix_fmts; break;
  273. case CHROMA:
  274. case XFLAT:
  275. case AFLAT:
  276. case FLAT: in_pix_fmts = in_flat_pix_fmts; break;
  277. case ACOLOR:
  278. case COLOR: in_pix_fmts = in_color_pix_fmts; break;
  279. default: return AVERROR_BUG;
  280. }
  281. if (!ctx->inputs[0]->out_formats) {
  282. if ((ret = ff_formats_ref(ff_make_format_list(in_pix_fmts), &ctx->inputs[0]->out_formats)) < 0)
  283. return ret;
  284. }
  285. avff = ctx->inputs[0]->in_formats;
  286. desc = av_pix_fmt_desc_get(avff->formats[0]);
  287. ncomp = desc->nb_components;
  288. rgb = desc->flags & AV_PIX_FMT_FLAG_RGB;
  289. depth = desc->comp[0].depth;
  290. for (i = 1; i < avff->nb_formats; i++) {
  291. desc = av_pix_fmt_desc_get(avff->formats[i]);
  292. if (rgb != (desc->flags & AV_PIX_FMT_FLAG_RGB) ||
  293. depth != desc->comp[0].depth)
  294. return AVERROR(EAGAIN);
  295. }
  296. if (s->filter == LOWPASS && ncomp == 1 && depth == 8)
  297. out_pix_fmts = out_gray8_lowpass_pix_fmts;
  298. else if (s->filter == LOWPASS && ncomp == 1 && depth == 9)
  299. out_pix_fmts = out_gray9_lowpass_pix_fmts;
  300. else if (s->filter == LOWPASS && ncomp == 1 && depth == 10)
  301. out_pix_fmts = out_gray10_lowpass_pix_fmts;
  302. else if (s->filter == LOWPASS && ncomp == 1 && depth == 12)
  303. out_pix_fmts = out_gray12_lowpass_pix_fmts;
  304. else if (rgb && depth == 8 && ncomp > 2)
  305. out_pix_fmts = out_rgb8_lowpass_pix_fmts;
  306. else if (rgb && depth == 9 && ncomp > 2)
  307. out_pix_fmts = out_rgb9_lowpass_pix_fmts;
  308. else if (rgb && depth == 10 && ncomp > 2)
  309. out_pix_fmts = out_rgb10_lowpass_pix_fmts;
  310. else if (rgb && depth == 12 && ncomp > 2)
  311. out_pix_fmts = out_rgb12_lowpass_pix_fmts;
  312. else if (depth == 8 && ncomp > 2)
  313. out_pix_fmts = out_yuv8_lowpass_pix_fmts;
  314. else if (depth == 9 && ncomp > 2)
  315. out_pix_fmts = out_yuv9_lowpass_pix_fmts;
  316. else if (depth == 10 && ncomp > 2)
  317. out_pix_fmts = out_yuv10_lowpass_pix_fmts;
  318. else if (depth == 12 && ncomp > 2)
  319. out_pix_fmts = out_yuv12_lowpass_pix_fmts;
  320. else
  321. return AVERROR(EAGAIN);
  322. if ((ret = ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->in_formats)) < 0)
  323. return ret;
  324. return 0;
  325. }
  326. static void envelope_instant16(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
  327. {
  328. const int dst_linesize = out->linesize[component] / 2;
  329. const int bg = s->bg_color[component] * (s->max / 256);
  330. const int limit = s->max - 1;
  331. const int dst_h = s->display == PARADE ? out->height / s->acomp : out->height;
  332. const int dst_w = s->display == PARADE ? out->width / s->acomp : out->width;
  333. const int start = s->estart[plane];
  334. const int end = s->eend[plane];
  335. uint16_t *dst;
  336. int x, y;
  337. if (s->mode) {
  338. for (x = offset; x < offset + dst_w; x++) {
  339. for (y = start; y < end; y++) {
  340. dst = (uint16_t *)out->data[component] + y * dst_linesize + x;
  341. if (dst[0] != bg) {
  342. dst[0] = limit;
  343. break;
  344. }
  345. }
  346. for (y = end - 1; y >= start; y--) {
  347. dst = (uint16_t *)out->data[component] + y * dst_linesize + x;
  348. if (dst[0] != bg) {
  349. dst[0] = limit;
  350. break;
  351. }
  352. }
  353. }
  354. } else {
  355. for (y = offset; y < offset + dst_h; y++) {
  356. dst = (uint16_t *)out->data[component] + y * dst_linesize;
  357. for (x = start; x < end; x++) {
  358. if (dst[x] != bg) {
  359. dst[x] = limit;
  360. break;
  361. }
  362. }
  363. for (x = end - 1; x >= start; x--) {
  364. if (dst[x] != bg) {
  365. dst[x] = limit;
  366. break;
  367. }
  368. }
  369. }
  370. }
  371. }
  372. static void envelope_instant(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
  373. {
  374. const int dst_linesize = out->linesize[component];
  375. const uint8_t bg = s->bg_color[component];
  376. const int dst_h = s->display == PARADE ? out->height / s->acomp : out->height;
  377. const int dst_w = s->display == PARADE ? out->width / s->acomp : out->width;
  378. const int start = s->estart[plane];
  379. const int end = s->eend[plane];
  380. uint8_t *dst;
  381. int x, y;
  382. if (s->mode) {
  383. for (x = offset; x < offset + dst_w; x++) {
  384. for (y = start; y < end; y++) {
  385. dst = out->data[component] + y * dst_linesize + x;
  386. if (dst[0] != bg) {
  387. dst[0] = 255;
  388. break;
  389. }
  390. }
  391. for (y = end - 1; y >= start; y--) {
  392. dst = out->data[component] + y * dst_linesize + x;
  393. if (dst[0] != bg) {
  394. dst[0] = 255;
  395. break;
  396. }
  397. }
  398. }
  399. } else {
  400. for (y = offset; y < offset + dst_h; y++) {
  401. dst = out->data[component] + y * dst_linesize;
  402. for (x = start; x < end; x++) {
  403. if (dst[x] != bg) {
  404. dst[x] = 255;
  405. break;
  406. }
  407. }
  408. for (x = end - 1; x >= start; x--) {
  409. if (dst[x] != bg) {
  410. dst[x] = 255;
  411. break;
  412. }
  413. }
  414. }
  415. }
  416. }
  417. static void envelope_peak16(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
  418. {
  419. const int dst_linesize = out->linesize[component] / 2;
  420. const int bg = s->bg_color[component] * (s->max / 256);
  421. const int limit = s->max - 1;
  422. const int dst_h = s->display == PARADE ? out->height / s->acomp : out->height;
  423. const int dst_w = s->display == PARADE ? out->width / s->acomp : out->width;
  424. const int start = s->estart[plane];
  425. const int end = s->eend[plane];
  426. int *emax = s->emax[plane][component];
  427. int *emin = s->emin[plane][component];
  428. uint16_t *dst;
  429. int x, y;
  430. if (s->mode) {
  431. for (x = offset; x < offset + dst_w; x++) {
  432. for (y = start; y < end && y < emin[x - offset]; y++) {
  433. dst = (uint16_t *)out->data[component] + y * dst_linesize + x;
  434. if (dst[0] != bg) {
  435. emin[x - offset] = y;
  436. break;
  437. }
  438. }
  439. for (y = end - 1; y >= start && y >= emax[x - offset]; y--) {
  440. dst = (uint16_t *)out->data[component] + y * dst_linesize + x;
  441. if (dst[0] != bg) {
  442. emax[x - offset] = y;
  443. break;
  444. }
  445. }
  446. }
  447. if (s->envelope == 3)
  448. envelope_instant16(s, out, plane, component, offset);
  449. for (x = offset; x < offset + dst_w; x++) {
  450. dst = (uint16_t *)out->data[component] + emin[x - offset] * dst_linesize + x;
  451. dst[0] = limit;
  452. dst = (uint16_t *)out->data[component] + emax[x - offset] * dst_linesize + x;
  453. dst[0] = limit;
  454. }
  455. } else {
  456. for (y = offset; y < offset + dst_h; y++) {
  457. dst = (uint16_t *)out->data[component] + y * dst_linesize;
  458. for (x = start; x < end && x < emin[y - offset]; x++) {
  459. if (dst[x] != bg) {
  460. emin[y - offset] = x;
  461. break;
  462. }
  463. }
  464. for (x = end - 1; x >= start && x >= emax[y - offset]; x--) {
  465. if (dst[x] != bg) {
  466. emax[y - offset] = x;
  467. break;
  468. }
  469. }
  470. }
  471. if (s->envelope == 3)
  472. envelope_instant16(s, out, plane, component, offset);
  473. for (y = offset; y < offset + dst_h; y++) {
  474. dst = (uint16_t *)out->data[component] + y * dst_linesize + emin[y - offset];
  475. dst[0] = limit;
  476. dst = (uint16_t *)out->data[component] + y * dst_linesize + emax[y - offset];
  477. dst[0] = limit;
  478. }
  479. }
  480. }
  481. static void envelope_peak(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
  482. {
  483. const int dst_linesize = out->linesize[component];
  484. const int bg = s->bg_color[component];
  485. const int dst_h = s->display == PARADE ? out->height / s->acomp : out->height;
  486. const int dst_w = s->display == PARADE ? out->width / s->acomp : out->width;
  487. const int start = s->estart[plane];
  488. const int end = s->eend[plane];
  489. int *emax = s->emax[plane][component];
  490. int *emin = s->emin[plane][component];
  491. uint8_t *dst;
  492. int x, y;
  493. if (s->mode) {
  494. for (x = offset; x < offset + dst_w; x++) {
  495. for (y = start; y < end && y < emin[x - offset]; y++) {
  496. dst = out->data[component] + y * dst_linesize + x;
  497. if (dst[0] != bg) {
  498. emin[x - offset] = y;
  499. break;
  500. }
  501. }
  502. for (y = end - 1; y >= start && y >= emax[x - offset]; y--) {
  503. dst = out->data[component] + y * dst_linesize + x;
  504. if (dst[0] != bg) {
  505. emax[x - offset] = y;
  506. break;
  507. }
  508. }
  509. }
  510. if (s->envelope == 3)
  511. envelope_instant(s, out, plane, component, offset);
  512. for (x = offset; x < offset + dst_w; x++) {
  513. dst = out->data[component] + emin[x - offset] * dst_linesize + x;
  514. dst[0] = 255;
  515. dst = out->data[component] + emax[x - offset] * dst_linesize + x;
  516. dst[0] = 255;
  517. }
  518. } else {
  519. for (y = offset; y < offset + dst_h; y++) {
  520. dst = out->data[component] + y * dst_linesize;
  521. for (x = start; x < end && x < emin[y - offset]; x++) {
  522. if (dst[x] != bg) {
  523. emin[y - offset] = x;
  524. break;
  525. }
  526. }
  527. for (x = end - 1; x >= start && x >= emax[y - offset]; x--) {
  528. if (dst[x] != bg) {
  529. emax[y - offset] = x;
  530. break;
  531. }
  532. }
  533. }
  534. if (s->envelope == 3)
  535. envelope_instant(s, out, plane, component, offset);
  536. for (y = offset; y < offset + dst_h; y++) {
  537. dst = out->data[component] + y * dst_linesize + emin[y - offset];
  538. dst[0] = 255;
  539. dst = out->data[component] + y * dst_linesize + emax[y - offset];
  540. dst[0] = 255;
  541. }
  542. }
  543. }
  544. static void envelope16(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
  545. {
  546. if (s->envelope == 0) {
  547. return;
  548. } else if (s->envelope == 1) {
  549. envelope_instant16(s, out, plane, component, offset);
  550. } else {
  551. envelope_peak16(s, out, plane, component, offset);
  552. }
  553. }
  554. static void envelope(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
  555. {
  556. if (s->envelope == 0) {
  557. return;
  558. } else if (s->envelope == 1) {
  559. envelope_instant(s, out, plane, component, offset);
  560. } else {
  561. envelope_peak(s, out, plane, component, offset);
  562. }
  563. }
  564. static void update16(uint16_t *target, int max, int intensity, int limit)
  565. {
  566. if (*target <= max)
  567. *target += intensity;
  568. else
  569. *target = limit;
  570. }
  571. static void update(uint8_t *target, int max, int intensity)
  572. {
  573. if (*target <= max)
  574. *target += intensity;
  575. else
  576. *target = 255;
  577. }
  578. static void update_cr(uint8_t *target, int unused, int intensity)
  579. {
  580. if (*target - intensity > 0)
  581. *target -= intensity;
  582. else
  583. *target = 0;
  584. }
  585. static void update16_cr(uint16_t *target, int unused, int intensity, int limit)
  586. {
  587. if (*target - intensity > 0)
  588. *target -= intensity;
  589. else
  590. *target = 0;
  591. }
  592. static av_always_inline void lowpass16(WaveformContext *s,
  593. AVFrame *in, AVFrame *out,
  594. int component, int intensity,
  595. int offset_y, int offset_x,
  596. int column, int mirror,
  597. int jobnr, int nb_jobs)
  598. {
  599. const int plane = s->desc->comp[component].plane;
  600. const int shift_w = s->shift_w[component];
  601. const int shift_h = s->shift_h[component];
  602. const int src_linesize = in->linesize[plane] / 2;
  603. const int dst_linesize = out->linesize[plane] / 2;
  604. const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1);
  605. const int limit = s->max - 1;
  606. const int max = limit - intensity;
  607. const int src_h = AV_CEIL_RSHIFT(in->height, shift_h);
  608. const int src_w = AV_CEIL_RSHIFT(in->width, shift_w);
  609. const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
  610. const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
  611. const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
  612. const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
  613. const int step = column ? 1 << shift_w : 1 << shift_h;
  614. const uint16_t *src_data = (const uint16_t *)in->data[plane] + sliceh_start * src_linesize;
  615. uint16_t *dst_data = (uint16_t *)out->data[plane] + (offset_y + sliceh_start * step) * dst_linesize + offset_x;
  616. uint16_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1);
  617. uint16_t * const dst_line = (mirror ? dst_bottom_line : dst_data);
  618. const uint16_t *p;
  619. int y;
  620. if (!column && mirror)
  621. dst_data += s->size;
  622. for (y = sliceh_start; y < sliceh_end; y++) {
  623. const uint16_t *src_data_end = src_data + slicew_end;
  624. uint16_t *dst = dst_line + slicew_start * step;
  625. for (p = src_data + slicew_start; p < src_data_end; p++) {
  626. uint16_t *target;
  627. int i = 0, v = FFMIN(*p, limit);
  628. if (column) {
  629. do {
  630. target = dst++ + dst_signed_linesize * v;
  631. update16(target, max, intensity, limit);
  632. } while (++i < step);
  633. } else {
  634. uint16_t *row = dst_data;
  635. do {
  636. if (mirror)
  637. target = row - v - 1;
  638. else
  639. target = row + v;
  640. update16(target, max, intensity, limit);
  641. row += dst_linesize;
  642. } while (++i < step);
  643. }
  644. }
  645. src_data += src_linesize;
  646. dst_data += dst_linesize * step;
  647. }
  648. }
  649. #define LOWPASS16_FUNC(name, column, mirror) \
  650. static int lowpass16_##name(AVFilterContext *ctx, \
  651. void *arg, int jobnr, \
  652. int nb_jobs) \
  653. { \
  654. WaveformContext *s = ctx->priv; \
  655. ThreadData *td = arg; \
  656. AVFrame *in = td->in; \
  657. AVFrame *out = td->out; \
  658. int component = td->component; \
  659. int offset_y = td->offset_y; \
  660. int offset_x = td->offset_x; \
  661. \
  662. lowpass16(s, in, out, component, s->intensity, \
  663. offset_y, offset_x, column, mirror, \
  664. jobnr, nb_jobs); \
  665. \
  666. return 0; \
  667. }
  668. LOWPASS16_FUNC(column_mirror, 1, 1)
  669. LOWPASS16_FUNC(column, 1, 0)
  670. LOWPASS16_FUNC(row_mirror, 0, 1)
  671. LOWPASS16_FUNC(row, 0, 0)
  672. static av_always_inline void lowpass(WaveformContext *s,
  673. AVFrame *in, AVFrame *out,
  674. int component, int intensity,
  675. int offset_y, int offset_x,
  676. int column, int mirror,
  677. int jobnr, int nb_jobs)
  678. {
  679. const int plane = s->desc->comp[component].plane;
  680. const int shift_w = s->shift_w[component];
  681. const int shift_h = s->shift_h[component];
  682. const int src_linesize = in->linesize[plane];
  683. const int dst_linesize = out->linesize[plane];
  684. const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1);
  685. const int max = 255 - intensity;
  686. const int src_h = AV_CEIL_RSHIFT(in->height, shift_h);
  687. const int src_w = AV_CEIL_RSHIFT(in->width, shift_w);
  688. const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
  689. const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
  690. const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
  691. const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
  692. const int step = column ? 1 << shift_w : 1 << shift_h;
  693. const uint8_t *src_data = in->data[plane] + sliceh_start * src_linesize;
  694. uint8_t *dst_data = out->data[plane] + (offset_y + sliceh_start * step) * dst_linesize + offset_x;
  695. uint8_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1);
  696. uint8_t * const dst_line = (mirror ? dst_bottom_line : dst_data);
  697. const uint8_t *p;
  698. int y;
  699. if (!column && mirror)
  700. dst_data += s->size;
  701. for (y = sliceh_start; y < sliceh_end; y++) {
  702. const uint8_t *src_data_end = src_data + slicew_end;
  703. uint8_t *dst = dst_line + slicew_start * step;
  704. for (p = src_data + slicew_start; p < src_data_end; p++) {
  705. uint8_t *target;
  706. if (column) {
  707. target = dst + dst_signed_linesize * *p;
  708. dst += step;
  709. update(target, max, intensity);
  710. } else {
  711. uint8_t *row = dst_data;
  712. if (mirror)
  713. target = row - *p - 1;
  714. else
  715. target = row + *p;
  716. update(target, max, intensity);
  717. row += dst_linesize;
  718. }
  719. }
  720. src_data += src_linesize;
  721. dst_data += dst_linesize * step;
  722. }
  723. if (column && step > 1) {
  724. const int dst_h = 256;
  725. uint8_t *dst;
  726. int x, z;
  727. dst = out->data[plane] + offset_y * dst_linesize + offset_x;
  728. for (y = 0; y < dst_h; y++) {
  729. for (x = slicew_start * step; x < slicew_end * step; x+=step) {
  730. for (z = 1; z < step; z++) {
  731. dst[x + z] = dst[x];
  732. }
  733. }
  734. dst += dst_linesize;
  735. }
  736. } else if (step > 1) {
  737. const int dst_w = 256;
  738. uint8_t *dst;
  739. int z;
  740. dst = out->data[plane] + (offset_y + sliceh_start * step) * dst_linesize + offset_x;
  741. for (y = sliceh_start * step; y < sliceh_end * step; y+=step) {
  742. for (z = 1; z < step; z++)
  743. memcpy(dst + dst_linesize * z, dst, dst_w);
  744. dst += dst_linesize * step;
  745. }
  746. }
  747. }
  748. #define LOWPASS_FUNC(name, column, mirror) \
  749. static int lowpass_##name(AVFilterContext *ctx, \
  750. void *arg, int jobnr, \
  751. int nb_jobs) \
  752. { \
  753. WaveformContext *s = ctx->priv; \
  754. ThreadData *td = arg; \
  755. AVFrame *in = td->in; \
  756. AVFrame *out = td->out; \
  757. int component = td->component; \
  758. int offset_y = td->offset_y; \
  759. int offset_x = td->offset_x; \
  760. \
  761. lowpass(s, in, out, component, s->intensity, \
  762. offset_y, offset_x, column, mirror, \
  763. jobnr, nb_jobs); \
  764. \
  765. return 0; \
  766. }
  767. LOWPASS_FUNC(column_mirror, 1, 1)
  768. LOWPASS_FUNC(column, 1, 0)
  769. LOWPASS_FUNC(row_mirror, 0, 1)
  770. LOWPASS_FUNC(row, 0, 0)
  771. static av_always_inline void flat16(WaveformContext *s,
  772. AVFrame *in, AVFrame *out,
  773. int component, int intensity,
  774. int offset_y, int offset_x,
  775. int column, int mirror,
  776. int jobnr, int nb_jobs)
  777. {
  778. const int plane = s->desc->comp[component].plane;
  779. const int c0_linesize = in->linesize[ plane + 0 ] / 2;
  780. const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2;
  781. const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2;
  782. const int c0_shift_w = s->shift_w[ component + 0 ];
  783. const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
  784. const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
  785. const int c0_shift_h = s->shift_h[ component + 0 ];
  786. const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
  787. const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
  788. const int d0_linesize = out->linesize[ plane + 0 ] / 2;
  789. const int d1_linesize = out->linesize[(plane + 1) % s->ncomp] / 2;
  790. const int limit = s->max - 1;
  791. const int max = limit - intensity;
  792. const int mid = s->max / 2;
  793. const int src_h = in->height;
  794. const int src_w = in->width;
  795. const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
  796. const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
  797. const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
  798. const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
  799. int x, y;
  800. if (column) {
  801. const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
  802. const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
  803. for (x = slicew_start; x < slicew_end; x++) {
  804. const uint16_t *c0_data = (uint16_t *)in->data[plane + 0];
  805. const uint16_t *c1_data = (uint16_t *)in->data[(plane + 1) % s->ncomp];
  806. const uint16_t *c2_data = (uint16_t *)in->data[(plane + 2) % s->ncomp];
  807. uint16_t *d0_data = (uint16_t *)(out->data[plane]) + offset_y * d0_linesize + offset_x;
  808. uint16_t *d1_data = (uint16_t *)(out->data[(plane + 1) % s->ncomp]) + offset_y * d1_linesize + offset_x;
  809. uint16_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
  810. uint16_t * const d0 = (mirror ? d0_bottom_line : d0_data);
  811. uint16_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
  812. uint16_t * const d1 = (mirror ? d1_bottom_line : d1_data);
  813. for (y = 0; y < src_h; y++) {
  814. const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit) + s->max;
  815. const int c1 = FFMIN(FFABS(c1_data[x >> c1_shift_w] - mid) + FFABS(c2_data[x >> c2_shift_w] - mid), limit);
  816. uint16_t *target;
  817. target = d0 + x + d0_signed_linesize * c0;
  818. update16(target, max, intensity, limit);
  819. target = d1 + x + d1_signed_linesize * (c0 - c1);
  820. update16(target, max, intensity, limit);
  821. target = d1 + x + d1_signed_linesize * (c0 + c1);
  822. update16(target, max, intensity, limit);
  823. if (!c0_shift_h || (y & c0_shift_h))
  824. c0_data += c0_linesize;
  825. if (!c1_shift_h || (y & c1_shift_h))
  826. c1_data += c1_linesize;
  827. if (!c2_shift_h || (y & c2_shift_h))
  828. c2_data += c2_linesize;
  829. d0_data += d0_linesize;
  830. d1_data += d1_linesize;
  831. }
  832. }
  833. } else {
  834. const uint16_t *c0_data = (uint16_t *)(in->data[plane]) + (sliceh_start >> c0_shift_h) * c0_linesize;
  835. const uint16_t *c1_data = (uint16_t *)(in->data[(plane + 1) % s->ncomp]) + (sliceh_start >> c1_shift_h) * c1_linesize;
  836. const uint16_t *c2_data = (uint16_t *)(in->data[(plane + 2) % s->ncomp]) + (sliceh_start >> c2_shift_h) * c2_linesize;
  837. uint16_t *d0_data = (uint16_t *)(out->data[plane]) + (offset_y + sliceh_start) * d0_linesize + offset_x;
  838. uint16_t *d1_data = (uint16_t *)(out->data[(plane + 1) % s->ncomp]) + (offset_y + sliceh_start) * d1_linesize + offset_x;
  839. if (mirror) {
  840. d0_data += s->size - 1;
  841. d1_data += s->size - 1;
  842. }
  843. for (y = sliceh_start; y < sliceh_end; y++) {
  844. for (x = 0; x < src_w; x++) {
  845. const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit) + s->max;
  846. const int c1 = FFMIN(FFABS(c1_data[x >> c1_shift_w] - mid) + FFABS(c2_data[x >> c2_shift_w] - mid), limit);
  847. uint16_t *target;
  848. if (mirror) {
  849. target = d0_data - c0;
  850. update16(target, max, intensity, limit);
  851. target = d1_data - (c0 - c1);
  852. update16(target, max, intensity, limit);
  853. target = d1_data - (c0 + c1);
  854. update16(target, max, intensity, limit);
  855. } else {
  856. target = d0_data + c0;
  857. update16(target, max, intensity, limit);
  858. target = d1_data + (c0 - c1);
  859. update16(target, max, intensity, limit);
  860. target = d1_data + (c0 + c1);
  861. update16(target, max, intensity, limit);
  862. }
  863. }
  864. if (!c0_shift_h || (y & c0_shift_h))
  865. c0_data += c0_linesize;
  866. if (!c1_shift_h || (y & c1_shift_h))
  867. c1_data += c1_linesize;
  868. if (!c2_shift_h || (y & c2_shift_h))
  869. c2_data += c2_linesize;
  870. d0_data += d0_linesize;
  871. d1_data += d1_linesize;
  872. }
  873. }
  874. }
  875. #define FLAT16_FUNC(name, column, mirror) \
  876. static int flat16_##name(AVFilterContext *ctx, \
  877. void *arg, int jobnr, \
  878. int nb_jobs) \
  879. { \
  880. WaveformContext *s = ctx->priv; \
  881. ThreadData *td = arg; \
  882. AVFrame *in = td->in; \
  883. AVFrame *out = td->out; \
  884. int component = td->component; \
  885. int offset_y = td->offset_y; \
  886. int offset_x = td->offset_x; \
  887. \
  888. flat16(s, in, out, component, s->intensity, \
  889. offset_y, offset_x, column, mirror, \
  890. jobnr, nb_jobs); \
  891. \
  892. return 0; \
  893. }
  894. FLAT16_FUNC(column_mirror, 1, 1)
  895. FLAT16_FUNC(column, 1, 0)
  896. FLAT16_FUNC(row_mirror, 0, 1)
  897. FLAT16_FUNC(row, 0, 0)
  898. static av_always_inline void flat(WaveformContext *s,
  899. AVFrame *in, AVFrame *out,
  900. int component, int intensity,
  901. int offset_y, int offset_x,
  902. int column, int mirror,
  903. int jobnr, int nb_jobs)
  904. {
  905. const int plane = s->desc->comp[component].plane;
  906. const int c0_linesize = in->linesize[ plane + 0 ];
  907. const int c1_linesize = in->linesize[(plane + 1) % s->ncomp];
  908. const int c2_linesize = in->linesize[(plane + 2) % s->ncomp];
  909. const int c0_shift_w = s->shift_w[ component + 0 ];
  910. const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
  911. const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
  912. const int c0_shift_h = s->shift_h[ component + 0 ];
  913. const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
  914. const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
  915. const int d0_linesize = out->linesize[ plane + 0 ];
  916. const int d1_linesize = out->linesize[(plane + 1) % s->ncomp];
  917. const int max = 255 - intensity;
  918. const int src_h = in->height;
  919. const int src_w = in->width;
  920. const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
  921. const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
  922. const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
  923. const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
  924. int x, y;
  925. if (column) {
  926. const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
  927. const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
  928. for (x = slicew_start; x < slicew_end; x++) {
  929. const uint8_t *c0_data = in->data[plane + 0];
  930. const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp];
  931. const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp];
  932. uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x;
  933. uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
  934. uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
  935. uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data);
  936. uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
  937. uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data);
  938. for (y = 0; y < src_h; y++) {
  939. const int c0 = c0_data[x >> c0_shift_w] + 256;
  940. const int c1 = FFABS(c1_data[x >> c1_shift_w] - 128) + FFABS(c2_data[x >> c2_shift_w] - 128);
  941. uint8_t *target;
  942. target = d0 + x + d0_signed_linesize * c0;
  943. update(target, max, intensity);
  944. target = d1 + x + d1_signed_linesize * (c0 - c1);
  945. update(target, max, intensity);
  946. target = d1 + x + d1_signed_linesize * (c0 + c1);
  947. update(target, max, intensity);
  948. if (!c0_shift_h || (y & c0_shift_h))
  949. c0_data += c0_linesize;
  950. if (!c1_shift_h || (y & c1_shift_h))
  951. c1_data += c1_linesize;
  952. if (!c2_shift_h || (y & c2_shift_h))
  953. c2_data += c2_linesize;
  954. d0_data += d0_linesize;
  955. d1_data += d1_linesize;
  956. }
  957. }
  958. } else {
  959. const uint8_t *c0_data = in->data[plane] + (sliceh_start >> c0_shift_h) * c0_linesize;
  960. const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp] + (sliceh_start >> c1_shift_h) * c1_linesize;
  961. const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp] + (sliceh_start >> c2_shift_h) * c2_linesize;
  962. uint8_t *d0_data = out->data[plane] + (offset_y + sliceh_start) * d0_linesize + offset_x;
  963. uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + (offset_y + sliceh_start) * d1_linesize + offset_x;
  964. if (mirror) {
  965. d0_data += s->size - 1;
  966. d1_data += s->size - 1;
  967. }
  968. for (y = sliceh_start; y < sliceh_end; y++) {
  969. for (x = 0; x < src_w; x++) {
  970. const int c0 = c0_data[x >> c0_shift_w] + 256;
  971. const int c1 = FFABS(c1_data[x >> c1_shift_w] - 128) + FFABS(c2_data[x >> c2_shift_w] - 128);
  972. uint8_t *target;
  973. if (mirror) {
  974. target = d0_data - c0;
  975. update(target, max, intensity);
  976. target = d1_data - (c0 - c1);
  977. update(target, max, intensity);
  978. target = d1_data - (c0 + c1);
  979. update(target, max, intensity);
  980. } else {
  981. target = d0_data + c0;
  982. update(target, max, intensity);
  983. target = d1_data + (c0 - c1);
  984. update(target, max, intensity);
  985. target = d1_data + (c0 + c1);
  986. update(target, max, intensity);
  987. }
  988. }
  989. if (!c0_shift_h || (y & c0_shift_h))
  990. c0_data += c0_linesize;
  991. if (!c1_shift_h || (y & c1_shift_h))
  992. c1_data += c1_linesize;
  993. if (!c2_shift_h || (y & c2_shift_h))
  994. c2_data += c2_linesize;
  995. d0_data += d0_linesize;
  996. d1_data += d1_linesize;
  997. }
  998. }
  999. }
  1000. #define FLAT_FUNC(name, column, mirror) \
  1001. static int flat_##name(AVFilterContext *ctx, \
  1002. void *arg, int jobnr, \
  1003. int nb_jobs) \
  1004. { \
  1005. WaveformContext *s = ctx->priv; \
  1006. ThreadData *td = arg; \
  1007. AVFrame *in = td->in; \
  1008. AVFrame *out = td->out; \
  1009. int component = td->component; \
  1010. int offset_y = td->offset_y; \
  1011. int offset_x = td->offset_x; \
  1012. \
  1013. flat(s, in, out, component, s->intensity, \
  1014. offset_y, offset_x, column, mirror, \
  1015. jobnr, nb_jobs); \
  1016. \
  1017. return 0; \
  1018. }
  1019. FLAT_FUNC(column_mirror, 1, 1)
  1020. FLAT_FUNC(column, 1, 0)
  1021. FLAT_FUNC(row_mirror, 0, 1)
  1022. FLAT_FUNC(row, 0, 0)
  1023. #define AFLAT16(name, update_cr, column, mirror) \
  1024. static int name(AVFilterContext *ctx, \
  1025. void *arg, int jobnr, \
  1026. int nb_jobs) \
  1027. { \
  1028. WaveformContext *s = ctx->priv; \
  1029. ThreadData *td = arg; \
  1030. AVFrame *in = td->in; \
  1031. AVFrame *out = td->out; \
  1032. int component = td->component; \
  1033. int offset_y = td->offset_y; \
  1034. int offset_x = td->offset_x; \
  1035. const int intensity = s->intensity; \
  1036. const int plane = s->desc->comp[component].plane; \
  1037. const int c0_linesize = in->linesize[ plane + 0 ] / 2; \
  1038. const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2; \
  1039. const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2; \
  1040. const int c0_shift_w = s->shift_w[ component + 0 ]; \
  1041. const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp]; \
  1042. const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp]; \
  1043. const int c0_shift_h = s->shift_h[ component + 0 ]; \
  1044. const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp]; \
  1045. const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp]; \
  1046. const int d0_linesize = out->linesize[ plane + 0 ] / 2; \
  1047. const int d1_linesize = out->linesize[(plane + 1) % s->ncomp] / 2; \
  1048. const int d2_linesize = out->linesize[(plane + 2) % s->ncomp] / 2; \
  1049. const int limit = s->max - 1; \
  1050. const int max = limit - intensity; \
  1051. const int mid = s->max / 2; \
  1052. const int src_h = in->height; \
  1053. const int src_w = in->width; \
  1054. const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0; \
  1055. const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h; \
  1056. const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0; \
  1057. const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w; \
  1058. int x, y; \
  1059. \
  1060. if (column) { \
  1061. const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1); \
  1062. const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1); \
  1063. const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1); \
  1064. \
  1065. for (x = slicew_start; x < slicew_end; x++) { \
  1066. const uint16_t *c0_data = (uint16_t *)in->data[plane + 0]; \
  1067. const uint16_t *c1_data = (uint16_t *)in->data[(plane + 1) % s->ncomp]; \
  1068. const uint16_t *c2_data = (uint16_t *)in->data[(plane + 2) % s->ncomp]; \
  1069. uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x; \
  1070. uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; \
  1071. uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; \
  1072. uint16_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1); \
  1073. uint16_t * const d0 = (mirror ? d0_bottom_line : d0_data); \
  1074. uint16_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1); \
  1075. uint16_t * const d1 = (mirror ? d1_bottom_line : d1_data); \
  1076. uint16_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1); \
  1077. uint16_t * const d2 = (mirror ? d2_bottom_line : d2_data); \
  1078. \
  1079. for (y = 0; y < src_h; y++) { \
  1080. const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit) + mid; \
  1081. const int c1 = FFMIN(c1_data[x >> c1_shift_w], limit) - mid; \
  1082. const int c2 = FFMIN(c2_data[x >> c2_shift_w], limit) - mid; \
  1083. uint16_t *target; \
  1084. \
  1085. target = d0 + x + d0_signed_linesize * c0; \
  1086. update16(target, max, intensity, limit); \
  1087. \
  1088. target = d1 + x + d1_signed_linesize * (c0 + c1); \
  1089. update16(target, max, intensity, limit); \
  1090. \
  1091. target = d2 + x + d2_signed_linesize * (c0 + c2); \
  1092. update_cr(target, max, intensity, limit); \
  1093. \
  1094. if (!c0_shift_h || (y & c0_shift_h)) \
  1095. c0_data += c0_linesize; \
  1096. if (!c1_shift_h || (y & c1_shift_h)) \
  1097. c1_data += c1_linesize; \
  1098. if (!c2_shift_h || (y & c2_shift_h)) \
  1099. c2_data += c2_linesize; \
  1100. d0_data += d0_linesize; \
  1101. d1_data += d1_linesize; \
  1102. d2_data += d2_linesize; \
  1103. } \
  1104. } \
  1105. } else { \
  1106. const uint16_t *c0_data = (uint16_t *)in->data[plane] + (sliceh_start >> c0_shift_h) * c0_linesize; \
  1107. const uint16_t *c1_data = (uint16_t *)in->data[(plane + 1) % s->ncomp] + (sliceh_start >> c1_shift_h) * c1_linesize; \
  1108. const uint16_t *c2_data = (uint16_t *)in->data[(plane + 2) % s->ncomp] + (sliceh_start >> c2_shift_h) * c2_linesize; \
  1109. uint16_t *d0_data = (uint16_t *)out->data[plane] + (offset_y + sliceh_start) * d0_linesize + offset_x; \
  1110. uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + (offset_y + sliceh_start) * d1_linesize + offset_x; \
  1111. uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + (offset_y + sliceh_start) * d2_linesize + offset_x; \
  1112. \
  1113. if (mirror) { \
  1114. d0_data += s->size - 1; \
  1115. d1_data += s->size - 1; \
  1116. d2_data += s->size - 1; \
  1117. } \
  1118. \
  1119. for (y = sliceh_start; y < sliceh_end; y++) { \
  1120. for (x = 0; x < src_w; x++) { \
  1121. const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit) + mid; \
  1122. const int c1 = FFMIN(c1_data[x >> c1_shift_w], limit) - mid; \
  1123. const int c2 = FFMIN(c2_data[x >> c2_shift_w], limit) - mid; \
  1124. uint16_t *target; \
  1125. \
  1126. if (mirror) { \
  1127. target = d0_data - c0; \
  1128. update16(target, max, intensity, limit); \
  1129. target = d1_data - (c0 + c1); \
  1130. update16(target, max, intensity, limit); \
  1131. target = d2_data - (c0 + c2); \
  1132. update_cr(target, max, intensity, limit); \
  1133. } else { \
  1134. target = d0_data + c0; \
  1135. update16(target, max, intensity, limit); \
  1136. target = d1_data + (c0 + c1); \
  1137. update16(target, max, intensity, limit); \
  1138. target = d2_data + (c0 + c2); \
  1139. update_cr(target, max, intensity, limit); \
  1140. } \
  1141. } \
  1142. \
  1143. if (!c0_shift_h || (y & c0_shift_h)) \
  1144. c0_data += c0_linesize; \
  1145. if (!c1_shift_h || (y & c1_shift_h)) \
  1146. c1_data += c1_linesize; \
  1147. if (!c2_shift_h || (y & c2_shift_h)) \
  1148. c2_data += c2_linesize; \
  1149. d0_data += d0_linesize; \
  1150. d1_data += d1_linesize; \
  1151. d2_data += d2_linesize; \
  1152. } \
  1153. } \
  1154. return 0; \
  1155. }
  1156. #define AFLAT(name, update_cr, column, mirror) \
  1157. static int name(AVFilterContext *ctx, \
  1158. void *arg, int jobnr, \
  1159. int nb_jobs) \
  1160. { \
  1161. WaveformContext *s = ctx->priv; \
  1162. ThreadData *td = arg; \
  1163. AVFrame *in = td->in; \
  1164. AVFrame *out = td->out; \
  1165. int component = td->component; \
  1166. int offset_y = td->offset_y; \
  1167. int offset_x = td->offset_x; \
  1168. const int src_h = in->height; \
  1169. const int src_w = in->width; \
  1170. const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0; \
  1171. const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h; \
  1172. const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0; \
  1173. const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w; \
  1174. const int intensity = s->intensity; \
  1175. const int plane = s->desc->comp[component].plane; \
  1176. const int c0_linesize = in->linesize[ plane + 0 ]; \
  1177. const int c1_linesize = in->linesize[(plane + 1) % s->ncomp]; \
  1178. const int c2_linesize = in->linesize[(plane + 2) % s->ncomp]; \
  1179. const int c0_shift_w = s->shift_w[ component + 0 ]; \
  1180. const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp]; \
  1181. const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp]; \
  1182. const int c0_shift_h = s->shift_h[ component + 0 ]; \
  1183. const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp]; \
  1184. const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp]; \
  1185. const int d0_linesize = out->linesize[ plane + 0 ]; \
  1186. const int d1_linesize = out->linesize[(plane + 1) % s->ncomp]; \
  1187. const int d2_linesize = out->linesize[(plane + 2) % s->ncomp]; \
  1188. const int max = 255 - intensity; \
  1189. int x, y; \
  1190. \
  1191. if (column) { \
  1192. const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1); \
  1193. const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1); \
  1194. const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1); \
  1195. \
  1196. for (x = slicew_start; x < slicew_end; x++) { \
  1197. const uint8_t *c0_data = in->data[plane + 0]; \
  1198. const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp]; \
  1199. const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp]; \
  1200. uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x; \
  1201. uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x; \
  1202. uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x; \
  1203. uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1); \
  1204. uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data); \
  1205. uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1); \
  1206. uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data); \
  1207. uint8_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1); \
  1208. uint8_t * const d2 = (mirror ? d2_bottom_line : d2_data); \
  1209. \
  1210. for (y = 0; y < src_h; y++) { \
  1211. const int c0 = c0_data[x >> c0_shift_w] + 128; \
  1212. const int c1 = c1_data[x >> c1_shift_w] - 128; \
  1213. const int c2 = c2_data[x >> c2_shift_w] - 128; \
  1214. uint8_t *target; \
  1215. \
  1216. target = d0 + x + d0_signed_linesize * c0; \
  1217. update(target, max, intensity); \
  1218. \
  1219. target = d1 + x + d1_signed_linesize * (c0 + c1); \
  1220. update(target, max, intensity); \
  1221. \
  1222. target = d2 + x + d2_signed_linesize * (c0 + c2); \
  1223. update_cr(target, max, intensity); \
  1224. \
  1225. if (!c0_shift_h || (y & c0_shift_h)) \
  1226. c0_data += c0_linesize; \
  1227. if (!c1_shift_h || (y & c1_shift_h)) \
  1228. c1_data += c1_linesize; \
  1229. if (!c1_shift_h || (y & c1_shift_h)) \
  1230. c2_data += c1_linesize; \
  1231. d0_data += d0_linesize; \
  1232. d1_data += d1_linesize; \
  1233. d2_data += d2_linesize; \
  1234. } \
  1235. } \
  1236. } else { \
  1237. const uint8_t *c0_data = in->data[plane] + (sliceh_start >> c0_shift_h) * c0_linesize; \
  1238. const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp] + (sliceh_start >> c1_shift_h) * c1_linesize; \
  1239. const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp] + (sliceh_start >> c2_shift_h) * c2_linesize; \
  1240. uint8_t *d0_data = out->data[plane] + (offset_y + sliceh_start) * d0_linesize + offset_x; \
  1241. uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + (offset_y + sliceh_start) * d1_linesize + offset_x; \
  1242. uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + (offset_y + sliceh_start) * d2_linesize + offset_x; \
  1243. \
  1244. if (mirror) { \
  1245. d0_data += s->size - 1; \
  1246. d1_data += s->size - 1; \
  1247. d2_data += s->size - 1; \
  1248. } \
  1249. \
  1250. for (y = sliceh_start; y < sliceh_end; y++) { \
  1251. for (x = 0; x < src_w; x++) { \
  1252. const int c0 = c0_data[x >> c0_shift_w] + 128; \
  1253. const int c1 = c1_data[x >> c1_shift_w] - 128; \
  1254. const int c2 = c2_data[x >> c2_shift_w] - 128; \
  1255. uint8_t *target; \
  1256. \
  1257. if (mirror) { \
  1258. target = d0_data - c0; \
  1259. update(target, max, intensity); \
  1260. target = d1_data - (c0 + c1); \
  1261. update(target, max, intensity); \
  1262. target = d2_data - (c0 + c2); \
  1263. update_cr(target, max, intensity); \
  1264. } else { \
  1265. target = d0_data + c0; \
  1266. update(target, max, intensity); \
  1267. target = d1_data + (c0 + c1); \
  1268. update(target, max, intensity); \
  1269. target = d2_data + (c0 + c2); \
  1270. update_cr(target, max, intensity); \
  1271. } \
  1272. } \
  1273. \
  1274. if (!c0_shift_h || (y & c0_shift_h)) \
  1275. c0_data += c0_linesize; \
  1276. if (!c1_shift_h || (y & c1_shift_h)) \
  1277. c1_data += c1_linesize; \
  1278. if (!c2_shift_h || (y & c2_shift_h)) \
  1279. c2_data += c2_linesize; \
  1280. d0_data += d0_linesize; \
  1281. d1_data += d1_linesize; \
  1282. d2_data += d2_linesize; \
  1283. } \
  1284. } \
  1285. return 0; \
  1286. }
  1287. AFLAT16(aflat16_row, update16, 0, 0)
  1288. AFLAT16(aflat16_row_mirror, update16, 0, 1)
  1289. AFLAT16(aflat16_column, update16, 1, 0)
  1290. AFLAT16(aflat16_column_mirror, update16, 1, 1)
  1291. AFLAT16(xflat16_row, update16_cr, 0, 0)
  1292. AFLAT16(xflat16_row_mirror, update16_cr, 0, 1)
  1293. AFLAT16(xflat16_column, update16_cr, 1, 0)
  1294. AFLAT16(xflat16_column_mirror, update16_cr, 1, 1)
  1295. AFLAT(aflat_row, update, 0, 0)
  1296. AFLAT(aflat_row_mirror, update, 0, 1)
  1297. AFLAT(aflat_column, update, 1, 0)
  1298. AFLAT(aflat_column_mirror, update, 1, 1)
  1299. AFLAT(xflat_row, update_cr, 0, 0)
  1300. AFLAT(xflat_row_mirror, update_cr, 0, 1)
  1301. AFLAT(xflat_column, update_cr, 1, 0)
  1302. AFLAT(xflat_column_mirror, update_cr, 1, 1)
  1303. static av_always_inline void chroma16(WaveformContext *s,
  1304. AVFrame *in, AVFrame *out,
  1305. int component, int intensity,
  1306. int offset_y, int offset_x,
  1307. int column, int mirror,
  1308. int jobnr, int nb_jobs)
  1309. {
  1310. const int plane = s->desc->comp[component].plane;
  1311. const int c0_linesize = in->linesize[(plane + 1) % s->ncomp] / 2;
  1312. const int c1_linesize = in->linesize[(plane + 2) % s->ncomp] / 2;
  1313. const int dst_linesize = out->linesize[plane] / 2;
  1314. const int limit = s->max - 1;
  1315. const int max = limit - intensity;
  1316. const int mid = s->max / 2;
  1317. const int c0_shift_w = s->shift_w[(component + 1) % s->ncomp];
  1318. const int c1_shift_w = s->shift_w[(component + 2) % s->ncomp];
  1319. const int c0_shift_h = s->shift_h[(component + 1) % s->ncomp];
  1320. const int c1_shift_h = s->shift_h[(component + 2) % s->ncomp];
  1321. const int src_h = in->height;
  1322. const int src_w = in->width;
  1323. const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
  1324. const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
  1325. const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
  1326. const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
  1327. int x, y;
  1328. if (column) {
  1329. const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1);
  1330. for (x = slicew_start; x < slicew_end; x++) {
  1331. const uint16_t *c0_data = (uint16_t *)in->data[(plane + 1) % s->ncomp];
  1332. const uint16_t *c1_data = (uint16_t *)in->data[(plane + 2) % s->ncomp];
  1333. uint16_t *dst_data = (uint16_t *)out->data[plane] + offset_y * dst_linesize + offset_x;
  1334. uint16_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1);
  1335. uint16_t * const dst_line = (mirror ? dst_bottom_line : dst_data);
  1336. uint16_t *dst = dst_line;
  1337. for (y = 0; y < src_h; y++) {
  1338. const int sum = FFMIN(FFABS(c0_data[x >> c0_shift_w] - mid) + FFABS(c1_data[x >> c1_shift_w] - mid - 1), limit);
  1339. uint16_t *target;
  1340. target = dst + x + dst_signed_linesize * sum;
  1341. update16(target, max, intensity, limit);
  1342. if (!c0_shift_h || (y & c0_shift_h))
  1343. c0_data += c0_linesize;
  1344. if (!c1_shift_h || (y & c1_shift_h))
  1345. c1_data += c1_linesize;
  1346. dst_data += dst_linesize;
  1347. }
  1348. }
  1349. } else {
  1350. const uint16_t *c0_data = (uint16_t *)in->data[(plane + 1) % s->ncomp] + (sliceh_start >> c0_shift_h) * c0_linesize;
  1351. const uint16_t *c1_data = (uint16_t *)in->data[(plane + 2) % s->ncomp] + (sliceh_start >> c1_shift_h) * c1_linesize;
  1352. uint16_t *dst_data = (uint16_t *)out->data[plane] + (offset_y + sliceh_start) * dst_linesize + offset_x;
  1353. if (mirror)
  1354. dst_data += s->size - 1;
  1355. for (y = sliceh_start; y < sliceh_end; y++) {
  1356. for (x = 0; x < src_w; x++) {
  1357. const int sum = FFMIN(FFABS(c0_data[x >> c0_shift_w] - mid) + FFABS(c1_data[x >> c1_shift_w] - mid - 1), limit);
  1358. uint16_t *target;
  1359. if (mirror) {
  1360. target = dst_data - sum;
  1361. update16(target, max, intensity, limit);
  1362. } else {
  1363. target = dst_data + sum;
  1364. update16(target, max, intensity, limit);
  1365. }
  1366. }
  1367. if (!c0_shift_h || (y & c0_shift_h))
  1368. c0_data += c0_linesize;
  1369. if (!c1_shift_h || (y & c1_shift_h))
  1370. c1_data += c1_linesize;
  1371. dst_data += dst_linesize;
  1372. }
  1373. }
  1374. }
  1375. #define CHROMA16_FUNC(name, column, mirror) \
  1376. static int chroma16_##name(AVFilterContext *ctx, \
  1377. void *arg, int jobnr, \
  1378. int nb_jobs) \
  1379. { \
  1380. WaveformContext *s = ctx->priv; \
  1381. ThreadData *td = arg; \
  1382. AVFrame *in = td->in; \
  1383. AVFrame *out = td->out; \
  1384. int component = td->component; \
  1385. int offset_y = td->offset_y; \
  1386. int offset_x = td->offset_x; \
  1387. \
  1388. chroma16(s, in, out, component, s->intensity,\
  1389. offset_y, offset_x, column, mirror, \
  1390. jobnr, nb_jobs); \
  1391. \
  1392. return 0; \
  1393. }
  1394. CHROMA16_FUNC(column_mirror, 1, 1)
  1395. CHROMA16_FUNC(column, 1, 0)
  1396. CHROMA16_FUNC(row_mirror, 0, 1)
  1397. CHROMA16_FUNC(row, 0, 0)
  1398. static av_always_inline void chroma(WaveformContext *s,
  1399. AVFrame *in, AVFrame *out,
  1400. int component, int intensity,
  1401. int offset_y, int offset_x,
  1402. int column, int mirror,
  1403. int jobnr, int nb_jobs)
  1404. {
  1405. const int plane = s->desc->comp[component].plane;
  1406. const int src_h = in->height;
  1407. const int src_w = in->width;
  1408. const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
  1409. const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
  1410. const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
  1411. const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
  1412. const int c0_linesize = in->linesize[(plane + 1) % s->ncomp];
  1413. const int c1_linesize = in->linesize[(plane + 2) % s->ncomp];
  1414. const int dst_linesize = out->linesize[plane];
  1415. const int max = 255 - intensity;
  1416. const int c0_shift_w = s->shift_w[(component + 1) % s->ncomp];
  1417. const int c1_shift_w = s->shift_w[(component + 2) % s->ncomp];
  1418. const int c0_shift_h = s->shift_h[(component + 1) % s->ncomp];
  1419. const int c1_shift_h = s->shift_h[(component + 2) % s->ncomp];
  1420. int x, y;
  1421. if (column) {
  1422. const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1);
  1423. for (x = slicew_start; x < slicew_end; x++) {
  1424. const uint8_t *c0_data = in->data[(plane + 1) % s->ncomp];
  1425. const uint8_t *c1_data = in->data[(plane + 2) % s->ncomp];
  1426. uint8_t *dst_data = out->data[plane] + offset_y * dst_linesize + offset_x;
  1427. uint8_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1);
  1428. uint8_t * const dst_line = (mirror ? dst_bottom_line : dst_data);
  1429. uint8_t *dst = dst_line;
  1430. for (y = 0; y < src_h; y++) {
  1431. const int sum = FFABS(c0_data[x >> c0_shift_w] - 128) + FFABS(c1_data[x >> c1_shift_w] - 127);
  1432. uint8_t *target;
  1433. target = dst + x + dst_signed_linesize * sum;
  1434. update(target, max, intensity);
  1435. if (!c0_shift_h || (y & c0_shift_h))
  1436. c0_data += c0_linesize;
  1437. if (!c1_shift_h || (y & c1_shift_h))
  1438. c1_data += c1_linesize;
  1439. dst_data += dst_linesize;
  1440. }
  1441. }
  1442. } else {
  1443. const uint8_t *c0_data = in->data[(plane + 1) % s->ncomp] + (sliceh_start >> c0_shift_h) * c0_linesize;
  1444. const uint8_t *c1_data = in->data[(plane + 2) % s->ncomp] + (sliceh_start >> c1_shift_h) * c1_linesize;
  1445. uint8_t *dst_data = out->data[plane] + (offset_y + sliceh_start) * dst_linesize + offset_x;
  1446. if (mirror)
  1447. dst_data += s->size - 1;
  1448. for (y = sliceh_start; y < sliceh_end; y++) {
  1449. for (x = 0; x < src_w; x++) {
  1450. const int sum = FFABS(c0_data[x >> c0_shift_w] - 128) + FFABS(c1_data[x >> c1_shift_w] - 127);
  1451. uint8_t *target;
  1452. if (mirror) {
  1453. target = dst_data - sum;
  1454. update(target, max, intensity);
  1455. } else {
  1456. target = dst_data + sum;
  1457. update(target, max, intensity);
  1458. }
  1459. }
  1460. if (!c0_shift_h || (y & c0_shift_h))
  1461. c0_data += c0_linesize;
  1462. if (!c1_shift_h || (y & c1_shift_h))
  1463. c1_data += c1_linesize;
  1464. dst_data += dst_linesize;
  1465. }
  1466. }
  1467. }
  1468. #define CHROMA_FUNC(name, column, mirror) \
  1469. static int chroma_##name(AVFilterContext *ctx, \
  1470. void *arg, int jobnr, \
  1471. int nb_jobs) \
  1472. { \
  1473. WaveformContext *s = ctx->priv; \
  1474. ThreadData *td = arg; \
  1475. AVFrame *in = td->in; \
  1476. AVFrame *out = td->out; \
  1477. int component = td->component; \
  1478. int offset_y = td->offset_y; \
  1479. int offset_x = td->offset_x; \
  1480. \
  1481. chroma(s, in, out, component, s->intensity, \
  1482. offset_y, offset_x, column, mirror, \
  1483. jobnr, nb_jobs); \
  1484. \
  1485. return 0; \
  1486. }
  1487. CHROMA_FUNC(column_mirror, 1, 1)
  1488. CHROMA_FUNC(column, 1, 0)
  1489. CHROMA_FUNC(row_mirror, 0, 1)
  1490. CHROMA_FUNC(row, 0, 0)
  1491. static av_always_inline void color16(WaveformContext *s,
  1492. AVFrame *in, AVFrame *out,
  1493. int component, int intensity,
  1494. int offset_y, int offset_x,
  1495. int column, int mirror,
  1496. int jobnr, int nb_jobs)
  1497. {
  1498. const int plane = s->desc->comp[component].plane;
  1499. const int limit = s->max - 1;
  1500. const int src_h = in->height;
  1501. const int src_w = in->width;
  1502. const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
  1503. const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
  1504. const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
  1505. const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
  1506. const int c0_linesize = in->linesize[ plane + 0 ] / 2;
  1507. const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2;
  1508. const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2;
  1509. const int c0_shift_h = s->shift_h[ component + 0 ];
  1510. const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
  1511. const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
  1512. const uint16_t *c0_data = (const uint16_t *)in->data[plane + 0] + (sliceh_start >> c0_shift_h) * c0_linesize;
  1513. const uint16_t *c1_data = (const uint16_t *)in->data[(plane + 1) % s->ncomp] + (sliceh_start >> c1_shift_h) * c1_linesize;
  1514. const uint16_t *c2_data = (const uint16_t *)in->data[(plane + 2) % s->ncomp] + (sliceh_start >> c2_shift_h) * c2_linesize;
  1515. const int d0_linesize = out->linesize[ plane + 0 ] / 2;
  1516. const int d1_linesize = out->linesize[(plane + 1) % s->ncomp] / 2;
  1517. const int d2_linesize = out->linesize[(plane + 2) % s->ncomp] / 2;
  1518. const int c0_shift_w = s->shift_w[ component + 0 ];
  1519. const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
  1520. const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
  1521. int x, y;
  1522. if (column) {
  1523. const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
  1524. const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
  1525. const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1);
  1526. uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x;
  1527. uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
  1528. uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x;
  1529. uint16_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
  1530. uint16_t * const d0 = (mirror ? d0_bottom_line : d0_data);
  1531. uint16_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
  1532. uint16_t * const d1 = (mirror ? d1_bottom_line : d1_data);
  1533. uint16_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1);
  1534. uint16_t * const d2 = (mirror ? d2_bottom_line : d2_data);
  1535. for (y = 0; y < src_h; y++) {
  1536. for (x = slicew_start; x < slicew_end; x++) {
  1537. const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit);
  1538. const int c1 = c1_data[x >> c1_shift_w];
  1539. const int c2 = c2_data[x >> c2_shift_w];
  1540. *(d0 + d0_signed_linesize * c0 + x) = c0;
  1541. *(d1 + d1_signed_linesize * c0 + x) = c1;
  1542. *(d2 + d2_signed_linesize * c0 + x) = c2;
  1543. }
  1544. if (!c0_shift_h || (y & c0_shift_h))
  1545. c0_data += c0_linesize;
  1546. if (!c1_shift_h || (y & c1_shift_h))
  1547. c1_data += c1_linesize;
  1548. if (!c2_shift_h || (y & c2_shift_h))
  1549. c2_data += c2_linesize;
  1550. d0_data += d0_linesize;
  1551. d1_data += d1_linesize;
  1552. d2_data += d2_linesize;
  1553. }
  1554. } else {
  1555. uint16_t *d0_data = (uint16_t *)out->data[plane] + (offset_y + sliceh_start) * d0_linesize + offset_x;
  1556. uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + (offset_y + sliceh_start) * d1_linesize + offset_x;
  1557. uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + (offset_y + sliceh_start) * d2_linesize + offset_x;
  1558. if (mirror) {
  1559. d0_data += s->size - 1;
  1560. d1_data += s->size - 1;
  1561. d2_data += s->size - 1;
  1562. }
  1563. for (y = sliceh_start; y < sliceh_end; y++) {
  1564. for (x = 0; x < src_w; x++) {
  1565. const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit);
  1566. const int c1 = c1_data[x >> c1_shift_w];
  1567. const int c2 = c2_data[x >> c2_shift_w];
  1568. if (mirror) {
  1569. *(d0_data - c0) = c0;
  1570. *(d1_data - c0) = c1;
  1571. *(d2_data - c0) = c2;
  1572. } else {
  1573. *(d0_data + c0) = c0;
  1574. *(d1_data + c0) = c1;
  1575. *(d2_data + c0) = c2;
  1576. }
  1577. }
  1578. if (!c0_shift_h || (y & c0_shift_h))
  1579. c0_data += c0_linesize;
  1580. if (!c1_shift_h || (y & c1_shift_h))
  1581. c1_data += c1_linesize;
  1582. if (!c2_shift_h || (y & c2_shift_h))
  1583. c2_data += c2_linesize;
  1584. d0_data += d0_linesize;
  1585. d1_data += d1_linesize;
  1586. d2_data += d2_linesize;
  1587. }
  1588. }
  1589. }
  1590. #define COLOR16_FUNC(name, column, mirror) \
  1591. static int color16_##name(AVFilterContext *ctx, \
  1592. void *arg, int jobnr, \
  1593. int nb_jobs) \
  1594. { \
  1595. WaveformContext *s = ctx->priv; \
  1596. ThreadData *td = arg; \
  1597. AVFrame *in = td->in; \
  1598. AVFrame *out = td->out; \
  1599. int component = td->component; \
  1600. int offset_y = td->offset_y; \
  1601. int offset_x = td->offset_x; \
  1602. \
  1603. color16(s, in, out, component, s->intensity, \
  1604. offset_y, offset_x, column, mirror, \
  1605. jobnr, nb_jobs); \
  1606. \
  1607. return 0; \
  1608. }
  1609. COLOR16_FUNC(column_mirror, 1, 1)
  1610. COLOR16_FUNC(column, 1, 0)
  1611. COLOR16_FUNC(row_mirror, 0, 1)
  1612. COLOR16_FUNC(row, 0, 0)
  1613. static av_always_inline void color(WaveformContext *s,
  1614. AVFrame *in, AVFrame *out,
  1615. int component, int intensity,
  1616. int offset_y, int offset_x,
  1617. int column, int mirror,
  1618. int jobnr, int nb_jobs)
  1619. {
  1620. const int plane = s->desc->comp[component].plane;
  1621. const int src_h = in->height;
  1622. const int src_w = in->width;
  1623. const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
  1624. const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
  1625. const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
  1626. const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
  1627. const int c0_linesize = in->linesize[ plane + 0 ];
  1628. const int c1_linesize = in->linesize[(plane + 1) % s->ncomp];
  1629. const int c2_linesize = in->linesize[(plane + 2) % s->ncomp];
  1630. const int c0_shift_h = s->shift_h[ component + 0 ];
  1631. const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
  1632. const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
  1633. const uint8_t *c0_data = in->data[plane] + (sliceh_start >> c0_shift_h) * c0_linesize;
  1634. const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp] + (sliceh_start >> c1_shift_h) * c1_linesize;
  1635. const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp] + (sliceh_start >> c2_shift_h) * c2_linesize;
  1636. const int d0_linesize = out->linesize[ plane + 0 ];
  1637. const int d1_linesize = out->linesize[(plane + 1) % s->ncomp];
  1638. const int d2_linesize = out->linesize[(plane + 2) % s->ncomp];
  1639. const int c0_shift_w = s->shift_w[ component + 0 ];
  1640. const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
  1641. const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
  1642. int x, y;
  1643. if (column) {
  1644. const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
  1645. const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
  1646. const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1);
  1647. uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x;
  1648. uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
  1649. uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x;
  1650. uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
  1651. uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data);
  1652. uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
  1653. uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data);
  1654. uint8_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1);
  1655. uint8_t * const d2 = (mirror ? d2_bottom_line : d2_data);
  1656. for (y = 0; y < src_h; y++) {
  1657. for (x = slicew_start; x < slicew_end; x++) {
  1658. const int c0 = c0_data[x >> c0_shift_w];
  1659. const int c1 = c1_data[x >> c1_shift_w];
  1660. const int c2 = c2_data[x >> c2_shift_w];
  1661. *(d0 + d0_signed_linesize * c0 + x) = c0;
  1662. *(d1 + d1_signed_linesize * c0 + x) = c1;
  1663. *(d2 + d2_signed_linesize * c0 + x) = c2;
  1664. }
  1665. if (!c0_shift_h || (y & c0_shift_h))
  1666. c0_data += c0_linesize;
  1667. if (!c1_shift_h || (y & c1_shift_h))
  1668. c1_data += c1_linesize;
  1669. if (!c2_shift_h || (y & c2_shift_h))
  1670. c2_data += c2_linesize;
  1671. d0_data += d0_linesize;
  1672. d1_data += d1_linesize;
  1673. d2_data += d2_linesize;
  1674. }
  1675. } else {
  1676. uint8_t *d0_data = out->data[plane] + (offset_y + sliceh_start) * d0_linesize + offset_x;
  1677. uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + (offset_y + sliceh_start) * d1_linesize + offset_x;
  1678. uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + (offset_y + sliceh_start) * d2_linesize + offset_x;
  1679. if (mirror) {
  1680. d0_data += s->size - 1;
  1681. d1_data += s->size - 1;
  1682. d2_data += s->size - 1;
  1683. }
  1684. for (y = sliceh_start; y < sliceh_end; y++) {
  1685. for (x = 0; x < src_w; x++) {
  1686. const int c0 = c0_data[x >> c0_shift_w];
  1687. const int c1 = c1_data[x >> c1_shift_w];
  1688. const int c2 = c2_data[x >> c2_shift_w];
  1689. if (mirror) {
  1690. *(d0_data - c0) = c0;
  1691. *(d1_data - c0) = c1;
  1692. *(d2_data - c0) = c2;
  1693. } else {
  1694. *(d0_data + c0) = c0;
  1695. *(d1_data + c0) = c1;
  1696. *(d2_data + c0) = c2;
  1697. }
  1698. }
  1699. if (!c0_shift_h || (y & c0_shift_h))
  1700. c0_data += c0_linesize;
  1701. if (!c1_shift_h || (y & c1_shift_h))
  1702. c1_data += c1_linesize;
  1703. if (!c2_shift_h || (y & c2_shift_h))
  1704. c2_data += c2_linesize;
  1705. d0_data += d0_linesize;
  1706. d1_data += d1_linesize;
  1707. d2_data += d2_linesize;
  1708. }
  1709. }
  1710. }
  1711. #define COLOR_FUNC(name, column, mirror) \
  1712. static int color_##name(AVFilterContext *ctx, \
  1713. void *arg, int jobnr, \
  1714. int nb_jobs) \
  1715. { \
  1716. WaveformContext *s = ctx->priv; \
  1717. ThreadData *td = arg; \
  1718. AVFrame *in = td->in; \
  1719. AVFrame *out = td->out; \
  1720. int component = td->component; \
  1721. int offset_y = td->offset_y; \
  1722. int offset_x = td->offset_x; \
  1723. \
  1724. color(s, in, out, component, s->intensity, \
  1725. offset_y, offset_x, column, mirror, \
  1726. jobnr, nb_jobs); \
  1727. \
  1728. return 0; \
  1729. }
  1730. COLOR_FUNC(column_mirror, 1, 1)
  1731. COLOR_FUNC(column, 1, 0)
  1732. COLOR_FUNC(row_mirror, 0, 1)
  1733. COLOR_FUNC(row, 0, 0)
  1734. static av_always_inline void acolor16(WaveformContext *s,
  1735. AVFrame *in, AVFrame *out,
  1736. int component, int intensity,
  1737. int offset_y, int offset_x,
  1738. int column, int mirror,
  1739. int jobnr, int nb_jobs)
  1740. {
  1741. const int plane = s->desc->comp[component].plane;
  1742. const int limit = s->max - 1;
  1743. const int max = limit - intensity;
  1744. const int src_h = in->height;
  1745. const int src_w = in->width;
  1746. const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
  1747. const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
  1748. const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
  1749. const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
  1750. const int c0_shift_h = s->shift_h[ component + 0 ];
  1751. const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
  1752. const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
  1753. const int c0_linesize = in->linesize[ plane + 0 ] / 2;
  1754. const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2;
  1755. const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2;
  1756. const uint16_t *c0_data = (const uint16_t *)in->data[plane + 0] + (sliceh_start >> c0_shift_h) * c0_linesize;
  1757. const uint16_t *c1_data = (const uint16_t *)in->data[(plane + 1) % s->ncomp] + (sliceh_start >> c1_shift_h) * c1_linesize;
  1758. const uint16_t *c2_data = (const uint16_t *)in->data[(plane + 2) % s->ncomp] + (sliceh_start >> c2_shift_h) * c2_linesize;
  1759. const int d0_linesize = out->linesize[ plane + 0 ] / 2;
  1760. const int d1_linesize = out->linesize[(plane + 1) % s->ncomp] / 2;
  1761. const int d2_linesize = out->linesize[(plane + 2) % s->ncomp] / 2;
  1762. const int c0_shift_w = s->shift_w[ component + 0 ];
  1763. const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
  1764. const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
  1765. int x, y;
  1766. if (column) {
  1767. const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
  1768. const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
  1769. const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1);
  1770. uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x;
  1771. uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
  1772. uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x;
  1773. uint16_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
  1774. uint16_t * const d0 = (mirror ? d0_bottom_line : d0_data);
  1775. uint16_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
  1776. uint16_t * const d1 = (mirror ? d1_bottom_line : d1_data);
  1777. uint16_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1);
  1778. uint16_t * const d2 = (mirror ? d2_bottom_line : d2_data);
  1779. for (y = 0; y < src_h; y++) {
  1780. for (x = slicew_start; x < slicew_end; x++) {
  1781. const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit);
  1782. const int c1 = c1_data[x >> c1_shift_w];
  1783. const int c2 = c2_data[x >> c2_shift_w];
  1784. update16(d0 + d0_signed_linesize * c0 + x, max, intensity, limit);
  1785. *(d1 + d1_signed_linesize * c0 + x) = c1;
  1786. *(d2 + d2_signed_linesize * c0 + x) = c2;
  1787. }
  1788. if (!c0_shift_h || (y & c0_shift_h))
  1789. c0_data += c0_linesize;
  1790. if (!c1_shift_h || (y & c1_shift_h))
  1791. c1_data += c1_linesize;
  1792. if (!c2_shift_h || (y & c2_shift_h))
  1793. c2_data += c2_linesize;
  1794. d0_data += d0_linesize;
  1795. d1_data += d1_linesize;
  1796. d2_data += d2_linesize;
  1797. }
  1798. } else {
  1799. uint16_t *d0_data = (uint16_t *)out->data[plane] + (offset_y + sliceh_start) * d0_linesize + offset_x;
  1800. uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + (offset_y + sliceh_start) * d1_linesize + offset_x;
  1801. uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + (offset_y + sliceh_start) * d2_linesize + offset_x;
  1802. if (mirror) {
  1803. d0_data += s->size - 1;
  1804. d1_data += s->size - 1;
  1805. d2_data += s->size - 1;
  1806. }
  1807. for (y = sliceh_start; y < sliceh_end; y++) {
  1808. for (x = 0; x < src_w; x++) {
  1809. const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit);
  1810. const int c1 = c1_data[x >> c1_shift_w];
  1811. const int c2 = c2_data[x >> c2_shift_w];
  1812. if (mirror) {
  1813. update16(d0_data - c0, max, intensity, limit);
  1814. *(d1_data - c0) = c1;
  1815. *(d2_data - c0) = c2;
  1816. } else {
  1817. update16(d0_data + c0, max, intensity, limit);
  1818. *(d1_data + c0) = c1;
  1819. *(d2_data + c0) = c2;
  1820. }
  1821. }
  1822. if (!c0_shift_h || (y & c0_shift_h))
  1823. c0_data += c0_linesize;
  1824. if (!c1_shift_h || (y & c1_shift_h))
  1825. c1_data += c1_linesize;
  1826. if (!c2_shift_h || (y & c2_shift_h))
  1827. c2_data += c2_linesize;
  1828. d0_data += d0_linesize;
  1829. d1_data += d1_linesize;
  1830. d2_data += d2_linesize;
  1831. }
  1832. }
  1833. }
  1834. #define ACOLOR16_FUNC(name, column, mirror) \
  1835. static int acolor16_##name(AVFilterContext *ctx, \
  1836. void *arg, int jobnr, \
  1837. int nb_jobs) \
  1838. { \
  1839. WaveformContext *s = ctx->priv; \
  1840. ThreadData *td = arg; \
  1841. AVFrame *in = td->in; \
  1842. AVFrame *out = td->out; \
  1843. int component = td->component; \
  1844. int offset_y = td->offset_y; \
  1845. int offset_x = td->offset_x; \
  1846. \
  1847. acolor16(s, in, out, component, s->intensity,\
  1848. offset_y, offset_x, column, mirror, \
  1849. jobnr, nb_jobs); \
  1850. \
  1851. return 0; \
  1852. }
  1853. ACOLOR16_FUNC(column_mirror, 1, 1)
  1854. ACOLOR16_FUNC(column, 1, 0)
  1855. ACOLOR16_FUNC(row_mirror, 0, 1)
  1856. ACOLOR16_FUNC(row, 0, 0)
  1857. static av_always_inline void acolor(WaveformContext *s,
  1858. AVFrame *in, AVFrame *out,
  1859. int component, int intensity,
  1860. int offset_y, int offset_x,
  1861. int column, int mirror,
  1862. int jobnr, int nb_jobs)
  1863. {
  1864. const int plane = s->desc->comp[component].plane;
  1865. const int src_h = in->height;
  1866. const int src_w = in->width;
  1867. const int sliceh_start = !column ? (src_h * jobnr) / nb_jobs : 0;
  1868. const int sliceh_end = !column ? (src_h * (jobnr+1)) / nb_jobs : src_h;
  1869. const int slicew_start = column ? (src_w * jobnr) / nb_jobs : 0;
  1870. const int slicew_end = column ? (src_w * (jobnr+1)) / nb_jobs : src_w;
  1871. const int c0_shift_w = s->shift_w[ component + 0 ];
  1872. const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
  1873. const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
  1874. const int c0_shift_h = s->shift_h[ component + 0 ];
  1875. const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
  1876. const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
  1877. const int c0_linesize = in->linesize[ plane + 0 ];
  1878. const int c1_linesize = in->linesize[(plane + 1) % s->ncomp];
  1879. const int c2_linesize = in->linesize[(plane + 2) % s->ncomp];
  1880. const uint8_t *c0_data = in->data[plane + 0] + (sliceh_start >> c0_shift_h) * c0_linesize;
  1881. const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp] + (sliceh_start >> c1_shift_h) * c1_linesize;
  1882. const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp] + (sliceh_start >> c2_shift_h) * c2_linesize;
  1883. const int d0_linesize = out->linesize[ plane + 0 ];
  1884. const int d1_linesize = out->linesize[(plane + 1) % s->ncomp];
  1885. const int d2_linesize = out->linesize[(plane + 2) % s->ncomp];
  1886. const int max = 255 - intensity;
  1887. int x, y;
  1888. if (column) {
  1889. const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
  1890. const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
  1891. const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1);
  1892. uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x;
  1893. uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
  1894. uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x;
  1895. uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
  1896. uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data);
  1897. uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
  1898. uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data);
  1899. uint8_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1);
  1900. uint8_t * const d2 = (mirror ? d2_bottom_line : d2_data);
  1901. for (y = 0; y < src_h; y++) {
  1902. for (x = slicew_start; x < slicew_end; x++) {
  1903. const int c0 = c0_data[x >> c0_shift_w];
  1904. const int c1 = c1_data[x >> c1_shift_w];
  1905. const int c2 = c2_data[x >> c2_shift_w];
  1906. update(d0 + d0_signed_linesize * c0 + x, max, intensity);
  1907. *(d1 + d1_signed_linesize * c0 + x) = c1;
  1908. *(d2 + d2_signed_linesize * c0 + x) = c2;
  1909. }
  1910. if (!c0_shift_h || (y & c0_shift_h))
  1911. c0_data += c0_linesize;
  1912. if (!c1_shift_h || (y & c1_shift_h))
  1913. c1_data += c1_linesize;
  1914. if (!c2_shift_h || (y & c2_shift_h))
  1915. c2_data += c2_linesize;
  1916. d0_data += d0_linesize;
  1917. d1_data += d1_linesize;
  1918. d2_data += d2_linesize;
  1919. }
  1920. } else {
  1921. uint8_t *d0_data = out->data[plane] + (offset_y + sliceh_start) * d0_linesize + offset_x;
  1922. uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + (offset_y + sliceh_start) * d1_linesize + offset_x;
  1923. uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + (offset_y + sliceh_start) * d2_linesize + offset_x;
  1924. if (mirror) {
  1925. d0_data += s->size - 1;
  1926. d1_data += s->size - 1;
  1927. d2_data += s->size - 1;
  1928. }
  1929. for (y = sliceh_start; y < sliceh_end; y++) {
  1930. for (x = 0; x < src_w; x++) {
  1931. const int c0 = c0_data[x >> c0_shift_w];
  1932. const int c1 = c1_data[x >> c1_shift_w];
  1933. const int c2 = c2_data[x >> c2_shift_w];
  1934. if (mirror) {
  1935. update(d0_data - c0, max, intensity);
  1936. *(d1_data - c0) = c1;
  1937. *(d2_data - c0) = c2;
  1938. } else {
  1939. update(d0_data + c0, max, intensity);
  1940. *(d1_data + c0) = c1;
  1941. *(d2_data + c0) = c2;
  1942. }
  1943. }
  1944. if (!c0_shift_h || (y & c0_shift_h))
  1945. c0_data += c0_linesize;
  1946. if (!c1_shift_h || (y & c1_shift_h))
  1947. c1_data += c1_linesize;
  1948. if (!c2_shift_h || (y & c2_shift_h))
  1949. c2_data += c2_linesize;
  1950. d0_data += d0_linesize;
  1951. d1_data += d1_linesize;
  1952. d2_data += d2_linesize;
  1953. }
  1954. }
  1955. }
  1956. #define ACOLOR_FUNC(name, column, mirror) \
  1957. static int acolor_##name(AVFilterContext *ctx, \
  1958. void *arg, int jobnr, \
  1959. int nb_jobs) \
  1960. { \
  1961. WaveformContext *s = ctx->priv; \
  1962. ThreadData *td = arg; \
  1963. AVFrame *in = td->in; \
  1964. AVFrame *out = td->out; \
  1965. int component = td->component; \
  1966. int offset_y = td->offset_y; \
  1967. int offset_x = td->offset_x; \
  1968. \
  1969. acolor(s, in, out, component, s->intensity, \
  1970. offset_y, offset_x, column, mirror, \
  1971. jobnr, nb_jobs); \
  1972. \
  1973. return 0; \
  1974. }
  1975. ACOLOR_FUNC(column_mirror, 1, 1)
  1976. ACOLOR_FUNC(column, 1, 0)
  1977. ACOLOR_FUNC(row_mirror, 0, 1)
  1978. ACOLOR_FUNC(row, 0, 0)
  1979. static const uint8_t black_yuva_color[4] = { 0, 127, 127, 255 };
  1980. static const uint8_t black_gbrp_color[4] = { 0, 0, 0, 255 };
  1981. static const GraticuleLines aflat_digital8[] = {
  1982. { { { "16", 16+128 }, { "16", 16+128 }, { "16", 16+128 }, { "0", 0+128 } } },
  1983. { { { "128", 128+128 }, { "128", 128+128 }, { "128", 128+128 }, { "128", 128+128 } } },
  1984. { { { "235", 235+128 }, { "240", 240+128 }, { "240", 240+128 }, { "255", 255+128 } } },
  1985. };
  1986. static const GraticuleLines aflat_digital9[] = {
  1987. { { { "32", 32+256 }, { "32", 32+256 }, { "32", 32+256 }, { "0", 0+256 } } },
  1988. { { { "256", 256+256 }, { "256", 256+256 }, { "256", 256+256 }, { "256", 256+256 } } },
  1989. { { { "470", 470+256 }, { "480", 480+256 }, { "480", 480+256 }, { "511", 511+256 } } },
  1990. };
  1991. static const GraticuleLines aflat_digital10[] = {
  1992. { { { "64", 64+512 }, { "64", 64+512 }, { "64", 64+512 }, { "0", 0+512 } } },
  1993. { { { "512", 512+512 }, { "512", 512+512 }, { "512", 512+512 }, { "512", 512+512 } } },
  1994. { { { "940", 940+512 }, { "960", 960+512 }, { "960", 960+512 }, { "1023", 1023+512 } } },
  1995. };
  1996. static const GraticuleLines aflat_digital12[] = {
  1997. { { { "256", 256+2048 }, { "256", 256+2048 }, { "256", 256+2048 }, { "0", 0+2048 } } },
  1998. { { { "2048", 2048+2048 }, { "2048", 2048+2048 }, { "2048", 2048+2048 }, { "2048", 2048+2048 } } },
  1999. { { { "3760", 3760+2048 }, { "3840", 3840+2048 }, { "3840", 3840+2048 }, { "4095", 4095+2048 } } },
  2000. };
  2001. static const GraticuleLines aflat_millivolts8[] = {
  2002. { { { "0", 16+128 }, { "0", 16+128 }, { "0", 16+128 }, { "0", 0+128 } } },
  2003. { { { "175", 71+128 }, { "175", 72+128 }, { "175", 72+128 }, { "175", 64+128 } } },
  2004. { { { "350", 126+128 }, { "350", 128+128 }, { "350", 128+128 }, { "350", 128+128 } } },
  2005. { { { "525", 180+128 }, { "525", 184+128 }, { "525", 184+128 }, { "525", 192+128 } } },
  2006. { { { "700", 235+128 }, { "700", 240+128 }, { "700", 240+128 }, { "700", 255+128 } } },
  2007. };
  2008. static const GraticuleLines aflat_millivolts9[] = {
  2009. { { { "0", 32+256 }, { "0", 32+256 }, { "0", 32+256 }, { "0", 0+256 } } },
  2010. { { { "175", 142+256 }, { "175", 144+256 }, { "175", 144+256 }, { "175", 128+256 } } },
  2011. { { { "350", 251+256 }, { "350", 256+256 }, { "350", 256+256 }, { "350", 256+256 } } },
  2012. { { { "525", 361+256 }, { "525", 368+256 }, { "525", 368+256 }, { "525", 384+256 } } },
  2013. { { { "700", 470+256 }, { "700", 480+256 }, { "700", 480+256 }, { "700", 511+256 } } },
  2014. };
  2015. static const GraticuleLines aflat_millivolts10[] = {
  2016. { { { "0", 64+512 }, { "0", 64+512 }, { "0", 64+512 }, { "0", 0+512 } } },
  2017. { { { "175", 283+512 }, { "175", 288+512 }, { "175", 288+512 }, { "175", 256+512 } } },
  2018. { { { "350", 502+512 }, { "350", 512+512 }, { "350", 512+512 }, { "350", 512+512 } } },
  2019. { { { "525", 721+512 }, { "525", 736+512 }, { "525", 736+512 }, { "525", 768+512 } } },
  2020. { { { "700", 940+512 }, { "700", 960+512 }, { "700", 960+512 }, { "700", 1023+512 } } },
  2021. };
  2022. static const GraticuleLines aflat_millivolts12[] = {
  2023. { { { "0", 256+2048 }, { "0", 256+2048 }, { "0", 256+2048 }, { "0", 0+2048 } } },
  2024. { { { "175", 1132+2048 }, { "175", 1152+2048 }, { "175", 1152+2048 }, { "175", 1024+2048 } } },
  2025. { { { "350", 2008+2048 }, { "350", 2048+2048 }, { "350", 2048+2048 }, { "350", 2048+2048 } } },
  2026. { { { "525", 2884+2048 }, { "525", 2944+2048 }, { "525", 2944+2048 }, { "525", 3072+2048 } } },
  2027. { { { "700", 3760+2048 }, { "700", 3840+2048 }, { "700", 3840+2048 }, { "700", 4095+2048 } } },
  2028. };
  2029. static const GraticuleLines aflat_ire8[] = {
  2030. { { { "-25", -39+128 }, { "-25", -40+128 }, { "-25", -40+128 }, { "-25", -64+128 } } },
  2031. { { { "0", 16+128 }, { "0", 16+128 }, { "0", 16+128 }, { "0", 0+128 } } },
  2032. { { { "25", 71+128 }, { "25", 72+128 }, { "25", 72+128 }, { "25", 64+128 } } },
  2033. { { { "50", 126+128 }, { "50", 128+128 }, { "50", 128+128 }, { "50", 128+128 } } },
  2034. { { { "75", 180+128 }, { "75", 184+128 }, { "75", 184+128 }, { "75", 192+128 } } },
  2035. { { { "100", 235+128 }, { "100", 240+128 }, { "100", 240+128 }, { "100", 256+128 } } },
  2036. { { { "125", 290+128 }, { "125", 296+128 }, { "125", 296+128 }, { "125", 320+128 } } },
  2037. };
  2038. static const GraticuleLines aflat_ire9[] = {
  2039. { { { "-25", -78+256 }, { "-25", -80+256 }, { "-25", -80+256 }, { "-25",-128+256 } } },
  2040. { { { "0", 32+256 }, { "0", 32+256 }, { "0", 32+256 }, { "0", 0+256 } } },
  2041. { { { "25", 142+256 }, { "25", 144+256 }, { "25", 144+256 }, { "25", 128+256 } } },
  2042. { { { "50", 251+256 }, { "50", 256+256 }, { "50", 256+256 }, { "50", 256+256 } } },
  2043. { { { "75", 361+256 }, { "75", 368+256 }, { "75", 368+256 }, { "75", 384+256 } } },
  2044. { { { "100", 470+256 }, { "100", 480+256 }, { "100", 480+256 }, { "100", 512+256 } } },
  2045. { { { "125", 580+256 }, { "125", 592+256 }, { "125", 592+256 }, { "125", 640+256 } } },
  2046. };
  2047. static const GraticuleLines aflat_ire10[] = {
  2048. { { { "-25",-156+512 }, { "-25",-160+512 }, { "-25",-160+512 }, { "-25", -256+512 } } },
  2049. { { { "0", 64+512 }, { "0", 64+512 }, { "0", 64+512 }, { "0", 0+512 } } },
  2050. { { { "25", 283+512 }, { "25", 288+512 }, { "25", 288+512 }, { "25", 256+512 } } },
  2051. { { { "50", 502+512 }, { "50", 512+512 }, { "50", 512+512 }, { "50", 512+512 } } },
  2052. { { { "75", 721+512 }, { "75", 736+512 }, { "75", 736+512 }, { "75", 768+512 } } },
  2053. { { { "100", 940+512 }, { "100", 960+512 }, { "100", 960+512 }, { "100", 1024+512 } } },
  2054. { { { "125",1160+512 }, { "125",1184+512 }, { "125",1184+512 }, { "125", 1280+512 } } },
  2055. };
  2056. static const GraticuleLines aflat_ire12[] = {
  2057. { { { "-25", -624+2048 }, { "-25", -640+2048 }, { "-25", -640+2048 }, { "-25",-1024+2048 } } },
  2058. { { { "0", 256+2048 }, { "0", 256+2048 }, { "0", 256+2048 }, { "0", 0+2048 } } },
  2059. { { { "25", 1132+2048 }, { "25", 1152+2048 }, { "25", 1152+2048 }, { "25", 1024+2048 } } },
  2060. { { { "50", 2008+2048 }, { "50", 2048+2048 }, { "50", 2048+2048 }, { "50", 2048+2048 } } },
  2061. { { { "75", 2884+2048 }, { "75", 2944+2048 }, { "75", 2944+2048 }, { "75", 3072+2048 } } },
  2062. { { { "100", 3760+2048 }, { "100", 3840+2048 }, { "100", 3840+2048 }, { "100", 4096+2048 } } },
  2063. { { { "125", 4640+2048 }, { "125", 4736+2048 }, { "125", 4736+2048 }, { "125", 5120+2048 } } },
  2064. };
  2065. static const GraticuleLines flat_digital8[] = {
  2066. { { { "16", 16+256 }, { "16", 16+256 }, { "16", 16+256 }, { "0", 0+256 } } },
  2067. { { { "128", 128+256 }, { "128", 128+256 }, { "128", 128+256 }, { "128", 128+256 } } },
  2068. { { { "235", 235+256 }, { "240", 240+256 }, { "240", 240+256 }, { "255", 255+256 } } },
  2069. };
  2070. static const GraticuleLines flat_digital9[] = {
  2071. { { { "32", 32+512 }, { "32", 32+512 }, { "32", 32+512 }, { "0", 0+512 } } },
  2072. { { { "256", 256+512 }, { "256", 256+512 }, { "256", 256+512 }, { "256", 256+512 } } },
  2073. { { { "470", 470+512 }, { "480", 480+512 }, { "480", 480+512 }, { "511", 511+512 } } },
  2074. };
  2075. static const GraticuleLines flat_digital10[] = {
  2076. { { { "64", 64+1024 }, { "64", 64+1024 }, { "64", 64+1024 }, { "0", 0+1024 } } },
  2077. { { { "512", 512+1024 }, { "512", 512+1024 }, { "512", 512+1024 }, { "512", 512+1024 } } },
  2078. { { { "940", 940+1024 }, { "960", 960+1024 }, { "960", 960+1024 }, { "1023", 1023+1024 } } },
  2079. };
  2080. static const GraticuleLines flat_digital12[] = {
  2081. { { { "256", 256+4096 }, { "256", 256+4096 }, { "256", 256+4096 }, { "0", 0+4096 } } },
  2082. { { { "2048", 2048+4096 }, { "2048", 2048+4096 }, { "2048", 2048+4096 }, { "2048", 2048+4096 } } },
  2083. { { { "3760", 3760+4096 }, { "3840", 3840+4096 }, { "3840", 3840+4096 }, { "4095", 4095+4096 } } },
  2084. };
  2085. static const GraticuleLines flat_millivolts8[] = {
  2086. { { { "0", 16+256 }, { "0", 16+256 }, { "0", 16+256 }, { "0", 0+256 } } },
  2087. { { { "175", 71+256 }, { "175", 72+256 }, { "175", 72+256 }, { "175", 64+256 } } },
  2088. { { { "350", 126+256 }, { "350", 128+256 }, { "350", 128+256 }, { "350", 128+256 } } },
  2089. { { { "525", 180+256 }, { "525", 184+256 }, { "525", 184+256 }, { "525", 192+256 } } },
  2090. { { { "700", 235+256 }, { "700", 240+256 }, { "700", 240+256 }, { "700", 255+256 } } },
  2091. };
  2092. static const GraticuleLines flat_millivolts9[] = {
  2093. { { { "0", 32+512 }, { "0", 32+512 }, { "0", 32+512 }, { "0", 0+512 } } },
  2094. { { { "175", 142+512 }, { "175", 144+512 }, { "175", 144+512 }, { "175", 128+512 } } },
  2095. { { { "350", 251+512 }, { "350", 256+512 }, { "350", 256+512 }, { "350", 256+512 } } },
  2096. { { { "525", 361+512 }, { "525", 368+512 }, { "525", 368+512 }, { "525", 384+512 } } },
  2097. { { { "700", 470+512 }, { "700", 480+512 }, { "700", 480+512 }, { "700", 511+512 } } },
  2098. };
  2099. static const GraticuleLines flat_millivolts10[] = {
  2100. { { { "0", 64+1024 }, { "0", 64+1024 }, { "0", 64+1024 }, { "0", 0+1024 } } },
  2101. { { { "175", 283+1024 }, { "175", 288+1024 }, { "175", 288+1024 }, { "175", 256+1024 } } },
  2102. { { { "350", 502+1024 }, { "350", 512+1024 }, { "350", 512+1024 }, { "350", 512+1024 } } },
  2103. { { { "525", 721+1024 }, { "525", 736+1024 }, { "525", 736+1024 }, { "525", 768+1024 } } },
  2104. { { { "700", 940+1024 }, { "700", 960+1024 }, { "700", 960+1024 }, { "700", 1023+1024 } } },
  2105. };
  2106. static const GraticuleLines flat_millivolts12[] = {
  2107. { { { "0", 256+4096 }, { "0", 256+4096 }, { "0", 256+4096 }, { "0", 0+4096 } } },
  2108. { { { "175", 1132+4096 }, { "175", 1152+4096 }, { "175", 1152+4096 }, { "175", 1024+4096 } } },
  2109. { { { "350", 2008+4096 }, { "350", 2048+4096 }, { "350", 2048+4096 }, { "350", 2048+4096 } } },
  2110. { { { "525", 2884+4096 }, { "525", 2944+4096 }, { "525", 2944+4096 }, { "525", 3072+4096 } } },
  2111. { { { "700", 3760+4096 }, { "700", 3840+4096 }, { "700", 3840+4096 }, { "700", 4095+4096 } } },
  2112. };
  2113. static const GraticuleLines flat_ire8[] = {
  2114. { { { "-25", -39+256 }, { "-25", -40+256 }, { "-25", -40+256 }, { "-25", -64+256 } } },
  2115. { { { "0", 16+256 }, { "0", 16+256 }, { "0", 16+256 }, { "0", 0+256 } } },
  2116. { { { "25", 71+256 }, { "25", 72+256 }, { "25", 72+256 }, { "25", 64+256 } } },
  2117. { { { "50", 126+256 }, { "50", 128+256 }, { "50", 128+256 }, { "50", 128+256 } } },
  2118. { { { "75", 180+256 }, { "75", 184+256 }, { "75", 184+256 }, { "75", 192+256 } } },
  2119. { { { "100", 235+256 }, { "100", 240+256 }, { "100", 240+256 }, { "100", 256+256 } } },
  2120. { { { "125", 290+256 }, { "125", 296+256 }, { "125", 296+256 }, { "125", 320+256 } } },
  2121. };
  2122. static const GraticuleLines flat_ire9[] = {
  2123. { { { "-25", -78+512 }, { "-25", -80+512 }, { "-25", -80+512 }, { "-25",-128+512 } } },
  2124. { { { "0", 32+512 }, { "0", 32+512 }, { "0", 32+512 }, { "0", 0+512 } } },
  2125. { { { "25", 142+512 }, { "25", 144+512 }, { "25", 144+512 }, { "25", 128+512 } } },
  2126. { { { "50", 251+512 }, { "50", 256+512 }, { "50", 256+512 }, { "50", 256+512 } } },
  2127. { { { "75", 361+512 }, { "75", 368+512 }, { "75", 368+512 }, { "75", 384+512 } } },
  2128. { { { "100", 470+512 }, { "100", 480+512 }, { "100", 480+512 }, { "100", 512+512 } } },
  2129. { { { "125", 580+512 }, { "125", 592+512 }, { "125", 592+512 }, { "125", 640+512 } } },
  2130. };
  2131. static const GraticuleLines flat_ire10[] = {
  2132. { { { "-25",-156+1024 }, { "-25",-160+1024 }, { "-25",-160+1024 }, { "-25", -256+1024 } } },
  2133. { { { "0", 64+1024 }, { "0", 64+1024 }, { "0", 64+1024 }, { "0", 0+1024 } } },
  2134. { { { "25", 283+1024 }, { "25", 288+1024 }, { "25", 288+1024 }, { "25", 256+1024 } } },
  2135. { { { "50", 502+1024 }, { "50", 512+1024 }, { "50", 512+1024 }, { "50", 512+1024 } } },
  2136. { { { "75", 721+1024 }, { "75", 736+1024 }, { "75", 736+1024 }, { "75", 768+1024 } } },
  2137. { { { "100", 940+1024 }, { "100", 960+1024 }, { "100", 960+1024 }, { "100", 1024+1024 } } },
  2138. { { { "125",1160+1024 }, { "125",1184+1024 }, { "125",1184+1024 }, { "125", 1280+1024 } } },
  2139. };
  2140. static const GraticuleLines flat_ire12[] = {
  2141. { { { "-25", -624+4096 }, { "-25", -640+4096 }, { "-25", -640+4096 }, { "-25",-1024+4096 } } },
  2142. { { { "0", 256+4096 }, { "0", 256+4096 }, { "0", 256+4096 }, { "0", 0+4096 } } },
  2143. { { { "25", 1132+4096 }, { "25", 1152+4096 }, { "25", 1152+4096 }, { "25", 1024+4096 } } },
  2144. { { { "50", 2008+4096 }, { "50", 2048+4096 }, { "50", 2048+4096 }, { "50", 2048+4096 } } },
  2145. { { { "75", 2884+4096 }, { "75", 2944+4096 }, { "75", 2944+4096 }, { "75", 3072+4096 } } },
  2146. { { { "100", 3760+4096 }, { "100", 3840+4096 }, { "100", 3840+4096 }, { "100", 4096+4096 } } },
  2147. { { { "125", 4640+4096 }, { "125", 4736+4096 }, { "125", 4736+4096 }, { "125", 5120+4096 } } },
  2148. };
  2149. static const GraticuleLines digital8[] = {
  2150. { { { "16", 16 }, { "16", 16 }, { "16", 16 }, { "0", 0 } } },
  2151. { { { "128", 128 }, { "128", 128 }, { "128", 128 }, { "128", 128 } } },
  2152. { { { "235", 235 }, { "240", 240 }, { "240", 240 }, { "255", 255 } } },
  2153. };
  2154. static const GraticuleLines digital9[] = {
  2155. { { { "32", 32 }, { "32", 32 }, { "32", 32 }, { "0", 0 } } },
  2156. { { { "256", 256 }, { "256", 256 }, { "256", 256 }, { "256", 256 } } },
  2157. { { { "470", 470 }, { "480", 480 }, { "480", 480 }, { "511", 511 } } },
  2158. };
  2159. static const GraticuleLines digital10[] = {
  2160. { { { "64", 64 }, { "64", 64 }, { "64", 64 }, { "0", 0 } } },
  2161. { { { "512", 512 }, { "512", 512 }, { "512", 512 }, { "512", 512 } } },
  2162. { { { "940", 940 }, { "960", 960 }, { "960", 960 }, { "1023", 1023 } } },
  2163. };
  2164. static const GraticuleLines digital12[] = {
  2165. { { { "256", 256 }, { "256", 256 }, { "256", 256 }, { "0", 0 } } },
  2166. { { { "2048", 2048 }, { "2048", 2048 }, { "2048", 2048 }, { "2048", 2048 } } },
  2167. { { { "3760", 3760 }, { "3840", 3840 }, { "3840", 3840 }, { "4095", 4095 } } },
  2168. };
  2169. static const GraticuleLines millivolts8[] = {
  2170. { { { "0", 16 }, { "0", 16 }, { "0", 16 }, { "0", 0 } } },
  2171. { { { "175", 71 }, { "175", 72 }, { "175", 72 }, { "175", 64 } } },
  2172. { { { "350", 126 }, { "350", 128 }, { "350", 128 }, { "350", 128 } } },
  2173. { { { "525", 180 }, { "525", 184 }, { "525", 184 }, { "525", 192 } } },
  2174. { { { "700", 235 }, { "700", 240 }, { "700", 240 }, { "700", 255 } } },
  2175. };
  2176. static const GraticuleLines millivolts9[] = {
  2177. { { { "0", 32 }, { "0", 32 }, { "0", 32 }, { "0", 0 } } },
  2178. { { { "175", 142 }, { "175", 144 }, { "175", 144 }, { "175", 128 } } },
  2179. { { { "350", 251 }, { "350", 256 }, { "350", 256 }, { "350", 256 } } },
  2180. { { { "525", 361 }, { "525", 368 }, { "525", 368 }, { "525", 384 } } },
  2181. { { { "700", 470 }, { "700", 480 }, { "700", 480 }, { "700", 511 } } },
  2182. };
  2183. static const GraticuleLines millivolts10[] = {
  2184. { { { "0", 64 }, { "0", 64 }, { "0", 64 }, { "0", 0 } } },
  2185. { { { "175", 283 }, { "175", 288 }, { "175", 288 }, { "175", 256 } } },
  2186. { { { "350", 502 }, { "350", 512 }, { "350", 512 }, { "350", 512 } } },
  2187. { { { "525", 721 }, { "525", 736 }, { "525", 736 }, { "525", 768 } } },
  2188. { { { "700", 940 }, { "700", 960 }, { "700", 960 }, { "700", 1023 } } },
  2189. };
  2190. static const GraticuleLines millivolts12[] = {
  2191. { { { "0", 256 }, { "0", 256 }, { "0", 256 }, { "0", 0 } } },
  2192. { { { "175", 1132 }, { "175", 1152 }, { "175", 1152 }, { "175", 1024 } } },
  2193. { { { "350", 2008 }, { "350", 2048 }, { "350", 2048 }, { "350", 2048 } } },
  2194. { { { "525", 2884 }, { "525", 2944 }, { "525", 2944 }, { "525", 3072 } } },
  2195. { { { "700", 3760 }, { "700", 3840 }, { "700", 3840 }, { "700", 4095 } } },
  2196. };
  2197. static const GraticuleLines ire8[] = {
  2198. { { { "0", 16 }, { "0", 16 }, { "0", 16 }, { "0", 0 } } },
  2199. { { { "25", 71 }, { "25", 72 }, { "25", 72 }, { "25", 64 } } },
  2200. { { { "50", 126 }, { "50", 128 }, { "50", 128 }, { "50", 128 } } },
  2201. { { { "75", 180 }, { "75", 184 }, { "75", 184 }, { "75", 192 } } },
  2202. { { { "100", 235 }, { "100", 240 }, { "100", 240 }, { "100", 255 } } },
  2203. };
  2204. static const GraticuleLines ire9[] = {
  2205. { { { "0", 32 }, { "0", 32 }, { "0", 32 }, { "0", 0 } } },
  2206. { { { "25", 142 }, { "25", 144 }, { "25", 144 }, { "25", 128 } } },
  2207. { { { "50", 251 }, { "50", 256 }, { "50", 256 }, { "50", 256 } } },
  2208. { { { "75", 361 }, { "75", 368 }, { "75", 368 }, { "75", 384 } } },
  2209. { { { "100", 470 }, { "100", 480 }, { "100", 480 }, { "100", 511 } } },
  2210. };
  2211. static const GraticuleLines ire10[] = {
  2212. { { { "0", 64 }, { "0", 64 }, { "0", 64 }, { "0", 0 } } },
  2213. { { { "25", 283 }, { "25", 288 }, { "25", 288 }, { "25", 256 } } },
  2214. { { { "50", 502 }, { "50", 512 }, { "50", 512 }, { "50", 512 } } },
  2215. { { { "75", 721 }, { "75", 736 }, { "75", 736 }, { "75", 768 } } },
  2216. { { { "100", 940 }, { "100", 960 }, { "100", 960 }, { "100", 1023 } } },
  2217. };
  2218. static const GraticuleLines ire12[] = {
  2219. { { { "0", 256 }, { "0", 256 }, { "0", 256 }, { "0", 0 } } },
  2220. { { { "25", 1132 }, { "25", 1152 }, { "25", 1152 }, { "25", 1024 } } },
  2221. { { { "50", 2008 }, { "50", 2048 }, { "50", 2048 }, { "50", 2048 } } },
  2222. { { { "75", 2884 }, { "75", 2944 }, { "75", 2944 }, { "75", 3072 } } },
  2223. { { { "100", 3760 }, { "100", 3840 }, { "100", 3840 }, { "100", 4095 } } },
  2224. };
  2225. static const GraticuleLines chroma_digital8[] = {
  2226. { { { "50", 50 }, { "50", 50 }, { "50", 50 }, { "50", 50 } } },
  2227. { { { "100", 100 }, { "100", 100 }, { "100", 100 }, { "100", 100 } } },
  2228. { { { "150", 150 }, { "150", 150 }, { "150", 150 }, { "150", 150 } } },
  2229. { { { "200", 200 }, { "200", 200 }, { "200", 200 }, { "200", 200 } } },
  2230. { { { "255", 255 }, { "255", 255 }, { "255", 255 }, { "255", 255 } } },
  2231. };
  2232. static const GraticuleLines chroma_digital9[] = {
  2233. { { { "100", 100 }, { "100", 100 }, { "100", 100 }, { "100", 100 } } },
  2234. { { { "200", 200 }, { "200", 200 }, { "200", 200 }, { "200", 200 } } },
  2235. { { { "300", 300 }, { "300", 300 }, { "300", 300 }, { "300", 300 } } },
  2236. { { { "400", 400 }, { "400", 400 }, { "400", 400 }, { "400", 400 } } },
  2237. { { { "500", 500 }, { "500", 500 }, { "500", 500 }, { "500", 500 } } },
  2238. };
  2239. static const GraticuleLines chroma_digital10[] = {
  2240. { { { "200", 200 }, { "200", 200 }, { "200", 200 }, { "200", 200 } } },
  2241. { { { "400", 400 }, { "400", 400 }, { "400", 400 }, { "400", 400 } } },
  2242. { { { "600", 600 }, { "600", 600 }, { "600", 600 }, { "600", 600 } } },
  2243. { { { "800", 800 }, { "800", 800 }, { "800", 800 }, { "800", 800 } } },
  2244. { { {"1000",1000 }, {"1000",1000 }, {"1000",1000 }, {"1000",1000 } } },
  2245. };
  2246. static const GraticuleLines chroma_digital12[] = {
  2247. { { { "800", 800 }, { "800", 800 }, { "800", 800 }, { "800", 800 } } },
  2248. { { { "1600", 1600 }, { "1600", 1600 }, { "1600", 1600 }, { "1600", 1600 } } },
  2249. { { { "2400", 2400 }, { "2400", 2400 }, { "2400", 2400 }, { "2400", 2400 } } },
  2250. { { { "3200", 3200 }, { "3200", 3200 }, { "3200", 3200 }, { "3200", 3200 } } },
  2251. { { { "4000", 4000 }, { "4000", 4000 }, { "4000", 4000 }, { "4000", 4000 } } },
  2252. };
  2253. static void blend_vline(uint8_t *dst, int height, int linesize, float o1, float o2, int v, int step)
  2254. {
  2255. int y;
  2256. for (y = 0; y < height; y += step) {
  2257. dst[0] = v * o1 + dst[0] * o2;
  2258. dst += linesize * step;
  2259. }
  2260. }
  2261. static void blend_vline16(uint16_t *dst, int height, int linesize, float o1, float o2, int v, int step)
  2262. {
  2263. int y;
  2264. for (y = 0; y < height; y += step) {
  2265. dst[0] = v * o1 + dst[0] * o2;
  2266. dst += (linesize / 2) * step;
  2267. }
  2268. }
  2269. static void blend_hline(uint8_t *dst, int width, float o1, float o2, int v, int step)
  2270. {
  2271. int x;
  2272. for (x = 0; x < width; x += step) {
  2273. dst[x] = v * o1 + dst[x] * o2;
  2274. }
  2275. }
  2276. static void blend_hline16(uint16_t *dst, int width, float o1, float o2, int v, int step)
  2277. {
  2278. int x;
  2279. for (x = 0; x < width; x += step) {
  2280. dst[x] = v * o1 + dst[x] * o2;
  2281. }
  2282. }
  2283. static void draw_htext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4])
  2284. {
  2285. const uint8_t *font;
  2286. int font_height;
  2287. int i, plane;
  2288. font = avpriv_cga_font, font_height = 8;
  2289. for (plane = 0; plane < 4 && out->data[plane]; plane++) {
  2290. for (i = 0; txt[i]; i++) {
  2291. int char_y, mask;
  2292. int v = color[plane];
  2293. uint8_t *p = out->data[plane] + y * out->linesize[plane] + (x + i * 8);
  2294. for (char_y = 0; char_y < font_height; char_y++) {
  2295. for (mask = 0x80; mask; mask >>= 1) {
  2296. if (font[txt[i] * font_height + char_y] & mask)
  2297. p[0] = p[0] * o2 + v * o1;
  2298. p++;
  2299. }
  2300. p += out->linesize[plane] - 8;
  2301. }
  2302. }
  2303. }
  2304. }
  2305. static void draw_htext16(AVFrame *out, int x, int y, int mult, float o1, float o2, const char *txt, const uint8_t color[4])
  2306. {
  2307. const uint8_t *font;
  2308. int font_height;
  2309. int i, plane;
  2310. font = avpriv_cga_font, font_height = 8;
  2311. for (plane = 0; plane < 4 && out->data[plane]; plane++) {
  2312. for (i = 0; txt[i]; i++) {
  2313. int char_y, mask;
  2314. int v = color[plane] * mult;
  2315. uint16_t *p = (uint16_t *)(out->data[plane] + y * out->linesize[plane]) + (x + i * 8);
  2316. for (char_y = 0; char_y < font_height; char_y++) {
  2317. for (mask = 0x80; mask; mask >>= 1) {
  2318. if (font[txt[i] * font_height + char_y] & mask)
  2319. p[0] = p[0] * o2 + v * o1;
  2320. p++;
  2321. }
  2322. p += out->linesize[plane] / 2 - 8;
  2323. }
  2324. }
  2325. }
  2326. }
  2327. static void draw_vtext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4])
  2328. {
  2329. const uint8_t *font;
  2330. int font_height;
  2331. int i, plane;
  2332. font = avpriv_cga_font, font_height = 8;
  2333. for (plane = 0; plane < 4 && out->data[plane]; plane++) {
  2334. for (i = 0; txt[i]; i++) {
  2335. int char_y, mask;
  2336. int v = color[plane];
  2337. for (char_y = font_height - 1; char_y >= 0; char_y--) {
  2338. uint8_t *p = out->data[plane] + (y + i * 10) * out->linesize[plane] + x;
  2339. for (mask = 0x80; mask; mask >>= 1) {
  2340. if (font[txt[i] * font_height + font_height - 1 - char_y] & mask)
  2341. p[char_y] = p[char_y] * o2 + v * o1;
  2342. p += out->linesize[plane];
  2343. }
  2344. }
  2345. }
  2346. }
  2347. }
  2348. static void draw_vtext16(AVFrame *out, int x, int y, int mult, float o1, float o2, const char *txt, const uint8_t color[4])
  2349. {
  2350. const uint8_t *font;
  2351. int font_height;
  2352. int i, plane;
  2353. font = avpriv_cga_font, font_height = 8;
  2354. for (plane = 0; plane < 4 && out->data[plane]; plane++) {
  2355. for (i = 0; txt[i]; i++) {
  2356. int char_y, mask;
  2357. int v = color[plane] * mult;
  2358. for (char_y = 0; char_y < font_height; char_y++) {
  2359. uint16_t *p = (uint16_t *)(out->data[plane] + (y + i * 10) * out->linesize[plane]) + x;
  2360. for (mask = 0x80; mask; mask >>= 1) {
  2361. if (font[txt[i] * font_height + font_height - 1 - char_y] & mask)
  2362. p[char_y] = p[char_y] * o2 + v * o1;
  2363. p += out->linesize[plane] / 2;
  2364. }
  2365. }
  2366. }
  2367. }
  2368. }
  2369. static void graticule_none(WaveformContext *s, AVFrame *out)
  2370. {
  2371. }
  2372. static void graticule_row(WaveformContext *s, AVFrame *out)
  2373. {
  2374. const int step = (s->flags & 2) + 1;
  2375. const float o1 = s->opacity;
  2376. const float o2 = 1. - o1;
  2377. const int height = s->display == PARADE ? out->height / s->acomp : out->height;
  2378. int C, k = 0, c, p, l, offset_x = 0, offset_y = 0;
  2379. for (c = 0; c < s->ncomp; c++) {
  2380. if (!((1 << c) & s->pcomp) || (!s->display && k > 0))
  2381. continue;
  2382. k++;
  2383. C = s->rgb ? 0 : c;
  2384. for (p = 0; p < s->ncomp; p++) {
  2385. const int v = s->grat_yuva_color[p];
  2386. for (l = 0; l < s->nb_glines; l++) {
  2387. const uint16_t pos = s->glines[l].line[C].pos;
  2388. int x = offset_x + (s->mirror ? s->size - 1 - pos : pos);
  2389. uint8_t *dst = out->data[p] + offset_y * out->linesize[p] + x;
  2390. blend_vline(dst, height, out->linesize[p], o1, o2, v, step);
  2391. }
  2392. }
  2393. for (l = 0; l < s->nb_glines && (s->flags & 1); l++) {
  2394. const char *name = s->glines[l].line[C].name;
  2395. const uint16_t pos = s->glines[l].line[C].pos;
  2396. int x = offset_x + (s->mirror ? s->size - 1 - pos : pos) - 10;
  2397. if (x < 0)
  2398. x = 4;
  2399. draw_vtext(out, x, offset_y + 2, o1, o2, name, s->grat_yuva_color);
  2400. }
  2401. offset_x += s->size * (s->display == STACK);
  2402. offset_y += height * (s->display == PARADE);
  2403. }
  2404. }
  2405. static void graticule16_row(WaveformContext *s, AVFrame *out)
  2406. {
  2407. const int step = (s->flags & 2) + 1;
  2408. const float o1 = s->opacity;
  2409. const float o2 = 1. - o1;
  2410. const int mult = s->max / 256;
  2411. const int height = s->display == PARADE ? out->height / s->acomp : out->height;
  2412. int C, k = 0, c, p, l, offset_x = 0, offset_y = 0;
  2413. for (c = 0; c < s->ncomp; c++) {
  2414. if (!((1 << c) & s->pcomp) || (!s->display && k > 0))
  2415. continue;
  2416. k++;
  2417. C = s->rgb ? 0 : c;
  2418. for (p = 0; p < s->ncomp; p++) {
  2419. const int v = s->grat_yuva_color[p] * mult;
  2420. for (l = 0; l < s->nb_glines ; l++) {
  2421. const uint16_t pos = s->glines[l].line[C].pos;
  2422. int x = offset_x + (s->mirror ? s->size - 1 - pos : pos);
  2423. uint16_t *dst = (uint16_t *)(out->data[p] + offset_y * out->linesize[p]) + x;
  2424. blend_vline16(dst, height, out->linesize[p], o1, o2, v, step);
  2425. }
  2426. }
  2427. for (l = 0; l < s->nb_glines && (s->flags & 1); l++) {
  2428. const char *name = s->glines[l].line[C].name;
  2429. const uint16_t pos = s->glines[l].line[C].pos;
  2430. int x = offset_x + (s->mirror ? s->size - 1 - pos : pos) - 10;
  2431. if (x < 0)
  2432. x = 4;
  2433. draw_vtext16(out, x, offset_y + 2, mult, o1, o2, name, s->grat_yuva_color);
  2434. }
  2435. offset_x += s->size * (s->display == STACK);
  2436. offset_y += height * (s->display == PARADE);
  2437. }
  2438. }
  2439. static void graticule_column(WaveformContext *s, AVFrame *out)
  2440. {
  2441. const int step = (s->flags & 2) + 1;
  2442. const float o1 = s->opacity;
  2443. const float o2 = 1. - o1;
  2444. const int width = s->display == PARADE ? out->width / s->acomp : out->width;
  2445. int C, k = 0, c, p, l, offset_y = 0, offset_x = 0;
  2446. for (c = 0; c < s->ncomp; c++) {
  2447. if ((!((1 << c) & s->pcomp) || (!s->display && k > 0)))
  2448. continue;
  2449. k++;
  2450. C = s->rgb ? 0 : c;
  2451. for (p = 0; p < s->ncomp; p++) {
  2452. const int v = s->grat_yuva_color[p];
  2453. for (l = 0; l < s->nb_glines ; l++) {
  2454. const uint16_t pos = s->glines[l].line[C].pos;
  2455. int y = offset_y + (s->mirror ? s->size - 1 - pos : pos);
  2456. uint8_t *dst = out->data[p] + y * out->linesize[p] + offset_x;
  2457. blend_hline(dst, width, o1, o2, v, step);
  2458. }
  2459. }
  2460. for (l = 0; l < s->nb_glines && (s->flags & 1); l++) {
  2461. const char *name = s->glines[l].line[C].name;
  2462. const uint16_t pos = s->glines[l].line[C].pos;
  2463. int y = offset_y + (s->mirror ? s->size - 1 - pos : pos) - 10;
  2464. if (y < 0)
  2465. y = 4;
  2466. draw_htext(out, 2 + offset_x, y, o1, o2, name, s->grat_yuva_color);
  2467. }
  2468. offset_y += s->size * (s->display == STACK);
  2469. offset_x += width * (s->display == PARADE);
  2470. }
  2471. }
  2472. static void graticule16_column(WaveformContext *s, AVFrame *out)
  2473. {
  2474. const int step = (s->flags & 2) + 1;
  2475. const float o1 = s->opacity;
  2476. const float o2 = 1. - o1;
  2477. const int mult = s->max / 256;
  2478. const int width = s->display == PARADE ? out->width / s->acomp : out->width;
  2479. int C, k = 0, c, p, l, offset_x = 0, offset_y = 0;
  2480. for (c = 0; c < s->ncomp; c++) {
  2481. if ((!((1 << c) & s->pcomp) || (!s->display && k > 0)))
  2482. continue;
  2483. k++;
  2484. C = s->rgb ? 0 : c;
  2485. for (p = 0; p < s->ncomp; p++) {
  2486. const int v = s->grat_yuva_color[p] * mult;
  2487. for (l = 0; l < s->nb_glines ; l++) {
  2488. const uint16_t pos = s->glines[l].line[C].pos;
  2489. int y = offset_y + (s->mirror ? s->size - 1 - pos : pos);
  2490. uint16_t *dst = (uint16_t *)(out->data[p] + y * out->linesize[p]) + offset_x;
  2491. blend_hline16(dst, width, o1, o2, v, step);
  2492. }
  2493. }
  2494. for (l = 0; l < s->nb_glines && (s->flags & 1); l++) {
  2495. const char *name = s->glines[l].line[C].name;
  2496. const uint16_t pos = s->glines[l].line[C].pos;
  2497. int y = offset_y + (s->mirror ? s->size - 1 - pos: pos) - 10;
  2498. if (y < 0)
  2499. y = 4;
  2500. draw_htext16(out, 2 + offset_x, y, mult, o1, o2, name, s->grat_yuva_color);
  2501. }
  2502. offset_y += s->size * (s->display == STACK);
  2503. offset_x += width * (s->display == PARADE);
  2504. }
  2505. }
  2506. static int config_input(AVFilterLink *inlink)
  2507. {
  2508. AVFilterContext *ctx = inlink->dst;
  2509. WaveformContext *s = ctx->priv;
  2510. s->desc = av_pix_fmt_desc_get(inlink->format);
  2511. s->ncomp = s->desc->nb_components;
  2512. s->bits = s->desc->comp[0].depth;
  2513. s->max = 1 << s->bits;
  2514. s->intensity = s->fintensity * (s->max - 1);
  2515. s->shift_w[0] = s->shift_w[3] = 0;
  2516. s->shift_h[0] = s->shift_h[3] = 0;
  2517. s->shift_w[1] = s->shift_w[2] = s->desc->log2_chroma_w;
  2518. s->shift_h[1] = s->shift_h[2] = s->desc->log2_chroma_h;
  2519. s->graticulef = graticule_none;
  2520. switch (s->filter) {
  2521. case XFLAT:
  2522. case AFLAT: s->size = 256 * 2; break;
  2523. case FLAT: s->size = 256 * 3; break;
  2524. default: s->size = 256; break;
  2525. }
  2526. switch (s->filter | ((s->bits > 8) << 4) |
  2527. (s->mode << 8) | (s->mirror << 12)) {
  2528. case 0x1100: s->waveform_slice = lowpass_column_mirror; break;
  2529. case 0x1000: s->waveform_slice = lowpass_row_mirror; break;
  2530. case 0x0100: s->waveform_slice = lowpass_column; break;
  2531. case 0x0000: s->waveform_slice = lowpass_row; break;
  2532. case 0x1110: s->waveform_slice = lowpass16_column_mirror; break;
  2533. case 0x1010: s->waveform_slice = lowpass16_row_mirror; break;
  2534. case 0x0110: s->waveform_slice = lowpass16_column; break;
  2535. case 0x0010: s->waveform_slice = lowpass16_row; break;
  2536. case 0x1101: s->waveform_slice = flat_column_mirror; break;
  2537. case 0x1001: s->waveform_slice = flat_row_mirror; break;
  2538. case 0x0101: s->waveform_slice = flat_column; break;
  2539. case 0x0001: s->waveform_slice = flat_row; break;
  2540. case 0x1111: s->waveform_slice = flat16_column_mirror; break;
  2541. case 0x1011: s->waveform_slice = flat16_row_mirror; break;
  2542. case 0x0111: s->waveform_slice = flat16_column; break;
  2543. case 0x0011: s->waveform_slice = flat16_row; break;
  2544. case 0x1102: s->waveform_slice = aflat_column_mirror; break;
  2545. case 0x1002: s->waveform_slice = aflat_row_mirror; break;
  2546. case 0x0102: s->waveform_slice = aflat_column; break;
  2547. case 0x0002: s->waveform_slice = aflat_row; break;
  2548. case 0x1112: s->waveform_slice = aflat16_column_mirror; break;
  2549. case 0x1012: s->waveform_slice = aflat16_row_mirror; break;
  2550. case 0x0112: s->waveform_slice = aflat16_column; break;
  2551. case 0x0012: s->waveform_slice = aflat16_row; break;
  2552. case 0x1103: s->waveform_slice = chroma_column_mirror; break;
  2553. case 0x1003: s->waveform_slice = chroma_row_mirror; break;
  2554. case 0x0103: s->waveform_slice = chroma_column; break;
  2555. case 0x0003: s->waveform_slice = chroma_row; break;
  2556. case 0x1113: s->waveform_slice = chroma16_column_mirror; break;
  2557. case 0x1013: s->waveform_slice = chroma16_row_mirror; break;
  2558. case 0x0113: s->waveform_slice = chroma16_column; break;
  2559. case 0x0013: s->waveform_slice = chroma16_row; break;
  2560. case 0x1104: s->waveform_slice = color_column_mirror; break;
  2561. case 0x1004: s->waveform_slice = color_row_mirror; break;
  2562. case 0x0104: s->waveform_slice = color_column; break;
  2563. case 0x0004: s->waveform_slice = color_row; break;
  2564. case 0x1114: s->waveform_slice = color16_column_mirror; break;
  2565. case 0x1014: s->waveform_slice = color16_row_mirror; break;
  2566. case 0x0114: s->waveform_slice = color16_column; break;
  2567. case 0x0014: s->waveform_slice = color16_row; break;
  2568. case 0x1105: s->waveform_slice = acolor_column_mirror; break;
  2569. case 0x1005: s->waveform_slice = acolor_row_mirror; break;
  2570. case 0x0105: s->waveform_slice = acolor_column; break;
  2571. case 0x0005: s->waveform_slice = acolor_row; break;
  2572. case 0x1115: s->waveform_slice = acolor16_column_mirror; break;
  2573. case 0x1015: s->waveform_slice = acolor16_row_mirror; break;
  2574. case 0x0115: s->waveform_slice = acolor16_column; break;
  2575. case 0x0015: s->waveform_slice = acolor16_row; break;
  2576. case 0x1106: s->waveform_slice = xflat_column_mirror; break;
  2577. case 0x1006: s->waveform_slice = xflat_row_mirror; break;
  2578. case 0x0106: s->waveform_slice = xflat_column; break;
  2579. case 0x0006: s->waveform_slice = xflat_row; break;
  2580. case 0x1116: s->waveform_slice = xflat16_column_mirror; break;
  2581. case 0x1016: s->waveform_slice = xflat16_row_mirror; break;
  2582. case 0x0116: s->waveform_slice = xflat16_column; break;
  2583. case 0x0016: s->waveform_slice = xflat16_row; break;
  2584. }
  2585. s->grat_yuva_color[0] = 255;
  2586. s->grat_yuva_color[2] = s->graticule == 2 ? 255 : 0;
  2587. s->grat_yuva_color[3] = 255;
  2588. switch (s->filter) {
  2589. case LOWPASS:
  2590. case COLOR:
  2591. case ACOLOR:
  2592. case CHROMA:
  2593. case AFLAT:
  2594. case XFLAT:
  2595. case FLAT:
  2596. if (s->graticule && s->mode == 1)
  2597. s->graticulef = s->bits > 8 ? graticule16_column : graticule_column;
  2598. else if (s->graticule && s->mode == 0)
  2599. s->graticulef = s->bits > 8 ? graticule16_row : graticule_row;
  2600. break;
  2601. }
  2602. switch (s->filter) {
  2603. case COLOR:
  2604. case ACOLOR:
  2605. case LOWPASS:
  2606. switch (s->scale) {
  2607. case DIGITAL:
  2608. switch (s->bits) {
  2609. case 8: s->glines = (GraticuleLines *)digital8; s->nb_glines = FF_ARRAY_ELEMS(digital8); break;
  2610. case 9: s->glines = (GraticuleLines *)digital9; s->nb_glines = FF_ARRAY_ELEMS(digital9); break;
  2611. case 10: s->glines = (GraticuleLines *)digital10; s->nb_glines = FF_ARRAY_ELEMS(digital10); break;
  2612. case 12: s->glines = (GraticuleLines *)digital12; s->nb_glines = FF_ARRAY_ELEMS(digital12); break;
  2613. }
  2614. break;
  2615. case MILLIVOLTS:
  2616. switch (s->bits) {
  2617. case 8: s->glines = (GraticuleLines *)millivolts8; s->nb_glines = FF_ARRAY_ELEMS(millivolts8); break;
  2618. case 9: s->glines = (GraticuleLines *)millivolts9; s->nb_glines = FF_ARRAY_ELEMS(millivolts9); break;
  2619. case 10: s->glines = (GraticuleLines *)millivolts10; s->nb_glines = FF_ARRAY_ELEMS(millivolts10); break;
  2620. case 12: s->glines = (GraticuleLines *)millivolts12; s->nb_glines = FF_ARRAY_ELEMS(millivolts12); break;
  2621. }
  2622. break;
  2623. case IRE:
  2624. switch (s->bits) {
  2625. case 8: s->glines = (GraticuleLines *)ire8; s->nb_glines = FF_ARRAY_ELEMS(ire8); break;
  2626. case 9: s->glines = (GraticuleLines *)ire9; s->nb_glines = FF_ARRAY_ELEMS(ire9); break;
  2627. case 10: s->glines = (GraticuleLines *)ire10; s->nb_glines = FF_ARRAY_ELEMS(ire10); break;
  2628. case 12: s->glines = (GraticuleLines *)ire12; s->nb_glines = FF_ARRAY_ELEMS(ire12); break;
  2629. }
  2630. break;
  2631. }
  2632. break;
  2633. case CHROMA:
  2634. switch (s->scale) {
  2635. case DIGITAL:
  2636. switch (s->bits) {
  2637. case 8: s->glines = (GraticuleLines *)chroma_digital8; s->nb_glines = FF_ARRAY_ELEMS(chroma_digital8); break;
  2638. case 9: s->glines = (GraticuleLines *)chroma_digital9; s->nb_glines = FF_ARRAY_ELEMS(chroma_digital9); break;
  2639. case 10: s->glines = (GraticuleLines *)chroma_digital10; s->nb_glines = FF_ARRAY_ELEMS(chroma_digital10); break;
  2640. case 12: s->glines = (GraticuleLines *)chroma_digital12; s->nb_glines = FF_ARRAY_ELEMS(chroma_digital12); break;
  2641. }
  2642. break;
  2643. case MILLIVOLTS:
  2644. switch (s->bits) {
  2645. case 8: s->glines = (GraticuleLines *)millivolts8; s->nb_glines = FF_ARRAY_ELEMS(millivolts8); break;
  2646. case 9: s->glines = (GraticuleLines *)millivolts9; s->nb_glines = FF_ARRAY_ELEMS(millivolts9); break;
  2647. case 10: s->glines = (GraticuleLines *)millivolts10; s->nb_glines = FF_ARRAY_ELEMS(millivolts10); break;
  2648. case 12: s->glines = (GraticuleLines *)millivolts12; s->nb_glines = FF_ARRAY_ELEMS(millivolts12); break;
  2649. }
  2650. break;
  2651. case IRE:
  2652. switch (s->bits) {
  2653. case 8: s->glines = (GraticuleLines *)ire8; s->nb_glines = FF_ARRAY_ELEMS(ire8); break;
  2654. case 9: s->glines = (GraticuleLines *)ire9; s->nb_glines = FF_ARRAY_ELEMS(ire9); break;
  2655. case 10: s->glines = (GraticuleLines *)ire10; s->nb_glines = FF_ARRAY_ELEMS(ire10); break;
  2656. case 12: s->glines = (GraticuleLines *)ire12; s->nb_glines = FF_ARRAY_ELEMS(ire12); break;
  2657. }
  2658. break;
  2659. }
  2660. break;
  2661. case XFLAT:
  2662. case AFLAT:
  2663. switch (s->scale) {
  2664. case DIGITAL:
  2665. switch (s->bits) {
  2666. case 8: s->glines = (GraticuleLines *)aflat_digital8; s->nb_glines = FF_ARRAY_ELEMS(aflat_digital8); break;
  2667. case 9: s->glines = (GraticuleLines *)aflat_digital9; s->nb_glines = FF_ARRAY_ELEMS(aflat_digital9); break;
  2668. case 10: s->glines = (GraticuleLines *)aflat_digital10; s->nb_glines = FF_ARRAY_ELEMS(aflat_digital10); break;
  2669. case 12: s->glines = (GraticuleLines *)aflat_digital12; s->nb_glines = FF_ARRAY_ELEMS(aflat_digital12); break;
  2670. }
  2671. break;
  2672. case MILLIVOLTS:
  2673. switch (s->bits) {
  2674. case 8: s->glines = (GraticuleLines *)aflat_millivolts8; s->nb_glines = FF_ARRAY_ELEMS(aflat_millivolts8); break;
  2675. case 9: s->glines = (GraticuleLines *)aflat_millivolts9; s->nb_glines = FF_ARRAY_ELEMS(aflat_millivolts9); break;
  2676. case 10: s->glines = (GraticuleLines *)aflat_millivolts10; s->nb_glines = FF_ARRAY_ELEMS(aflat_millivolts10); break;
  2677. case 12: s->glines = (GraticuleLines *)aflat_millivolts12; s->nb_glines = FF_ARRAY_ELEMS(aflat_millivolts12); break;
  2678. }
  2679. break;
  2680. case IRE:
  2681. switch (s->bits) {
  2682. case 8: s->glines = (GraticuleLines *)aflat_ire8; s->nb_glines = FF_ARRAY_ELEMS(aflat_ire8); break;
  2683. case 9: s->glines = (GraticuleLines *)aflat_ire9; s->nb_glines = FF_ARRAY_ELEMS(aflat_ire9); break;
  2684. case 10: s->glines = (GraticuleLines *)aflat_ire10; s->nb_glines = FF_ARRAY_ELEMS(aflat_ire10); break;
  2685. case 12: s->glines = (GraticuleLines *)aflat_ire12; s->nb_glines = FF_ARRAY_ELEMS(aflat_ire12); break;
  2686. }
  2687. break;
  2688. }
  2689. break;
  2690. case FLAT:
  2691. switch (s->scale) {
  2692. case DIGITAL:
  2693. switch (s->bits) {
  2694. case 8: s->glines = (GraticuleLines *)flat_digital8; s->nb_glines = FF_ARRAY_ELEMS(flat_digital8); break;
  2695. case 9: s->glines = (GraticuleLines *)flat_digital9; s->nb_glines = FF_ARRAY_ELEMS(flat_digital9); break;
  2696. case 10: s->glines = (GraticuleLines *)flat_digital10; s->nb_glines = FF_ARRAY_ELEMS(flat_digital10); break;
  2697. case 12: s->glines = (GraticuleLines *)flat_digital12; s->nb_glines = FF_ARRAY_ELEMS(flat_digital12); break;
  2698. }
  2699. break;
  2700. case MILLIVOLTS:
  2701. switch (s->bits) {
  2702. case 8: s->glines = (GraticuleLines *)flat_millivolts8; s->nb_glines = FF_ARRAY_ELEMS(flat_millivolts8); break;
  2703. case 9: s->glines = (GraticuleLines *)flat_millivolts9; s->nb_glines = FF_ARRAY_ELEMS(flat_millivolts9); break;
  2704. case 10: s->glines = (GraticuleLines *)flat_millivolts10; s->nb_glines = FF_ARRAY_ELEMS(flat_millivolts10); break;
  2705. case 12: s->glines = (GraticuleLines *)flat_millivolts12; s->nb_glines = FF_ARRAY_ELEMS(flat_millivolts12); break;
  2706. }
  2707. break;
  2708. case IRE:
  2709. switch (s->bits) {
  2710. case 8: s->glines = (GraticuleLines *)flat_ire8; s->nb_glines = FF_ARRAY_ELEMS(flat_ire8); break;
  2711. case 9: s->glines = (GraticuleLines *)flat_ire9; s->nb_glines = FF_ARRAY_ELEMS(flat_ire9); break;
  2712. case 10: s->glines = (GraticuleLines *)flat_ire10; s->nb_glines = FF_ARRAY_ELEMS(flat_ire10); break;
  2713. case 12: s->glines = (GraticuleLines *)flat_ire12; s->nb_glines = FF_ARRAY_ELEMS(flat_ire12); break;
  2714. }
  2715. break;
  2716. }
  2717. break;
  2718. }
  2719. s->size = s->size << (s->bits - 8);
  2720. switch (inlink->format) {
  2721. case AV_PIX_FMT_GBRAP:
  2722. case AV_PIX_FMT_GBRP:
  2723. case AV_PIX_FMT_GBRP9:
  2724. case AV_PIX_FMT_GBRP10:
  2725. case AV_PIX_FMT_GBRP12:
  2726. s->rgb = 1;
  2727. memcpy(s->bg_color, black_gbrp_color, sizeof(s->bg_color));
  2728. break;
  2729. default:
  2730. memcpy(s->bg_color, black_yuva_color, sizeof(s->bg_color));
  2731. }
  2732. s->bg_color[3] *= s->bgopacity;
  2733. return 0;
  2734. }
  2735. static int config_output(AVFilterLink *outlink)
  2736. {
  2737. AVFilterContext *ctx = outlink->src;
  2738. AVFilterLink *inlink = ctx->inputs[0];
  2739. WaveformContext *s = ctx->priv;
  2740. int comp = 0, i, j = 0, k, p, size;
  2741. for (i = 0; i < s->ncomp; i++) {
  2742. if ((1 << i) & s->pcomp)
  2743. comp++;
  2744. }
  2745. s->acomp = comp;
  2746. if (s->acomp == 0)
  2747. return AVERROR(EINVAL);
  2748. s->odesc = av_pix_fmt_desc_get(outlink->format);
  2749. s->dcomp = s->odesc->nb_components;
  2750. av_freep(&s->peak);
  2751. if (s->mode) {
  2752. outlink->h = s->size * FFMAX(comp * (s->display == STACK), 1);
  2753. outlink->w = inlink->w * FFMAX(comp * (s->display == PARADE), 1);
  2754. size = inlink->w;
  2755. } else {
  2756. outlink->w = s->size * FFMAX(comp * (s->display == STACK), 1);
  2757. outlink->h = inlink->h * FFMAX(comp * (s->display == PARADE), 1);
  2758. size = inlink->h;
  2759. }
  2760. s->peak = av_malloc_array(size, 32 * sizeof(*s->peak));
  2761. if (!s->peak)
  2762. return AVERROR(ENOMEM);
  2763. for (p = 0; p < s->ncomp; p++) {
  2764. const int plane = s->desc->comp[p].plane;
  2765. int offset;
  2766. if (!((1 << p) & s->pcomp))
  2767. continue;
  2768. for (k = 0; k < 4; k++) {
  2769. s->emax[plane][k] = s->peak + size * (plane * 4 + k + 0);
  2770. s->emin[plane][k] = s->peak + size * (plane * 4 + k + 16);
  2771. }
  2772. offset = j++ * s->size * (s->display == STACK);
  2773. s->estart[plane] = offset;
  2774. s->eend[plane] = (offset + s->size - 1);
  2775. for (i = 0; i < size; i++) {
  2776. for (k = 0; k < 4; k++) {
  2777. s->emax[plane][k][i] = s->estart[plane];
  2778. s->emin[plane][k][i] = s->eend[plane];
  2779. }
  2780. }
  2781. }
  2782. outlink->sample_aspect_ratio = (AVRational){1,1};
  2783. return 0;
  2784. }
  2785. static int filter_frame(AVFilterLink *inlink, AVFrame *in)
  2786. {
  2787. AVFilterContext *ctx = inlink->dst;
  2788. WaveformContext *s = ctx->priv;
  2789. AVFilterLink *outlink = ctx->outputs[0];
  2790. AVFrame *out;
  2791. int i, j, k;
  2792. out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
  2793. if (!out) {
  2794. av_frame_free(&in);
  2795. return AVERROR(ENOMEM);
  2796. }
  2797. out->pts = in->pts;
  2798. out->color_range = AVCOL_RANGE_JPEG;
  2799. for (k = 0; k < s->dcomp; k++) {
  2800. if (s->bits <= 8) {
  2801. for (i = 0; i < outlink->h ; i++)
  2802. memset(out->data[s->odesc->comp[k].plane] +
  2803. i * out->linesize[s->odesc->comp[k].plane],
  2804. s->bg_color[k], outlink->w);
  2805. } else {
  2806. const int mult = s->max / 256;
  2807. uint16_t *dst = (uint16_t *)out->data[s->odesc->comp[k].plane];
  2808. for (i = 0; i < outlink->h ; i++) {
  2809. for (j = 0; j < outlink->w; j++)
  2810. dst[j] = s->bg_color[k] * mult;
  2811. dst += out->linesize[s->odesc->comp[k].plane] / 2;
  2812. }
  2813. }
  2814. }
  2815. for (k = 0, i = 0; k < s->ncomp; k++) {
  2816. if ((1 << k) & s->pcomp) {
  2817. const int plane = s->desc->comp[k].plane;
  2818. ThreadData td;
  2819. int offset_y;
  2820. int offset_x;
  2821. if (s->display == PARADE) {
  2822. offset_x = s->mode ? i++ * inlink->w : 0;
  2823. offset_y = s->mode ? 0 : i++ * inlink->h;
  2824. } else {
  2825. offset_y = s->mode ? i++ * s->size * !!s->display : 0;
  2826. offset_x = s->mode ? 0 : i++ * s->size * !!s->display;
  2827. }
  2828. td.in = in;
  2829. td.out = out;
  2830. td.component = k;
  2831. td.offset_y = offset_y;
  2832. td.offset_x = offset_x;
  2833. ctx->internal->execute(ctx, s->waveform_slice, &td, NULL, ff_filter_get_nb_threads(ctx));
  2834. switch (s->filter) {
  2835. case ACOLOR:
  2836. case CHROMA:
  2837. case COLOR:
  2838. case LOWPASS:
  2839. if (s->bits <= 8)
  2840. envelope(s, out, plane, plane, s->mode ? offset_x : offset_y);
  2841. else
  2842. envelope16(s, out, plane, plane, s->mode ? offset_x : offset_y);
  2843. break;
  2844. case FLAT:
  2845. if (s->bits <= 8) {
  2846. envelope(s, out, plane, plane, s->mode ? offset_x : offset_y);
  2847. envelope(s, out, plane, (plane + 1) % s->ncomp, s->mode ? offset_x : offset_y);
  2848. } else {
  2849. envelope16(s, out, plane, plane, s->mode ? offset_x : offset_y);
  2850. envelope16(s, out, plane, (plane + 1) % s->ncomp, s->mode ? offset_x : offset_y);
  2851. }
  2852. break;
  2853. case AFLAT:
  2854. case XFLAT:
  2855. if (s->bits <= 8) {
  2856. envelope(s, out, plane, (plane + 0) % s->ncomp, s->mode ? offset_x : offset_y);
  2857. envelope(s, out, plane, (plane + 1) % s->ncomp, s->mode ? offset_x : offset_y);
  2858. envelope(s, out, plane, (plane + 2) % s->ncomp, s->mode ? offset_x : offset_y);
  2859. } else {
  2860. envelope16(s, out, plane, (plane + 0) % s->ncomp, s->mode ? offset_x : offset_y);
  2861. envelope16(s, out, plane, (plane + 1) % s->ncomp, s->mode ? offset_x : offset_y);
  2862. envelope16(s, out, plane, (plane + 2) % s->ncomp, s->mode ? offset_x : offset_y);
  2863. }
  2864. break;
  2865. }
  2866. }
  2867. }
  2868. s->graticulef(s, out);
  2869. av_frame_free(&in);
  2870. return ff_filter_frame(outlink, out);
  2871. }
  2872. static av_cold void uninit(AVFilterContext *ctx)
  2873. {
  2874. WaveformContext *s = ctx->priv;
  2875. av_freep(&s->peak);
  2876. }
  2877. static const AVFilterPad inputs[] = {
  2878. {
  2879. .name = "default",
  2880. .type = AVMEDIA_TYPE_VIDEO,
  2881. .filter_frame = filter_frame,
  2882. .config_props = config_input,
  2883. },
  2884. { NULL }
  2885. };
  2886. static const AVFilterPad outputs[] = {
  2887. {
  2888. .name = "default",
  2889. .type = AVMEDIA_TYPE_VIDEO,
  2890. .config_props = config_output,
  2891. },
  2892. { NULL }
  2893. };
  2894. AVFilter ff_vf_waveform = {
  2895. .name = "waveform",
  2896. .description = NULL_IF_CONFIG_SMALL("Video waveform monitor."),
  2897. .priv_size = sizeof(WaveformContext),
  2898. .priv_class = &waveform_class,
  2899. .query_formats = query_formats,
  2900. .uninit = uninit,
  2901. .inputs = inputs,
  2902. .outputs = outputs,
  2903. .flags = AVFILTER_FLAG_SLICE_THREADS,
  2904. };