<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
viewBox="0 0 744.09448819 1052.3622047"
id="svg2"
version="1.1"
- inkscape:version="0.91 r13725"
+ inkscape:version="1.0.2 (e86c870, 2021-01-15)"
sodipodi:docname="video.svg">
<defs
id="defs4">
+ <marker
+ style="overflow:visible;"
+ id="marker3668"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow1Mend"
+ inkscape:isstock="true">
+ <path
+ transform="scale(0.4) rotate(180) translate(10,0)"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ id="path3666" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker2973"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow1Mend"
+ inkscape:isstock="true">
+ <path
+ transform="scale(0.4) rotate(180) translate(10,0)"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ id="path2971" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="marker1688"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow1Mend"
+ inkscape:isstock="true"
+ inkscape:collect="always">
+ <path
+ transform="scale(0.4) rotate(180) translate(10,0)"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ id="path1434" />
+ </marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
id="path8484-9" />
</marker>
+ <marker
+ style="overflow:visible"
+ id="marker1688-3"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Mend"
+ inkscape:isstock="true">
+ <path
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path1434-7" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="marker1688-3-2"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Mend"
+ inkscape:isstock="true">
+ <path
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path1434-7-8" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="marker1688-3-29"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Mend"
+ inkscape:isstock="true">
+ <path
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path1434-7-3" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="marker1688-3-29-9"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Mend"
+ inkscape:isstock="true">
+ <path
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path1434-7-3-4" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="marker3668-5"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Mend"
+ inkscape:isstock="true">
+ <path
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path3666-6" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="marker1688-3-29-9-2"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Mend"
+ inkscape:isstock="true">
+ <path
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path1434-7-3-4-5" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="marker1688-3-29-9-2-7"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Mend"
+ inkscape:isstock="true">
+ <path
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path1434-7-3-4-5-4" />
+ </marker>
</defs>
<sodipodi:namedview
id="base"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="12.895211"
- inkscape:cx="-38.958419"
- inkscape:cy="710.99114"
+ inkscape:zoom="1.6119014"
+ inkscape:cx="436.93023"
+ inkscape:cy="615.356"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
- inkscape:window-width="1280"
- inkscape:window-height="995"
- inkscape:window-x="86"
- inkscape:window-y="0"
+ inkscape:window-width="1920"
+ inkscape:window-height="1016"
+ inkscape:window-x="0"
+ inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:showpageshadow="true"
showborder="false"
- inkscape:snap-global="false" />
+ inkscape:snap-global="false"
+ inkscape:document-rotation="0" />
<metadata
id="metadata7">
<rdf:RDF>
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
sodipodi:nodetypes="cccc" />
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:125%;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="157.97063"
y="145.07965"
- id="text3355-3"
- sodipodi:linespacing="125%"><tspan
+ id="text3355-3"><tspan
sodipodi:role="line"
id="tspan3357-6"
x="157.97063"
- y="145.07965">Player</tspan></text>
+ y="145.07965"
+ style="font-size:14px;line-height:1.25">Player</tspan></text>
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="261.11292"
y="79.787865"
- id="text3405"
- sodipodi:linespacing="125%"><tspan
+ id="text3405"><tspan
sodipodi:role="line"
id="tspan3407"
x="261.11292"
- y="79.787865">Call <tspan
+ y="79.787865"
+ style="font-size:8px;line-height:1.25">Call <tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';fill:#ff0000"
id="tspan3425">give(<tspan
style="fill:#0000ff"
id="tspan4943">ImageProxy</tspan>)</tspan></tspan></text>
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:125%;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="158.08263"
y="27.967474"
- id="text3459"
- sodipodi:linespacing="125%"><tspan
+ id="text3459"><tspan
sodipodi:role="line"
id="tspan3461"
x="158.08263"
- y="27.967474">FFmpegDecoder</tspan><tspan
+ y="27.967474"
+ style="font-size:14px;line-height:1.25">FFmpegDecoder</tspan><tspan
sodipodi:role="line"
x="158.08263"
y="45.467476"
- id="tspan3463">DCPDecoder</tspan><tspan
+ id="tspan3463"
+ style="font-size:14px;line-height:1.25">DCPDecoder</tspan><tspan
sodipodi:role="line"
x="158.08263"
y="62.967476"
- id="tspan3465">VideoMXFDecoder</tspan><tspan
+ id="tspan3465"
+ style="font-size:14px;line-height:1.25">VideoMXFDecoder</tspan><tspan
sodipodi:role="line"
x="158.08263"
y="80.467476"
- id="tspan3467">ImageDecoder</tspan></text>
+ id="tspan3467"
+ style="font-size:14px;line-height:1.25">ImageDecoder</tspan></text>
<text
xml:space="preserve"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="750.14496"
y="30.933632"
- id="text3503"
- sodipodi:linespacing="125%"><tspan
+ id="text3503"><tspan
sodipodi:role="line"
id="tspan3505"
x="750.14496"
- y="30.933632" /></text>
+ y="30.933632"
+ style="font-size:40px;line-height:1.25">Â </tspan></text>
<text
xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="730.14496"
y="42.362206"
- id="text3507"
- sodipodi:linespacing="125%"><tspan
+ id="text3507"><tspan
sodipodi:role="line"
id="tspan3509"
x="730.14496"
- y="42.362206" /></text>
+ y="42.362206"
+ style="font-size:40px;line-height:1.25">Â </tspan></text>
<text
xml:space="preserve"
- style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="730.14496"
y="48.076488"
- id="text3511"
- sodipodi:linespacing="125%"><tspan
+ id="text3511"><tspan
sodipodi:role="line"
id="tspan3513"
x="730.14496"
- y="48.076488" /></text>
+ y="48.076488"
+ style="font-size:40px;line-height:1.25">Â </tspan></text>
<g
id="g6532"
transform="translate(1.07113,-2.4356439)">
<text
- sodipodi:linespacing="125%"
id="text3427"
y="32.95697"
x="365.3392"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:125%;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
xml:space="preserve"><tspan
id="tspan3431"
y="32.95697"
x="365.3392"
- sodipodi:role="line">RawImageProxy</tspan><tspan
+ sodipodi:role="line"
+ style="font-size:14px;line-height:1.25">RawImageProxy</tspan><tspan
id="tspan3495"
y="50.45697"
x="365.3392"
- sodipodi:role="line">MagickImageProxy</tspan><tspan
+ sodipodi:role="line"
+ style="font-size:14px;line-height:1.25">MagickImageProxy</tspan><tspan
id="tspan3497"
y="67.95697"
x="365.3392"
- sodipodi:role="line">J2KImageProxy</tspan></text>
+ sodipodi:role="line"
+ style="font-size:14px;line-height:1.25">J2KImageProxy</tspan></text>
<text
- sodipodi:linespacing="125%"
id="text3515"
y="32.793625"
x="468.0589"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
xml:space="preserve"><tspan
y="32.793625"
x="468.0589"
id="tspan3517"
- sodipodi:role="line">image in any pixel format and colourspace</tspan></text>
+ sodipodi:role="line"
+ style="font-size:8px;line-height:1.25">image in any pixel format and colourspace</tspan></text>
<text
- sodipodi:linespacing="125%"
id="text3519"
y="50.478642"
x="489.33072"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
xml:space="preserve"><tspan
y="50.478642"
x="489.33072"
id="tspan3521"
- sodipodi:role="line">image assumed to be 24-bit RGB</tspan></text>
+ sodipodi:role="line"
+ style="font-size:8px;line-height:1.25">image assumed to be 24-bit RGB</tspan></text>
<text
- sodipodi:linespacing="125%"
id="text3523"
y="68.05394"
x="468.04465"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
xml:space="preserve"><tspan
y="68.05394"
x="468.04465"
id="tspan3525"
- sodipodi:role="line">image in J2K which could be sRGB or XYZ</tspan></text>
+ sodipodi:role="line"
+ style="font-size:8px;line-height:1.25">image in J2K which could be sRGB or XYZ</tspan></text>
</g>
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:125%;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="158.96458"
y="114.28626"
- id="text3598"
- sodipodi:linespacing="125%"><tspan
+ id="text3598"><tspan
sodipodi:role="line"
id="tspan3600"
x="158.96458"
- y="114.28626">VideoDecoder</tspan></text>
+ y="114.28626"
+ style="font-size:14px;line-height:1.25">VideoDecoder</tspan></text>
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="210.7205"
y="145.7095"
- id="text4752"
- sodipodi:linespacing="125%"><tspan
+ id="text4752"><tspan
sodipodi:role="line"
id="tspan4754"
x="210.7205"
y="145.7095"
- style="font-size:8px">Add <tspan
- style="fill:#0000ff;-inkscape-font-specification:'latin modern mono';font-family:'latin modern mono';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
+ style="font-size:8px;line-height:1.25">Add <tspan
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';fill:#0000ff"
id="tspan4945">ColourConversion</tspan> from Content</tspan></text>
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:125%;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="232.61076"
y="210.91785"
- id="text4774"
- sodipodi:linespacing="125%"><tspan
+ id="text4774"><tspan
sodipodi:role="line"
id="tspan4776"
x="232.61076"
- y="210.91785">Encoder</tspan></text>
+ y="210.91785"
+ style="font-size:14px;line-height:1.25">Encoder</tspan></text>
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:125%;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="80.230049"
y="210.91785"
- id="text4778"
- sodipodi:linespacing="125%"><tspan
+ id="text4778"><tspan
sodipodi:role="line"
id="tspan4780"
x="80.230049"
- y="210.91785">FilmViewer</tspan></text>
+ y="210.91785"
+ style="font-size:14px;line-height:1.25">FilmViewer</tspan></text>
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="80.358047"
y="223.85684"
- id="text4853"
- sodipodi:linespacing="125%"><tspan
+ id="text4853"><tspan
sodipodi:role="line"
id="tspan4855"
x="80.358047"
- y="223.85684">Call <tspan
+ y="223.85684"
+ style="font-size:8px;line-height:1.25">Call <tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono'"
id="tspan4949"><tspan
style="fill:#0000ff"
id="tspan4953">image</tspan></tspan> telling</tspan><tspan
sodipodi:role="line"
x="80.358047"
- y="234.18263"
- id="tspan4857">FFmpeg to convert to RGB</tspan></text>
+ y="234.08084"
+ id="tspan4857"
+ style="font-size:8px;line-height:1.25">FFmpeg to convert to RGB</tspan></text>
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:125%;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="232.70876"
y="236.76064"
- id="text4774-3"
- sodipodi:linespacing="125%"><tspan
+ id="text4774-3"><tspan
sodipodi:role="line"
id="tspan4776-1"
x="232.70876"
- y="236.76064">DCPVideo</tspan><tspan
+ y="236.76064"
+ style="font-size:14px;line-height:1.25">DCPVideo</tspan><tspan
sodipodi:role="line"
x="232.70876"
y="254.26064"
- id="tspan4893" /></text>
+ id="tspan4893"
+ style="font-size:14px;line-height:1.25">Â </tspan></text>
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="232.97478"
y="246.51703"
- id="text4895"
- sodipodi:linespacing="125%"><tspan
+ id="text4895"><tspan
sodipodi:role="line"
x="232.97478"
y="246.51703"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono'"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:1.25;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono'"
id="tspan4931"><tspan
id="tspan8152"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';fill:#ff0000">encode_locally()</tspan></tspan></text>
id="rect7578"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffaaaa;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:1.0292846px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<text
- sodipodi:linespacing="125%"
id="text7580"
y="173.77292"
x="385.19406"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
xml:space="preserve"><tspan
y="173.77292"
x="385.19406"
id="tspan7582"
- sodipodi:role="line">RawImageProxy</tspan></text>
+ sodipodi:role="line"
+ style="font-size:8px;line-height:1.25">RawImageProxy</tspan></text>
<g
transform="translate(-68.230852,57.45182)"
id="g7700">
y="118.93896" />
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="471.76764"
y="126.86294"
- id="text7604"
- sodipodi:linespacing="125%"><tspan
+ id="text7604"><tspan
sodipodi:role="line"
id="tspan7606"
x="471.76764"
- y="126.86294">YUV</tspan></text>
+ y="126.86294"
+ style="font-size:8px;line-height:1.25">YUV</tspan></text>
</g>
</g>
<g
id="rect7578-0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffaaaa;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:1.0292846px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<text
- sodipodi:linespacing="125%"
id="text7580-1"
y="173.77292"
x="385.19406"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
xml:space="preserve"><tspan
y="173.77292"
x="385.19406"
id="tspan7582-3"
- sodipodi:role="line">RawImageProxy</tspan></text>
+ sodipodi:role="line"
+ style="font-size:8px;line-height:1.25">RawImageProxy</tspan></text>
<g
transform="translate(-68.230852,57.45182)"
id="g7700-7">
y="118.93896" />
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="471.76764"
y="126.86294"
- id="text7604-2"
- sodipodi:linespacing="125%"><tspan
+ id="text7604-2"><tspan
sodipodi:role="line"
id="tspan7606-64"
x="471.76764"
- y="126.86294">RGB</tspan></text>
+ y="126.86294"
+ style="font-size:8px;line-height:1.25">RGB</tspan></text>
</g>
</g>
<g
id="rect7578-0-2"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffaaaa;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:1.1262238px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<text
- sodipodi:linespacing="125%"
id="text7580-1-0"
y="211.11105"
x="453.9198"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
xml:space="preserve"><tspan
y="211.11105"
x="453.9198"
id="tspan7582-3-2"
- sodipodi:role="line">MagickImageProxy</tspan></text>
+ sodipodi:role="line"
+ style="font-size:8px;line-height:1.25">MagickImageProxy</tspan></text>
<g
transform="translate(6.5830841,94.789948)"
id="g7700-7-9">
y="118.93896" />
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="471.76764"
y="126.86294"
- id="text7604-2-9"
- sodipodi:linespacing="125%"><tspan
+ id="text7604-2-9"><tspan
sodipodi:role="line"
id="tspan7606-64-9"
x="471.76764"
- y="126.86294">RGB</tspan></text>
+ y="126.86294"
+ style="font-size:8px;line-height:1.25">RGB</tspan></text>
</g>
</g>
<g
id="rect7578-0-2-5"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffaaaa;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:1.0356878px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<text
- sodipodi:linespacing="125%"
id="text7580-1-0-1"
y="239.25938"
x="404.95599"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
xml:space="preserve"><tspan
y="239.25938"
x="404.95599"
id="tspan7582-3-2-0"
- sodipodi:role="line">J2KImageProxy</tspan></text>
+ sodipodi:role="line"
+ style="font-size:8px;line-height:1.25">J2KImageProxy</tspan></text>
<g
transform="translate(-48.084616,122.93827)"
id="g7700-7-9-3">
y="118.93896" />
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="471.76764"
y="126.86294"
- id="text7604-2-9-8"
- sodipodi:linespacing="125%"><tspan
+ id="text7604-2-9-8"><tspan
sodipodi:role="line"
id="tspan7606-64-9-8"
x="471.76764"
- y="126.86294">RGB</tspan></text>
+ y="126.86294"
+ style="font-size:8px;line-height:1.25">RGB</tspan></text>
</g>
</g>
<g
id="rect7578-0-2-5-0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffaaaa;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:1.0356878px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<text
- sodipodi:linespacing="125%"
id="text7580-1-0-1-4"
y="239.25938"
x="404.95599"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
xml:space="preserve"><tspan
y="239.25938"
x="404.95599"
id="tspan7582-3-2-0-6"
- sodipodi:role="line">J2KImageProxy</tspan></text>
+ sodipodi:role="line"
+ style="font-size:8px;line-height:1.25">J2KImageProxy</tspan></text>
<g
transform="translate(-48.084616,122.93827)"
id="g7700-7-9-3-7">
y="118.93896" />
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="471.76764"
y="126.86294"
- id="text7604-2-9-8-0"
- sodipodi:linespacing="125%"><tspan
+ id="text7604-2-9-8-0"><tspan
sodipodi:role="line"
id="tspan7606-64-9-8-9"
x="471.76764"
- y="126.86294">XYZ</tspan></text>
+ y="126.86294"
+ style="font-size:8px;line-height:1.25">XYZ</tspan></text>
</g>
</g>
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="705.09467"
y="244.12233"
- id="text8237"
- sodipodi:linespacing="125%"><tspan
+ id="text8237"><tspan
sodipodi:role="line"
id="tspan8239"
x="705.09467"
y="244.12233"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono'"><tspan
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:1.25;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono'"><tspan
style="fill:#0000ff"
id="tspan8257">Player</tspan>::<tspan
style="fill:#ff0000"
y="264.45612" />
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="705.1507"
y="279.21188"
- id="text8400"
- sodipodi:linespacing="125%"><tspan
+ id="text8400"><tspan
sodipodi:role="line"
id="tspan8402"
x="705.1507"
- y="279.21188"><tspan
+ y="279.21188"
+ style="font-size:8px;line-height:1.25"><tspan
style="fill:#0000ff"
id="tspan8428">DCP</tspan>::<tspan
style="fill:#ff0000"
id="rect8285"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#eeaaff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<text
- sodipodi:linespacing="125%"
id="text8154"
y="244.55614"
x="348.75104"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
xml:space="preserve"><tspan
y="244.55614"
x="348.75104"
id="tspan8156"
- sodipodi:role="line">To RGB48LE</tspan></text>
+ sodipodi:role="line"
+ style="font-size:8px;line-height:1.25">To RGB48LE</tspan></text>
</g>
<path
style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker8482-3)"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="51.75613"
y="226.5392"
id="text9567"
- sodipodi:linespacing="125%"
- transform="matrix(0.88644001,-0.4628435,0.4628435,0.88644001,0,0)"><tspan
+ transform="rotate(-27.570746)"><tspan
sodipodi:role="line"
id="tspan9569"
x="51.75613"
- y="226.5392">Preview</tspan></text>
+ y="226.5392"
+ style="font-size:8px;line-height:1.25">Preview</tspan></text>
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="277.17169"
y="36.546879"
id="text9571"
- sodipodi:linespacing="125%"
- transform="matrix(0.87866652,0.47743601,-0.47743601,0.87866652,0,0)"><tspan
+ transform="rotate(28.518077)"><tspan
sodipodi:role="line"
id="tspan9573"
x="277.17169"
- y="36.546879">Encode</tspan></text>
+ y="36.546879"
+ style="font-size:8px;line-height:1.25">Encode</tspan></text>
<g
id="g9672">
<g
y="235.07904" />
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="348.75104"
y="244.55614"
- id="text8154-0"
- sodipodi:linespacing="125%"><tspan
+ id="text8154-0"><tspan
sodipodi:role="line"
id="tspan8156-4"
x="348.75104"
- y="244.55614">To XYZ12LE</tspan></text>
+ y="244.55614"
+ style="font-size:8px;line-height:1.25">To XYZ12LE</tspan></text>
</g>
</g>
<g
y="235.07904" />
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="348.75104"
y="244.55614"
- id="text8154-0-1"
- sodipodi:linespacing="125%"><tspan
+ id="text8154-0-1"><tspan
sodipodi:role="line"
id="tspan8156-4-6"
x="348.75104"
- y="244.55614">To XYZ12LE</tspan></text>
+ y="244.55614"
+ style="font-size:8px;line-height:1.25">To XYZ12LE</tspan></text>
</g>
</g>
<g
y="235.07904" />
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="348.75104"
y="244.55614"
- id="text8154-0-9"
- sodipodi:linespacing="125%"><tspan
+ id="text8154-0-9"><tspan
sodipodi:role="line"
id="tspan8156-4-64"
x="348.75104"
- y="244.55614">To XYZ12LE</tspan></text>
+ y="244.55614"
+ style="font-size:8px;line-height:1.25">To XYZ12LE</tspan></text>
</g>
</g>
<g
y="235.07904" />
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="348.75104"
y="244.55614"
- id="text8154-0-10"
- sodipodi:linespacing="125%"><tspan
+ id="text8154-0-10"><tspan
sodipodi:role="line"
id="tspan8156-4-2"
x="348.75104"
- y="244.55614">To XYZ12LE</tspan></text>
+ y="244.55614"
+ style="font-size:8px;line-height:1.25">To XYZ12LE</tspan></text>
</g>
</g>
<rect
id="rect7578-9"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffaaaa;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:1.0292846px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<text
- sodipodi:linespacing="125%"
id="text7580-17"
y="173.77292"
x="385.19406"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
xml:space="preserve"><tspan
y="173.77292"
x="385.19406"
id="tspan7582-0"
- sodipodi:role="line">RawImageProxy</tspan></text>
+ sodipodi:role="line"
+ style="font-size:8px;line-height:1.25">RawImageProxy</tspan></text>
<g
transform="translate(-68.230852,57.45182)"
id="g7700-6">
y="118.93896" />
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="471.76764"
y="126.86294"
- id="text7604-8"
- sodipodi:linespacing="125%"><tspan
+ id="text7604-8"><tspan
sodipodi:role="line"
id="tspan7606-5"
x="471.76764"
- y="126.86294">YUV</tspan></text>
+ y="126.86294"
+ style="font-size:8px;line-height:1.25">YUV</tspan></text>
</g>
</g>
<g
id="rect7578-0-9"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffaaaa;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:1.0292846px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<text
- sodipodi:linespacing="125%"
id="text7580-1-4"
y="173.77292"
x="385.19406"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
xml:space="preserve"><tspan
y="173.77292"
x="385.19406"
id="tspan7582-3-1"
- sodipodi:role="line">RawImageProxy</tspan></text>
+ sodipodi:role="line"
+ style="font-size:8px;line-height:1.25">RawImageProxy</tspan></text>
<g
transform="translate(-68.230852,57.45182)"
id="g7700-7-5">
y="118.93896" />
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="471.76764"
y="126.86294"
- id="text7604-2-1"
- sodipodi:linespacing="125%"><tspan
+ id="text7604-2-1"><tspan
sodipodi:role="line"
id="tspan7606-64-5"
x="471.76764"
- y="126.86294">RGB</tspan></text>
+ y="126.86294"
+ style="font-size:8px;line-height:1.25">RGB</tspan></text>
</g>
</g>
<g
id="rect7578-0-2-4"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffaaaa;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:1.1262238px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<text
- sodipodi:linespacing="125%"
id="text7580-1-0-9"
y="211.11105"
x="453.9198"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
xml:space="preserve"><tspan
y="211.11105"
x="453.9198"
id="tspan7582-3-2-8"
- sodipodi:role="line">MagickImageProxy</tspan></text>
+ sodipodi:role="line"
+ style="font-size:8px;line-height:1.25">MagickImageProxy</tspan></text>
<g
transform="translate(6.5830841,94.789948)"
id="g7700-7-9-38">
y="118.93896" />
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="471.76764"
y="126.86294"
- id="text7604-2-9-2"
- sodipodi:linespacing="125%"><tspan
+ id="text7604-2-9-2"><tspan
sodipodi:role="line"
id="tspan7606-64-9-2"
x="471.76764"
- y="126.86294">RGB</tspan></text>
+ y="126.86294"
+ style="font-size:8px;line-height:1.25">RGB</tspan></text>
</g>
</g>
<g
id="rect7578-0-2-5-7"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffaaaa;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:1.0356878px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<text
- sodipodi:linespacing="125%"
id="text7580-1-0-1-0"
y="239.25938"
x="404.95599"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
xml:space="preserve"><tspan
y="239.25938"
x="404.95599"
id="tspan7582-3-2-0-3"
- sodipodi:role="line">J2KImageProxy</tspan></text>
+ sodipodi:role="line"
+ style="font-size:8px;line-height:1.25">J2KImageProxy</tspan></text>
<g
transform="translate(-48.084616,122.93827)"
id="g7700-7-9-3-4">
y="118.93896" />
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="471.76764"
y="126.86294"
- id="text7604-2-9-8-6"
- sodipodi:linespacing="125%"><tspan
+ id="text7604-2-9-8-6"><tspan
sodipodi:role="line"
id="tspan7606-64-9-8-3"
x="471.76764"
- y="126.86294">RGB</tspan></text>
+ y="126.86294"
+ style="font-size:8px;line-height:1.25">RGB</tspan></text>
</g>
</g>
<g
id="rect7578-0-2-5-0-4"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffaaaa;fill-opacity:1;fill-rule:nonzero;stroke:#1a1a1a;stroke-width:1.0356878px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<text
- sodipodi:linespacing="125%"
id="text7580-1-0-1-4-4"
y="239.25938"
x="404.95599"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
xml:space="preserve"><tspan
y="239.25938"
x="404.95599"
id="tspan7582-3-2-0-6-3"
- sodipodi:role="line">J2KImageProxy</tspan></text>
+ sodipodi:role="line"
+ style="font-size:8px;line-height:1.25">J2KImageProxy</tspan></text>
<g
transform="translate(-48.084616,122.93827)"
id="g7700-7-9-3-7-9">
y="118.93896" />
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="471.76764"
y="126.86294"
- id="text7604-2-9-8-0-2"
- sodipodi:linespacing="125%"><tspan
+ id="text7604-2-9-8-0-2"><tspan
sodipodi:role="line"
id="tspan7606-64-9-8-9-5"
x="471.76764"
- y="126.86294">XYZ</tspan></text>
+ y="126.86294"
+ style="font-size:8px;line-height:1.25">XYZ</tspan></text>
</g>
</g>
<text
xml:space="preserve"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
x="5.1282115"
y="332.96237"
- id="text8237-8"
- sodipodi:linespacing="125%"><tspan
+ id="text8237-8"><tspan
sodipodi:role="line"
id="tspan8239-9"
x="5.1282115"
y="332.96237"
- style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono'"><tspan
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:1.25;font-family:'latin modern mono';-inkscape-font-specification:'latin modern mono'"><tspan
style="fill:#0000ff"
id="tspan8257-0">Player</tspan>::<tspan
style="fill:#ff0000"
id="rect8285-5"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#eeaaff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<text
- sodipodi:linespacing="125%"
id="text8154-1"
y="244.55614"
x="354.7998"
- style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:125%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:'latin modern roman';-inkscape-font-specification:'latin modern roman, ';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
xml:space="preserve"><tspan
y="244.55614"
x="354.7998"
id="tspan8156-0"
- sodipodi:role="line">To RGB24</tspan></text>
+ sodipodi:role="line"
+ style="font-size:8px;line-height:1.25">To RGB24</tspan></text>
+ </g>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;opacity:1;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ x="-309.2775"
+ y="554.51569"
+ id="text1175"
+ transform="translate(32.203591,-61.256847)"><tspan
+ sodipodi:role="line"
+ id="tspan1173"
+ x="-309.2775"
+ y="554.51569"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1">Decoder</tspan></text>
+ <g
+ id="g1275"
+ transform="translate(11.680627,-39.263855)">
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;opacity:1;vector-effect:none;fill:#008080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ x="-215.04077"
+ y="510.54083"
+ id="text1198"
+ transform="translate(-17.813399,3.8499265)"><tspan
+ sodipodi:role="line"
+ id="tspan1196"
+ x="-215.04077"
+ y="510.54083"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#008080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1">ContentVideo</tspan><tspan
+ sodipodi:role="line"
+ x="-215.04077"
+ y="528.04083"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#008080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ id="tspan1200"> </tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;opacity:1;vector-effect:none;fill:#008080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ x="-160.62468"
+ y="559.99548"
+ id="text1211"
+ transform="translate(-64.169864,-34.683152)"><tspan
+ sodipodi:role="line"
+ id="tspan1209"
+ x="-160.62468"
+ y="559.99548"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#008080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1">ImageProxy</tspan><tspan
+ sodipodi:role="line"
+ x="-160.62468"
+ y="572.49548"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#008080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ id="tspan1213" /><tspan
+ sodipodi:role="line"
+ x="-160.62468"
+ y="584.99548"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#008080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ id="tspan1217" /><tspan
+ sodipodi:role="line"
+ x="-160.62468"
+ y="597.49548"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#008080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ id="tspan1219" /></text>
</g>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000"
+ x="-309.2775"
+ y="554.51569"
+ id="text1175-2"
+ transform="translate(173.8463,-61.256847)"><tspan
+ sodipodi:role="line"
+ id="tspan1173-9"
+ x="-309.2775"
+ y="554.51569"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1">Player</tspan></text>
+ <g
+ id="g1275-1"
+ transform="translate(149.15963,-38.395575)">
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;opacity:1;vector-effect:none;fill:#008080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ x="-215.04077"
+ y="510.54083"
+ id="text1198-2"
+ transform="translate(-17.813399,3.8499265)"><tspan
+ sodipodi:role="line"
+ id="tspan1196-7"
+ x="-215.04077"
+ y="510.54083"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#008080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1">PlayerVideo</tspan><tspan
+ sodipodi:role="line"
+ x="-215.04077"
+ y="528.04083"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#008080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ id="tspan1200-0"> </tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;opacity:1;vector-effect:none;fill:#008080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ x="-160.62468"
+ y="559.99548"
+ id="text1211-9"
+ transform="translate(-64.169864,-34.683152)"><tspan
+ sodipodi:role="line"
+ id="tspan1209-3"
+ x="-160.62468"
+ y="559.99548"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#008080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1">ImageProxy</tspan><tspan
+ sodipodi:role="line"
+ x="-160.62468"
+ y="572.49548"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#008080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ id="tspan1217-6" /><tspan
+ sodipodi:role="line"
+ x="-160.62468"
+ y="584.99548"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#008080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ id="tspan1219-2" /></text>
+ </g>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000"
+ x="-309.2775"
+ y="554.51569"
+ id="text1175-2-6"
+ transform="translate(312.02999,-57.755915)"><tspan
+ sodipodi:role="line"
+ id="tspan1173-9-1"
+ x="-309.2775"
+ y="554.51569"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1" /></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000"
+ x="-309.2775"
+ y="554.51569"
+ id="text1175-2-8"
+ transform="translate(308.1405,-61.256847)"><tspan
+ sodipodi:role="line"
+ id="tspan1173-9-7"
+ x="-309.2775"
+ y="554.51569"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1">Butler</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;opacity:1;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ x="-87.686157"
+ y="420.73074"
+ id="text1390"
+ transform="translate(4.0571512,20.445338)"><tspan
+ sodipodi:role="line"
+ id="tspan1388"
+ x="-87.686157"
+ y="420.73074"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1">DCPEncoder</tspan></text>
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.9375px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker1688)"
+ d="m -111.77743,479.80479 43.572482,-33.42047"
+ id="path1411" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000"
+ x="-87.686157"
+ y="420.73074"
+ id="text1390-0"
+ transform="translate(164.6192,124.17483)"><tspan
+ sodipodi:role="line"
+ id="tspan1388-2"
+ x="-87.686157"
+ y="420.73074"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1">FFmpegEncoder</tspan></text>
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.9375px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker1688-3)"
+ d="M 33.640882,498.46273 77.213364,531.8832"
+ id="path1411-5" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000"
+ x="-87.686157"
+ y="420.73074"
+ id="text1390-0-9"
+ transform="translate(167.72734,29.633718)"><tspan
+ sodipodi:role="line"
+ id="tspan1388-2-2"
+ x="-87.686157"
+ y="420.73074"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1">VideoView</tspan></text>
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.9375px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker1688-3-2)"
+ d="M 34.296475,481.15447 77.868957,447.734"
+ id="path1411-5-9" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000"
+ x="-87.686157"
+ y="420.73074"
+ id="text1390-0-9-7"
+ transform="translate(265.11469,-6.3252721)"><tspan
+ sodipodi:role="line"
+ id="tspan1388-2-2-3"
+ x="-87.686157"
+ y="420.73074"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1">SimpleVideoView</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000"
+ x="-87.686157"
+ y="420.73074"
+ id="text1390-0-9-6"
+ transform="translate(265.31069,64.227674)"><tspan
+ sodipodi:role="line"
+ id="tspan1388-2-2-1"
+ x="-87.686157"
+ y="420.73074"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1">GLVideoView</tspan></text>
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.9375px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker1688-3-29)"
+ d="m 147.31102,448.44631 27.54102,32.33461"
+ id="path1411-5-1"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.9375px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker1688-3-29-9)"
+ d="m 147.83317,443.8501 27.54102,-32.33461"
+ id="path1411-5-1-7"
+ sodipodi:nodetypes="cc" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;opacity:1;vector-effect:none;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ x="336.05344"
+ y="420.61581"
+ id="text2864"
+ transform="translate(-31.120846,-23.390024)"><tspan
+ sodipodi:role="line"
+ id="tspan2862"
+ x="336.05344"
+ y="420.61581"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1">calls PlayerVideo::image(), hence make_image() which</tspan><tspan
+ sodipodi:role="line"
+ x="336.05344"
+ y="438.11581"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ id="tspan2885">does crop_scale_window(), so the PlayerVideo's </tspan><tspan
+ sodipodi:role="line"
+ x="336.05344"
+ y="455.61581"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ id="tspan2887">ImageProxy must be PADDED.</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000"
+ x="336.05344"
+ y="420.61581"
+ id="text2864-3"
+ transform="translate(2.3793434,115.28813)"><tspan
+ sodipodi:role="line"
+ id="tspan2862-6"
+ x="336.05344"
+ y="420.61581"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1">calls PlayerVideo::raw_image(), and passes</tspan><tspan
+ sodipodi:role="line"
+ x="336.05344"
+ y="438.11581"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ id="tspan2957">the result to GL, so the PlayerVideo's</tspan><tspan
+ sodipodi:role="line"
+ x="336.05344"
+ y="455.61581"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ id="tspan2959">ImageProxy must be COMPACT.</tspan><tspan
+ sodipodi:role="line"
+ x="336.05344"
+ y="473.11581"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ id="tspan2887-0" /></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;opacity:1;vector-effect:none;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ x="309.21796"
+ y="618.7019"
+ id="text3143"
+ transform="translate(5.5245543,46.014145)"><tspan
+ sodipodi:role="line"
+ x="309.21796"
+ y="618.7019"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ id="tspan3145">[ImageProxy's image may be made</tspan><tspan
+ sodipodi:role="line"
+ x="309.21796"
+ y="636.2019"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ id="tspan3149">by ImageProxy::prepare() or by the</tspan><tspan
+ sodipodi:role="line"
+ x="309.21796"
+ y="653.7019"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
+ id="tspan4786">decoder which made the ImageProxy]</tspan></text>
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.9375px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-variation-settings:normal;opacity:1;vector-effect:none;fill-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;marker-end:url(#marker3668);stop-color:#000000;stop-opacity:1"
+ d="m -219.14841,490.17833 h 79.16702"
+ id="path3184" />
+ <path
+ style="font-variation-settings:normal;vector-effect:none;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.9375px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker3668-5);stop-color:#000000"
+ d="M -85.603289,490.17833 H -6.4362693"
+ id="path3184-9" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000"
+ x="-87.686157"
+ y="420.73074"
+ id="text1390-0-9-6-3"
+ transform="translate(395.74642,92.267467)"><tspan
+ sodipodi:role="line"
+ id="tspan1388-2-2-1-7"
+ x="-87.686157"
+ y="420.73074"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1">[J2K optimised]</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000"
+ x="-87.686157"
+ y="420.73074"
+ id="text1390-0-9-6-3-4"
+ transform="translate(395.74227,43.24724)"><tspan
+ sodipodi:role="line"
+ id="tspan1388-2-2-1-7-5"
+ x="-87.686157"
+ y="420.73074"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:1.25;font-family:'Latin Modern Mono';-inkscape-font-specification:'Latin Modern Mono';font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:0px;word-spacing:0px;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;vector-effect:none;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1">[supporting any source]</tspan></text>
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.9375px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker1688-3-29-9-2)"
+ d="m 264.09526,481.80247 43.33723,-22.7705"
+ id="path1411-5-1-7-4"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.9375px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker1688-3-29-9-2-7)"
+ d="m 263.91609,485.60031 43.33723,22.7705"
+ id="path1411-5-1-7-4-4"
+ sodipodi:nodetypes="cc" />
</g>
</svg>
--- /dev/null
+4.3 with compute shaders "came out in 2012"
+Anything before 3.0 is deprecated (especially anything with glBegin/glEnd)
+
+https://stackoverflow.com/questions/14300569/opengl-glbegin-glend
+"The direct mode API with glBegin and glEnd is deprecated, largely for performance reasons."
+"Using VBOs scales better"
+
+OpenGL 3.3 tutorials (written 2012)
+http://www.opengl-tutorial.org/
+
+An intro to modern OpenGL (written 2010)
+https://duriansoftware.com/joe/an-intro-to-modern-opengl.-table-of-contents
+
+Learning Modern 3D Graphics Programming (written 2012)
+https://web.archive.org/web/20140209181347/http://www.arcsynthesis.org/gltut/
+
+"Since OpenGL3.3 most old stuff was moved to compatibility profile, while modern features are core profile; the latter requires self-written shaders, but they should be pretty simple for your case).
--- /dev/null
+#include <QtGui/QGuiApplication>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QOpenGLWindow>
+#include <QtGui/QOpenGLBuffer>
+#include <QtGui/QOpenGLFunctions>
+#include <QtGui/QOpenGLShaderProgram>
+#include <QtGui/QOpenGLVertexArrayObject>
+static QString vertexShader =
+"#version 100\n"
+"\n"
+"attribute vec3 vertexPosition;\n"
+"attribute vec3 vertexNormal;\n"
+"attribute vec3 vertexColor;\n"
+"attribute vec2 texCoord2d;\n"
+"\n"
+"uniform mat4 modelViewMatrix;\n"
+"uniform mat3 normalMatrix;\n"
+"uniform mat4 projectionMatrix;\n"
+"\n"
+"struct LightSource\n"
+"{\n"
+" vec3 ambient;\n"
+" vec3 diffuse;\n"
+" vec3 specular;\n"
+" vec3 position;\n"
+"};\n"
+"uniform LightSource lightSource;\n"
+"\n"
+"struct LightModel\n"
+"{\n"
+" vec3 ambient;\n"
+"};\n"
+"uniform LightModel lightModel;\n"
+"\n"
+"struct Material {\n"
+" vec3 emission;\n"
+" vec3 specular;\n"
+" float shininess;\n"
+"};\n"
+"uniform Material material;\n"
+"\n"
+"varying vec3 v_color;\n"
+"varying vec2 v_texCoord2d;\n"
+"\n"
+"void main()\n"
+"{\n"
+" vec3 normal = normalize(normalMatrix * vertexNormal); // normal vector \n"
+" vec3 position = vec3(modelViewMatrix * vec4(vertexPosition, 1)); // vertex pos in eye coords \n"
+" vec3 halfVector = normalize(lightSource.position + vec3(0,0,1)); // light half vector \n"
+" float nDotVP = dot(normal, normalize(lightSource.position)); // normal . light direction \n"
+" float nDotHV = max(0.f, dot(normal, halfVector)); // normal . light half vector \n"
+" float pf = mix(0.f, pow(nDotHV, material.shininess), step(0.f, nDotVP)); // power factor \n"
+"\n"
+" vec3 ambient = lightSource.ambient;\n"
+" vec3 diffuse = lightSource.diffuse * nDotVP;\n"
+" vec3 specular = lightSource.specular * pf;\n"
+" vec3 sceneColor = material.emission + vertexColor * lightModel.ambient;\n"
+"\n"
+" v_color = clamp(sceneColor + \n"
+" ambient * vertexColor + \n"
+" diffuse * vertexColor + \n"
+" specular * material.specular, 0.f, 1.f );\n"
+"\n"
+" v_texCoord2d = texCoord2d;\n"
+"\n"
+" gl_Position = projectionMatrix * modelViewMatrix * vec4(vertexPosition, 1);\n"
+"}\n"
+;
+static QString fragmentShader =
+"#version 100\n"
+"precision lowp vec3;\n"
+"precision lowp vec2;\n"
+"uniform sampler2D texUnit;\n"
+"\n"
+"varying vec3 v_color;\n"
+"varying vec2 v_texCoord2d;\n"
+"\n"
+"void main()\n"
+"{\n"
+" gl_FragColor = vec4(v_color, 1) * texture2D(texUnit, v_texCoord2d);\n"
+"}\n"
+;
+/*
+* Texture copied and modifided modified from:
+* <a href="https://www.opengl.org/archives/resources/code/samples/mjktips/TexShadowReflectLight.html
+*/
+static char *circles[] = {
+"................",
+"................",
+"......xxxx......",
+"....xxxxxxxx....",
+"...xxxxxxxxxx...",
+"...xxx....xxx...",
+"..xxx......xxx..",
+"..xxx......xxx..",
+"..xxx......xxx..",
+"..xxx......xxx..",
+"...xxx....xxx...",
+"...xxxxxxxxxx...",
+"....xxxxxxxx....",
+"......xxxx......",
+"................",
+"................",
+};
+struct Window : QOpenGLWindow, QOpenGLFunctions
+{
+Window() :
+m_vbo(QOpenGLBuffer::VertexBuffer),
+m_ibo(QOpenGLBuffer::IndexBuffer)
+{
+}
+void createShaderProgram()
+{
+if ( !m_pgm.addShaderFromSourceCode( QOpenGLShader::Vertex, vertexShader)) {
+qDebug() << "Error in vertex shader:" << m_pgm.log();
+exit(1);
+}
+if ( !m_pgm.addShaderFromSourceCode( QOpenGLShader::Fragment, fragmentShader)) {
+qDebug() << "Error in fragment shader:" << m_pgm.log();
+exit(1);
+}
+if ( !m_pgm.link() ) {
+qDebug() << "Error linking shader program:" << m_pgm.log();
+exit(1);
+}
+}
+void createGeometry()
+{
+// Initialize and bind the VAO that's going to capture all this vertex state
+m_vao.create();
+m_vao.bind();
+// we need 24 vertices, 24 normals, and 24 colors (6 faces, 4 vertices per face)
+// since we can't share normal data at the corners (each corner gets 3 normals)
+// and since we're not using glVertexAttribDivisor (not available in ES 2.0)
+struct Vertex {
+GLfloat position[3],
+normal [3],
+color [3],
+texcoord[2];
+} attribs[24]= {
+// Top face (y = 1.0f)
+{ { 1.0f, 1.0f, -1.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, { 0.0f, 0.0f} }, // Green
+{ {-1.0f, 1.0f, -1.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f} }, // Green
+{ {-1.0f, 1.0f, 1.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, { 1.0f, 1.0f} }, // Green
+{ { 1.0f, 1.0f, 1.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, { 1.0f, 0.0f} }, // Green
+// Bottom face (y = -1.0f)
+{ { 1.0f, -1.0f, 1.0f}, {0.0f, -1.0f, 0.0f}, {1.0f, 0.5f, 0.0f}, { 0.0f, 0.0f} }, // Orange
+{ {-1.0f, -1.0f, 1.0f}, {0.0f, -1.0f, 0.0f}, {1.0f, 0.5f, 0.0f}, { 0.0f, 1.0f} }, // Orange
+{ {-1.0f, -1.0f, -1.0f}, {0.0f, -1.0f, 0.0f}, {1.0f, 0.5f, 0.0f}, { 1.0f, 1.0f} }, // Orange
+{ { 1.0f, -1.0f, -1.0f}, {0.0f, -1.0f, 0.0f}, {1.0f, 0.5f, 0.0f}, { 1.0f, 0.0f} }, // Orange
+// Front face (z = 1.0f)
+{ { 1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, { 0.0f, 0.0f} }, // Red
+{ {-1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, { 0.0f, 1.0f} }, // Red
+{ {-1.0f, -1.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, { 1.0f, 1.0f} }, // Red
+{ { 1.0f, -1.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f} }, // Red
+// Back face (z = -1.0f)
+{ { 1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 0.0f}, { 0.0f, 0.0f} }, // Yellow
+{ {-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 0.0f}, { 0.0f, 1.0f} }, // Yellow
+{ {-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 0.0f}, { 1.0f, 1.0f} }, // Yellow
+{ { 1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 0.0f}, { 1.0f, 0.0f} }, // Yellow
+// Left face (x = -1.0f)
+{ {-1.0f, 1.0f, 1.0f}, {-1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f} }, // Blue
+{ {-1.0f, 1.0f, -1.0f}, {-1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, { 0.0f, 1.0f} }, // Blue
+{ {-1.0f, -1.0f, -1.0f}, {-1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, { 1.0f, 1.0f} }, // Blue
+{ {-1.0f, -1.0f, 1.0f}, {-1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, { 1.0f, 0.0f} }, // Blue
+// Right face (x = 1.0f)
+{ {1.0f, 1.0f, -1.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 1.0f}, { 0.0f, 0.0f} }, // Magenta
+{ {1.0f, 1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 1.0f}, { 0.0f, 1.0f} }, // Magenta
+{ {1.0f, -1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 1.0f}, { 1.0f, 1.0f} }, // Magenta
+{ {1.0f, -1.0f, -1.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 1.0f}, { 1.0f, 0.0f} }, // Magenta
+};
+// Put all the attribute data in a FBO
+m_vbo.create();
+m_vbo.setUsagePattern( QOpenGLBuffer::StaticDraw );
+m_vbo.bind();
+m_vbo.allocate(&attribs, sizeof(attribs));
+// Configure the vertex streams for this attribute data layout
+m_pgm.enableAttributeArray("vertexPosition");
+m_pgm.setAttributeBuffer("vertexPosition", GL_FLOAT, offsetof(Vertex, position), 3, sizeof(Vertex) );
+m_pgm.enableAttributeArray("vertexNormal");
+m_pgm.setAttributeBuffer("vertexNormal", GL_FLOAT, offsetof(Vertex, normal), 3, sizeof(Vertex) );
+m_pgm.enableAttributeArray("vertexColor");
+m_pgm.setAttributeBuffer("vertexColor", GL_FLOAT, offsetof(Vertex, color), 3, sizeof(Vertex) );
+m_pgm.enableAttributeArray("texCoord2d");
+m_pgm.setAttributeBuffer("texCoord2d", GL_FLOAT, offsetof(Vertex, texcoord), 3, sizeof(Vertex) );
+// we need 36 indices (6 faces, 2 triangles per face, 3 vertices per triangle)
+struct {
+GLubyte cube[36];
+} indices;
+m_cnt=0; for (GLsizei i=0, v=0; v<6*4; v+=4)
+{
+// first triangle (ccw winding)
+indices.cube[i++] = v + 0;
+indices.cube[i++] = v + 1;
+indices.cube[i++] = v + 2;
+// second triangle (ccw winding)
+indices.cube[i++] = v + 0;
+indices.cube[i++] = v + 2;
+indices.cube[i++] = v + 3;
+m_cnt = i;
+}
+// Put all the index data in a IBO
+m_ibo.create();
+m_ibo.setUsagePattern( QOpenGLBuffer::StaticDraw );
+m_ibo.bind();
+m_ibo.allocate(&indices, sizeof(indices));
+// Okay, we've finished setting up the vao
+m_vao.release();
+}
+void createTexture(void)
+{
+GLubyte image[16][16][3];
+GLubyte *loc;
+int s, t;
+/* Setup RGB image for the texture. */
+loc = (GLubyte*) image;
+for (t = 0; t < 16; t++) {
+for (s = 0; s < 16; s++) {
+if (circles[t][s] == 'x') {
+/* Nice green. */
+loc[0] = 0x1f;
+loc[1] = 0x8f;
+loc[2] = 0x1f;
+} else {
+/* Light gray. */
+loc[0] = 0xaa;
+loc[1] = 0xaa;
+loc[2] = 0xaa;
+}
+loc += 3;
+}
+}
+glGenTextures (1, &m_tex);
+glBindTexture (GL_TEXTURE_2D, m_tex);
+glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+glTexImage2D (GL_TEXTURE_2D, 0, 3, 16, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
+glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+}
+void initializeGL()
+{
+QOpenGLFunctions::initializeOpenGLFunctions();
+createShaderProgram(); m_pgm.bind();
+// Set lighting information
+m_pgm.setUniformValue("lightSource.ambient", QVector3D( 0.0f, 0.0f, 0.0f )); // opengl fixed-function default
+m_pgm.setUniformValue("lightSource.diffuse", QVector3D( 1.0f, 1.0f, 1.0f )); // opengl fixed-function default
+m_pgm.setUniformValue("lightSource.specular", QVector3D( 1.0f, 1.0f, 1.0f )); // opengl fixed-function default
+m_pgm.setUniformValue("lightSource.position", QVector3D( 1.0f, 1.0f, 1.0f )); // NOT DEFAULT VALUE
+m_pgm.setUniformValue("lightModel.ambient", QVector3D( 0.2f, 0.2f, 0.2f )); // opengl fixed-function default
+m_pgm.setUniformValue("material.emission", QVector3D( 0.0f, 0.0f, 0.0f )); // opengl fixed-function default
+m_pgm.setUniformValue("material.specular", QVector3D( 1.0f, 1.0f, 1.0f )); // NOT DEFAULT VALUE
+m_pgm.setUniformValue("material.shininess", 10.0f); // NOT DEFAULT VALUE
+createGeometry();
+m_view.setToIdentity();
+glEnable(GL_DEPTH_TEST);
+glEnable(GL_TEXTURE_2D);
+glActiveTexture(GL_TEXTURE0);
+m_pgm.setUniformValue("texUnit", 0);
+createTexture();
+glClearColor(.5f,.5f,.5f,1.f);
+}
+void resizeGL(int w, int h)
+{
+glViewport(0, 0, w, h);
+m_projection.setToIdentity();
+if (w <= h)
+m_projection.ortho(-2.f, 2.f, -2.f*h/w, 2.f*h/w, -2.f, 2.f);
+else
+m_projection.ortho(-2.f*w/h, 2.f*w/h, -2.f, 2.f, -2.f, 2.f);
+update();
+}
+void paintGL()
+{
+static unsigned cnt;
+glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+glActiveTexture(GL_TEXTURE0);
+glBindTexture(GL_TEXTURE_2D, m_tex);
+QMatrix4x4 model;
+model.rotate(cnt%360, 1,0,0);
+model.rotate(45, 0,0,1);
+QMatrix4x4 mv = m_view * model;
+m_pgm.bind();
+m_pgm.setUniformValue("modelViewMatrix", mv);
+m_pgm.setUniformValue("normalMatrix", mv.normalMatrix());
+m_pgm.setUniformValue("projectionMatrix", m_projection);
+m_vao.bind();
+glDrawElements(GL_TRIANGLES, m_cnt, GL_UNSIGNED_BYTE, 0);
+update();
+++cnt;
+}
+void keyPressEvent(QKeyEvent * ev)
+{
+switch (ev->key()) {
+case Qt::Key_Escape:
+exit(0);
+break;
+default:
+QOpenGLWindow::keyPressEvent(ev);
+break;
+}
+}
+QMatrix4x4 m_projection, m_view;
+QOpenGLShaderProgram m_pgm;
+QOpenGLVertexArrayObject m_vao;
+QOpenGLBuffer m_vbo;
+QOpenGLBuffer m_ibo;
+GLuint m_tex;
+GLsizei m_cnt;
+};
+int main(int argc, char *argv[])
+{
+QGuiApplication a(argc,argv);
+Window w;
+w.setWidth(640); w.setHeight(480);
+w.show();
+return a.exec();
+}
--- /dev/null
+#include <wx/wx.h>
+#include <wx/glcanvas.h>
+
+
+
+class GLCanvas
+{
+public:
+ GLCanvas (wxFrame* parent)
+ {
+ _canvas = new wxGLCanvas(parent);
+ Bind(wxEVT_PAINT, bind(&GLCanvas::paint, this);
+ }
+
+ wxWindow* get()
+ {
+ return _canvas;
+ }
+
+ void paint()
+ {
+
+ }
+
+
+private:
+ wxGLCanvas* _canvas;
+};
+
+
+
+class MyApp : public wxApp
+{
+public:
+ bool OnInit()
+ {
+ auto sizer = new wxBoxSizer(wxHORIZONTAL);
+ _frame = new wxFrame(nullptr, wxID_ANY, wxT("Hello world"));
+ _canvas = new GLCanvas(_frame);
+ sizer->Add(_canvas->get(), 1, wxEXPAND);
+ _frame->SetSizerAndFit(sizer);
+ _frame->Show();
+ return true;
+ }
+
+private:
+ wxFrame* _frame;
+ GLCanvas* _canvas;
+};
+
File "%static_deps%/bin/libpangoft2-1.0-0.dll"
File "%static_deps%/bin/libx264-155.dll"
File "%static_deps%/bin/libwebp-7.dll"
+File "%static_deps%/bin/GLEW.dll"
""", file=f)
if bits == 32:
class BitmapText
{
public:
- BitmapText (std::shared_ptr<Image> i, dcpomatic::Rect<double> r)
+ BitmapText (std::shared_ptr<const Image> i, dcpomatic::Rect<double> r)
: image (i)
, rectangle (r)
{}
- std::shared_ptr<Image> image;
+ std::shared_ptr<const Image> image;
/** Area that the subtitle covers on its corresponding video, expressed in
* proportions of the image size; e.g. rectangle.x = 0.5 would mean that
* the rectangle starts half-way across the video.
/** @param pixel_format Pixel format functor that will be used when calling ::image on PlayerVideos coming out of this
* butler. This will be used (where possible) to prepare the PlayerVideos so that calling image() on them is quick.
- * @param aligned Same as above for the `aligned' flag.
+ * @param alignment Same as above for the `alignment' value.
* @param fast Same as above for the `fast' flag.
*/
Butler::Butler (
int audio_channels,
function<AVPixelFormat (AVPixelFormat)> pixel_format,
VideoRange video_range,
- bool aligned,
- bool fast
+ Image::Alignment alignment,
+ bool fast,
+ bool prepare_only_proxy
)
: _film (film)
, _player (player)
, _disable_audio (false)
, _pixel_format (pixel_format)
, _video_range (video_range)
- , _aligned (aligned)
+ , _alignment (alignment)
, _fast (fast)
+ , _prepare_only_proxy (prepare_only_proxy)
{
_player_video_connection = _player->Video.connect (bind (&Butler::video, this, _1, _2));
_player_audio_connection = _player->Audio.connect (bind (&Butler::audio, this, _1, _2, _3));
/* If the weak_ptr cannot be locked the video obviously no longer requires any work */
if (video) {
LOG_TIMING("start-prepare in %1", thread_id());
- video->prepare (_pixel_format, _video_range, _aligned, _fast);
+ video->prepare (_pixel_format, _video_range, _alignment, _fast, _prepare_only_proxy);
LOG_TIMING("finish-prepare in %1", thread_id());
}
}
int audio_channels,
std::function<AVPixelFormat (AVPixelFormat)> pixel_format,
VideoRange video_range,
- bool aligned,
- bool fast
+ Image::Alignment alignment,
+ bool fast,
+ bool prepare_only_proxy
);
~Butler ();
std::function<AVPixelFormat (AVPixelFormat)> _pixel_format;
VideoRange _video_range;
- bool _aligned;
+ Image::Alignment _alignment;
bool _fast;
+ /** true to ask PlayerVideo::prepare to only prepare the ImageProxy and not also
+ * the final image. We want to do this when the viewer is intending to call
+ * PlayerVideo::raw_image() and do the things in PlayerVideo::make_imgae() itself:
+ * this is the case for the GLVideoView which can do scale, pixfmt conversion etc.
+ * in the shader.
+ */
+ bool _prepare_only_proxy = false;
+
/** If we are waiting to be refilled following a seek, this is the time we were
seeking to.
*/
class ContentBitmapText : public ContentText
{
public:
- ContentBitmapText (dcpomatic::ContentTime f, std::shared_ptr<Image> im, dcpomatic::Rect<double> r)
+ ContentBitmapText (dcpomatic::ContentTime f, std::shared_ptr<const Image> im, dcpomatic::Rect<double> r)
: ContentText (f)
, sub (im, r)
{}
#include "i18n.h"
+
using std::cout;
using std::make_shared;
using std::shared_ptr;
using std::string;
-using dcp::Size;
using dcp::ArrayData;
using dcp::raw_convert;
#if BOOST_VERSION >= 106100
using namespace boost::placeholders;
#endif
+
#define DCI_COEFFICENT (48.0 / 52.37)
+
/** Construct a DCP video frame.
* @param frame Input frame.
* @param index Index of the frame within the DCP.
{
shared_ptr<dcp::OpenJPEGImage> xyz;
- auto image = frame->image (bind(&PlayerVideo::keep_xyz_or_rgb, _1), VideoRange::FULL, true, false);
+ auto image = frame->image (bind(&PlayerVideo::keep_xyz_or_rgb, _1), VideoRange::FULL, false);
if (frame->colour_conversion()) {
xyz = dcp::rgb_to_xyz (
image->data()[0],
Encoder::Encoder (std::shared_ptr<const Film> film, std::weak_ptr<Job> job)
: _film (film)
, _job (job)
- , _player (new Player(film))
+ , _player (new Player(film, Image::Alignment::PADDED))
{
}
}
+GLError::GLError (char const* message)
+ : runtime_error (message)
+{
+
+}
+
+
CopyError::CopyError (string m, optional<int> n)
: runtime_error (String::compose("%1%2", m, n ? String::compose(" (%1)", *n) : ""))
, _message (m)
{
public:
GLError (char const* last, int e);
+ GLError (char const* message);
};
*/
+
/** @file src/ffmpeg_decoder.cc
* @brief A decoder using FFmpeg to decode content.
*/
-#include "filter.h"
-#include "exceptions.h"
-#include "image.h"
-#include "util.h"
-#include "log.h"
+
+#include "audio_buffers.h"
+#include "audio_content.h"
+#include "audio_decoder.h"
+#include "compose.hpp"
#include "dcpomatic_log.h"
-#include "ffmpeg_decoder.h"
-#include "text_decoder.h"
+#include "exceptions.h"
#include "ffmpeg_audio_stream.h"
-#include "ffmpeg_subtitle_stream.h"
-#include "video_filter_graph.h"
-#include "audio_buffers.h"
#include "ffmpeg_content.h"
-#include "raw_image_proxy.h"
-#include "video_decoder.h"
+#include "ffmpeg_decoder.h"
+#include "ffmpeg_subtitle_stream.h"
#include "film.h"
-#include "audio_decoder.h"
-#include "compose.hpp"
-#include "text_content.h"
-#include "audio_content.h"
+#include "filter.h"
#include "frame_interval_checker.h"
+#include "image.h"
+#include "log.h"
+#include "raw_image_proxy.h"
+#include "text_content.h"
+#include "text_decoder.h"
+#include "util.h"
+#include "video_decoder.h"
+#include "video_filter_graph.h"
#include <dcp/subtitle_string.h>
#include <sub/ssa_reader.h>
#include <sub/subtitle.h>
#include <libavformat/avformat.h>
}
#include <boost/algorithm/string.hpp>
-#include <vector>
#include <iomanip>
#include <iostream>
+#include <vector>
#include <stdint.h>
#include "i18n.h"
+
using std::cout;
-using std::string;
-using std::vector;
-using std::list;
+using std::dynamic_pointer_cast;
+using std::make_shared;
using std::min;
-using std::pair;
-using std::max;
-using std::map;
using std::shared_ptr;
-using std::make_shared;
-using std::make_pair;
-using boost::is_any_of;
-using boost::split;
+using std::string;
+using std::vector;
using boost::optional;
-using std::dynamic_pointer_cast;
using dcp::Size;
using namespace dcpomatic;
video = make_shared<VideoDecoder>(this, c);
_pts_offset = pts_offset (c->ffmpeg_audio_streams(), c->first_video(), c->active_video_frame_rate(film));
/* It doesn't matter what size or pixel format this is, it just needs to be black */
- _black_image.reset (new Image (AV_PIX_FMT_RGB24, dcp::Size (128, 128), true));
+ _black_image = make_shared<Image>(AV_PIX_FMT_RGB24, dcp::Size (128, 128), Image::Alignment::PADDED);
_black_image->make_black ();
} else {
_pts_offset = {};
/* Note BGRA is expressed little-endian, so the first byte in the word is B, second
G, third R, fourth A.
*/
- auto image = make_shared<Image>(AV_PIX_FMT_BGRA, dcp::Size (rect->w, rect->h), true);
+ auto image = make_shared<Image>(AV_PIX_FMT_BGRA, dcp::Size (rect->w, rect->h), Image::Alignment::PADDED);
#ifdef DCPOMATIC_HAVE_AVSUBTITLERECT_PICT
/* Start of the first line in the subtitle */
*/
+
+#include "butler.h"
+#include "cross.h"
#include "ffmpeg_encoder.h"
#include "film.h"
+#include "image.h"
#include "job.h"
+#include "log.h"
#include "player.h"
#include "player_video.h"
-#include "log.h"
-#include "image.h"
-#include "cross.h"
-#include "butler.h"
#include "compose.hpp"
#include <iostream>
#include "i18n.h"
+
using std::cout;
using std::list;
using std::make_shared;
-using std::map;
-using std::pair;
-using std::runtime_error;
using std::shared_ptr;
using std::string;
using std::weak_ptr;
using namespace boost::placeholders;
#endif
+
/** @param key Key to use to encrypt MP4 outputs */
FFmpegEncoder::FFmpegEncoder (
shared_ptr<const Film> film,
}
_butler = std::make_shared<Butler>(
- _film, _player, map, _output_audio_channels, bind(&PlayerVideo::force, _1, FFmpegFileEncoder::pixel_format(format)), VideoRange::VIDEO, true, false
+ _film, _player, map, _output_audio_channels, bind(&PlayerVideo::force, _1, FFmpegFileEncoder::pixel_format(format)), VideoRange::VIDEO, Image::Alignment::PADDED, false, false
);
}
*/
+#include "compose.hpp"
+#include "cross.h"
#include "ffmpeg_encoder.h"
#include "ffmpeg_wrapper.h"
#include "film.h"
+#include "image.h"
#include "job.h"
+#include "log.h"
#include "player.h"
#include "player_video.h"
-#include "log.h"
-#include "image.h"
-#include "cross.h"
-#include "compose.hpp"
extern "C" {
#include <libavutil/channel_layout.h>
}
using std::cout;
using std::make_shared;
-using std::pair;
-using std::runtime_error;
using std::shared_ptr;
using std::string;
-using std::weak_ptr;
using boost::bind;
-using boost::optional;
using namespace dcpomatic;
#if BOOST_VERSION >= 106100
using namespace boost::placeholders;
auto image = video->image (
bind (&PlayerVideo::force, _1, _pixel_format),
VideoRange::VIDEO,
- true,
false
);
ImageProxy::Result
-FFmpegImageProxy::image (optional<dcp::Size>) const
+FFmpegImageProxy::image (Image::Alignment alignment, optional<dcp::Size>) const
{
auto constexpr name_for_errors = "FFmpegImageProxy::image";
throw DecodeError (N_("avcodec_receive_frame"), name_for_errors, r, *_path);
}
- _image = make_shared<Image>(frame);
+ _image = make_shared<Image>(frame, alignment);
av_packet_unref (&packet);
av_frame_free (&frame);
FFmpegImageProxy (std::shared_ptr<Socket> socket);
Result image (
+ Image::Alignment alignment,
boost::optional<dcp::Size> size = boost::optional<dcp::Size> ()
) const;
using std::cout;
using std::make_shared;
using std::max;
-using std::min;
-using std::pair;
using std::shared_ptr;
using std::string;
-using std::vector;
using std::weak_ptr;
using boost::optional;
using boost::bind;
emit (bind(boost::ref(Progress), _("Examining audio, subtitles and closed captions")));
}
- auto player = make_shared<Player>(film);
+ auto player = make_shared<Player>(film, Image::Alignment::COMPACT);
player->set_ignore_video ();
if (check_loudness_done) {
/* We don't need to analyse audio because we already loaded a suitable analysis */
using dcp::Size;
-/** The memory alignment, in bytes, used for each row of an image if aligment is requested */
-#define ALIGNMENT 64
+/** The memory alignment, in bytes, used for each row of an image if Alignment::PADDED is requested */
+int constexpr ALIGNMENT = 64;
/* U/V black value for 8-bit colour */
static uint8_t const eight_bit_uv = (1 << 7) - 1;
VideoRange video_range,
AVPixelFormat out_format,
VideoRange out_video_range,
- bool out_aligned,
+ Alignment out_alignment,
bool fast
) const
{
/* Empirical testing suggests that sws_scale() will crash if
- the input image is not aligned.
+ the input image is not padded.
*/
- DCPOMATIC_ASSERT (aligned ());
+ DCPOMATIC_ASSERT (alignment() == Alignment::PADDED);
DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
- auto out = make_shared<Image>(out_format, out_size, out_aligned);
+ auto out = make_shared<Image>(out_format, out_size, out_alignment);
out->make_black ();
auto in_desc = av_pix_fmt_desc_get (_pixel_format);
}
shared_ptr<Image>
-Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const
+Image::convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const
{
- return scale(size(), yuv_to_rgb, out_format, out_aligned, fast);
+ return scale(size(), yuv_to_rgb, out_format, out_alignment, fast);
}
/** @param out_size Size to scale to.
* @param yuv_to_rgb YUVToRGB transform transform to use, if required.
* @param out_format Output pixel format.
- * @param out_aligned true to make an aligned output image.
+ * @param out_aligment Output alignment.
* @param fast Try to be fast at the possible expense of quality; at present this means using
* fast bilinear rather than bicubic scaling.
*/
shared_ptr<Image>
-Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast) const
+Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment out_alignment, bool fast) const
{
/* Empirical testing suggests that sws_scale() will crash if
- the input image is not aligned.
+ the input image alignment is not PADDED.
*/
- DCPOMATIC_ASSERT (aligned ());
+ DCPOMATIC_ASSERT (alignment() == Alignment::PADDED);
- auto scaled = make_shared<Image>(out_format, out_size, out_aligned);
+ auto scaled = make_shared<Image>(out_format, out_size, out_alignment);
auto scale_context = sws_getContext (
size().width, size().height, pixel_format(),
out_size.width, out_size.height, out_format,
}
case AV_PIX_FMT_YUV420P:
{
- auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, false, false);
+ auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
dcp::Size const ts = size();
dcp::Size const os = yuv->size();
for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
}
case AV_PIX_FMT_YUV420P10:
{
- auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, false, false);
+ auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
dcp::Size const ts = size();
dcp::Size const os = yuv->size();
for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
}
case AV_PIX_FMT_YUV422P10LE:
{
- auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, false, false);
+ auto yuv = other->convert_pixel_format (dcp::YUVToRGB::REC709, _pixel_format, Alignment::COMPACT, false);
dcp::Size const ts = size();
dcp::Size const os = yuv->size();
for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
*
* @param p Pixel format.
* @param s Size in pixels.
- * @param aligned true to make each row of this image aligned to a ALIGNMENT-byte boundary.
+ * @param alignment PADDED to make each row of this image aligned to a ALIGNMENT-byte boundary, otherwise COMPACT.
*/
-Image::Image (AVPixelFormat p, dcp::Size s, bool aligned)
+Image::Image (AVPixelFormat p, dcp::Size s, Alignment alignment)
: _size (s)
, _pixel_format (p)
- , _aligned (aligned)
+ , _alignment (alignment)
{
allocate ();
}
+
void
Image::allocate ()
{
for (int i = 0; i < planes(); ++i) {
_line_size[i] = ceil (_size.width * bytes_per_pixel(i));
- _stride[i] = stride_round_up (i, _line_size, _aligned ? ALIGNMENT : 1);
+ _stride[i] = stride_round_up (i, _line_size, _alignment == Alignment::PADDED ? ALIGNMENT : 1);
/* The assembler function ff_rgb24ToY_avx (in libswscale/x86/input.asm)
uses a 16-byte fetch to read three bytes (R/G/B) of image data.
: std::enable_shared_from_this<Image>(other)
, _size (other._size)
, _pixel_format (other._pixel_format)
- , _aligned (other._aligned)
+ , _alignment (other._alignment)
{
allocate ();
}
}
-Image::Image (AVFrame const * frame)
+Image::Image (AVFrame const * frame, Alignment alignment)
: _size (frame->width, frame->height)
, _pixel_format (static_cast<AVPixelFormat>(frame->format))
- , _aligned (true)
+ , _alignment (alignment)
{
DCPOMATIC_ASSERT (_pixel_format != AV_PIX_FMT_NONE);
}
}
-Image::Image (shared_ptr<const Image> other, bool aligned)
+Image::Image (shared_ptr<const Image> other, Alignment alignment)
: _size (other->_size)
, _pixel_format (other->_pixel_format)
- , _aligned (aligned)
+ , _alignment (alignment)
{
allocate ();
std::swap (_stride[i], other._stride[i]);
}
- std::swap (_aligned, other._aligned);
+ std::swap (_alignment, other._alignment);
}
Image::~Image ()
return _size;
}
-bool
-Image::aligned () const
+Image::Alignment
+Image::alignment () const
{
- return _aligned;
+ return _alignment;
}
PositionImage
-merge (list<PositionImage> images)
+merge (list<PositionImage> images, Image::Alignment alignment)
{
if (images.empty ()) {
return {};
}
if (images.size() == 1) {
- return images.front ();
+ images.front().image = Image::ensure_alignment(images.front().image, alignment);
+ return images.front();
}
dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
all.extend (dcpomatic::Rect<int>(i.position, i.image->size().width, i.image->size().height));
}
- auto merged = make_shared<Image>(images.front().image->pixel_format(), dcp::Size(all.width, all.height), true);
+ auto merged = make_shared<Image>(images.front().image->pixel_format(), dcp::Size(all.width, all.height), alignment);
merged->make_transparent ();
for (auto const& i: images) {
merged->alpha_blend (i.image, i.position - all.position());
bool
operator== (Image const & a, Image const & b)
{
- if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.aligned() != b.aligned()) {
+ if (a.planes() != b.planes() || a.pixel_format() != b.pixel_format() || a.alignment() != b.alignment()) {
return false;
}
}
}
+
shared_ptr<const Image>
-Image::ensure_aligned (shared_ptr<const Image> image)
+Image::ensure_alignment (shared_ptr<const Image> image, Image::Alignment alignment)
{
- if (image->aligned()) {
+ if (image->alignment() == alignment) {
return image;
}
- return make_shared<Image>(image, true);
+ return make_shared<Image>(image, alignment);
}
+
size_t
Image::memory_used () const
{
DCPOMATIC_ASSERT (bytes_per_pixel(0) == 4);
DCPOMATIC_ASSERT (planes() == 1);
if (pixel_format() != AV_PIX_FMT_RGBA) {
- return convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, true, false)->as_png();
+ return convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, Image::Alignment::PADDED, false)->as_png();
}
/* error handling? */
class Image : public std::enable_shared_from_this<Image>
{
public:
- Image (AVPixelFormat p, dcp::Size s, bool aligned);
- explicit Image (AVFrame const *);
+ enum class Alignment {
+ COMPACT,
+ PADDED
+ };
+
+ Image (AVPixelFormat p, dcp::Size s, Alignment alignment);
+ explicit Image (AVFrame const *, Alignment alignment);
explicit Image (Image const &);
- Image (std::shared_ptr<const Image>, bool);
+ Image (std::shared_ptr<const Image>, Alignment alignment);
Image& operator= (Image const &);
~Image ();
/** @return array of sizes of the data in each line, in bytes (including any alignment padding) */
int const * stride () const;
dcp::Size size () const;
- bool aligned () const;
+ Alignment alignment () const;
int planes () const;
int vertical_factor (int) const;
dcp::Size sample_size (int) const;
float bytes_per_pixel (int) const;
- std::shared_ptr<Image> convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool aligned, bool fast) const;
- std::shared_ptr<Image> scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool aligned, bool fast) const;
+ std::shared_ptr<Image> convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment alignment, bool fast) const;
+ std::shared_ptr<Image> scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, Alignment alignment, bool fast) const;
std::shared_ptr<Image> crop_scale_window (
Crop crop,
dcp::Size inter_size,
VideoRange video_range,
AVPixelFormat out_format,
VideoRange out_video_range,
- bool aligned,
+ Alignment alignment,
bool fast
) const;
void png_error (char const * message);
- static std::shared_ptr<const Image> ensure_aligned (std::shared_ptr<const Image> image);
+ static std::shared_ptr<const Image> ensure_alignment (std::shared_ptr<const Image> image, Alignment alignment);
private:
friend struct pixel_formats_test;
uint8_t** _data; ///< array of pointers to components
int* _line_size; ///< array of sizes of the data in each line, in bytes (without any alignment padding bytes)
int* _stride; ///< array of strides for each line, in bytes (including any alignment padding bytes)
- bool _aligned;
+ Alignment _alignment;
};
-extern PositionImage merge (std::list<PositionImage> images);
+extern PositionImage merge (std::list<PositionImage> images, Image::Alignment alignment);
extern bool operator== (Image const & a, Image const & b);
#endif
delete[] buffer;
} else {
FFmpegImageProxy proxy(content->path(0));
- _video_size = proxy.image().image->size();
+ _video_size = proxy.image(Image::Alignment::COMPACT).image->size();
}
if (content->still ()) {
/*
- Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
*/
+
#ifndef DCPOMATIC_IMAGE_PROXY_H
#define DCPOMATIC_IMAGE_PROXY_H
+
/** @file src/lib/image_proxy.h
* @brief ImageProxy and subclasses.
*/
+
+#include "image.h"
extern "C" {
#include <libavutil/pixfmt.h>
}
#include <boost/optional.hpp>
#include <boost/utility.hpp>
+
class Image;
class Socket;
class Node;
}
+
/** @class ImageProxy
* @brief A class which holds an Image, and can produce it on request.
*
ImageProxy& operator= (ImageProxy const&) = delete;
struct Result {
- Result (std::shared_ptr<Image> image_, int log2_scaling_)
+ Result (std::shared_ptr<const Image> image_, int log2_scaling_)
: image (image_)
, log2_scaling (log2_scaling_)
, error (false)
, error (error_)
{}
- /** Image (which will be aligned) */
- std::shared_ptr<Image> image;
+ std::shared_ptr<const Image> image;
/** log2 of any scaling down that has already been applied to the image;
* e.g. if the image is already half the size of the original, this value
* will be 1.
* can be used as an optimisation.
*/
virtual Result image (
+ Image::Alignment alignment,
boost::optional<dcp::Size> size = boost::optional<dcp::Size> ()
) const = 0;
* This method may be called in a different thread to image().
* @return log2 of any scaling down that will be applied to the image.
*/
- virtual int prepare (boost::optional<dcp::Size> = boost::optional<dcp::Size>()) const { return 0; }
+ virtual int prepare (Image::Alignment, boost::optional<dcp::Size> = boost::optional<dcp::Size>()) const { return 0; }
virtual size_t memory_used () const = 0;
};
+
std::shared_ptr<ImageProxy> image_proxy_factory (std::shared_ptr<cxml::Node> xml, std::shared_ptr<Socket> socket);
+
#endif
using std::cout;
using std::dynamic_pointer_cast;
-using std::make_pair;
using std::make_shared;
using std::max;
-using std::pair;
using std::shared_ptr;
using std::string;
using boost::optional;
if (xml->optional_number_child<int>("Eye")) {
_eye = static_cast<dcp::Eye>(xml->number_child<int>("Eye"));
}
- shared_ptr<ArrayData> data(new ArrayData(xml->number_child<int>("Size")));
+ auto data = make_shared<ArrayData>(xml->number_child<int>("Size"));
/* This only matters when we are using J2KImageProxy for the preview, which
will never use this constructor (which is only used for passing data to
encode servers). So we can put anything in here. It's a bit of a hack.
int
-J2KImageProxy::prepare (optional<dcp::Size> target_size) const
+J2KImageProxy::prepare (Image::Alignment alignment, optional<dcp::Size> target_size) const
{
boost::mutex::scoped_lock lm (_mutex);
try {
/* XXX: should check that potentially trashing _data here doesn't matter */
auto decompressed = dcp::decompress_j2k (const_cast<uint8_t*>(_data->data()), _data->size(), reduce);
- _image.reset (new Image (_pixel_format, decompressed->size(), true));
+ _image = make_shared<Image>(_pixel_format, decompressed->size(), alignment);
int const shift = 16 - decompressed->precision (0);
}
}
} catch (dcp::J2KDecompressionError& e) {
- _image = make_shared<Image>(_pixel_format, _size, true);
+ _image = make_shared<Image>(_pixel_format, _size, alignment);
_image->make_black ();
_error = true;
}
ImageProxy::Result
-J2KImageProxy::image (optional<dcp::Size> target_size) const
+J2KImageProxy::image (Image::Alignment alignment, optional<dcp::Size> target_size) const
{
- int const r = prepare (target_size);
+ int const r = prepare (alignment, target_size);
/* I think this is safe without a lock on mutex. _image is guaranteed to be
set up when prepare() has happened.
J2KImageProxy (dcp::ArrayData data, dcp::Size size, AVPixelFormat pixel_format);
Result image (
+ Image::Alignment alignment,
boost::optional<dcp::Size> size = boost::optional<dcp::Size> ()
) const;
void write_to_socket (std::shared_ptr<Socket>) const;
/** @return true if our image is definitely the same as another, false if it is probably not */
bool same (std::shared_ptr<const ImageProxy>) const;
- int prepare (boost::optional<dcp::Size> = boost::optional<dcp::Size>()) const;
+ int prepare (Image::Alignment alignment, boost::optional<dcp::Size> = boost::optional<dcp::Size>()) const;
std::shared_ptr<const dcp::Data> j2k () const {
return _data;
using std::list;
using std::make_pair;
using std::make_shared;
-using std::map;
using std::max;
using std::min;
using std::min;
int const PlayerProperty::PLAYBACK_LENGTH = 705;
-Player::Player (shared_ptr<const Film> film)
+Player::Player (shared_ptr<const Film> film, Image::Alignment subtitle_alignment)
: _film (film)
, _suspended (0)
, _tolerant (film->tolerant())
, _audio_merger (_film->audio_frame_rate())
+ , _subtitle_alignment (subtitle_alignment)
{
construct ();
}
_video_container_size = s;
- _black_image.reset (new Image (AV_PIX_FMT_RGB24, _video_container_size, true));
+ _black_image = make_shared<Image>(AV_PIX_FMT_RGB24, _video_container_size, Image::Alignment::PADDED);
_black_image->make_black ();
}
return {};
}
- return merge (captions);
+ return merge (captions, _subtitle_alignment);
}
}
dcp::Size scaled_size (width, height);
- ps.bitmap.push_back (BitmapText(image->scale(scaled_size, dcp::YUVToRGB::REC601, image->pixel_format(), true, _fast), subtitle.sub.rectangle));
+ ps.bitmap.push_back (BitmapText(image->scale(scaled_size, dcp::YUVToRGB::REC601, image->pixel_format(), Image::Alignment::PADDED, _fast), subtitle.sub.rectangle));
DCPTime from (content_time_to_dcp (piece, subtitle.from()));
_active_texts[static_cast<int>(text->type())].add_from (wc, ps, from);
#include "content_video.h"
#include "empty.h"
#include "film.h"
+#include "image.h"
#include "piece.h"
#include "player_text.h"
#include "position_image.h"
class Player : public std::enable_shared_from_this<Player>
{
public:
- Player (std::shared_ptr<const Film>);
+ Player (std::shared_ptr<const Film>, Image::Alignment subtitle_alignment);
Player (std::shared_ptr<const Film>, std::shared_ptr<const Playlist> playlist);
Player (Player const& Player) = delete;
dcpomatic::DCPTime _playback_length;
+ /** Alignment for subtitle images that we create */
+ Image::Alignment _subtitle_alignment = Image::Alignment::PADDED;
+
boost::signals2::scoped_connection _film_changed_connection;
boost::signals2::scoped_connection _playlist_change_connection;
boost::signals2::scoped_connection _playlist_content_change_connection;
if (node->optional_number_child<int>("SubtitleX")) {
auto image = make_shared<Image> (
- AV_PIX_FMT_BGRA, dcp::Size(node->number_child<int>("SubtitleWidth"), node->number_child<int>("SubtitleHeight")), true
+ AV_PIX_FMT_BGRA, dcp::Size(node->number_child<int>("SubtitleWidth"), node->number_child<int>("SubtitleHeight")), Image::Alignment::PADDED
);
image->read_from_socket (socket);
}
shared_ptr<Image>
-PlayerVideo::image (function<AVPixelFormat (AVPixelFormat)> pixel_format, VideoRange video_range, bool aligned, bool fast) const
+PlayerVideo::image (function<AVPixelFormat (AVPixelFormat)> pixel_format, VideoRange video_range, bool fast) const
{
/* XXX: this assumes that image() and prepare() are only ever called with the same parameters (except crop, inter size, out size, fade) */
boost::mutex::scoped_lock lm (_mutex);
if (!_image || _crop != _image_crop || _inter_size != _image_inter_size || _out_size != _image_out_size || _fade != _image_fade) {
- make_image (pixel_format, video_range, aligned, fast);
+ make_image (pixel_format, video_range, fast);
}
return _image;
}
+
+shared_ptr<const Image>
+PlayerVideo::raw_image () const
+{
+ return _in->image(Image::Alignment::COMPACT, _inter_size).image;
+}
+
+
/** Create an image for this frame. A lock must be held on _mutex.
* @param pixel_format Function which is called to decide what pixel format the output image should be;
* it is passed the pixel format of the input image from the ImageProxy, and should return the desired
* output pixel format. Two functions force and keep_xyz_or_rgb are provided for use here.
- * @param aligned true if the output image should be aligned to 32-byte boundaries.
* @param fast true to be fast at the expense of quality.
*/
void
-PlayerVideo::make_image (function<AVPixelFormat (AVPixelFormat)> pixel_format, VideoRange video_range, bool aligned, bool fast) const
+PlayerVideo::make_image (function<AVPixelFormat (AVPixelFormat)> pixel_format, VideoRange video_range, bool fast) const
{
_image_crop = _crop;
_image_inter_size = _inter_size;
_image_out_size = _out_size;
_image_fade = _fade;
- auto prox = _in->image (_inter_size);
+ auto prox = _in->image (Image::Alignment::PADDED, _inter_size);
_error = prox.error;
auto total_crop = _crop;
}
_image = prox.image->crop_scale_window (
- total_crop, _inter_size, _out_size, yuv_to_rgb, _video_range, pixel_format (prox.image->pixel_format()), video_range, aligned, fast
+ total_crop, _inter_size, _out_size, yuv_to_rgb, _video_range, pixel_format (prox.image->pixel_format()), video_range, Image::Alignment::COMPACT, fast
);
if (_text) {
- _image->alpha_blend (Image::ensure_aligned (_text->image), _text->position);
+ _image->alpha_blend (_text->image, _text->position);
}
if (_fade) {
}
void
-PlayerVideo::prepare (function<AVPixelFormat (AVPixelFormat)> pixel_format, VideoRange video_range, bool aligned, bool fast)
+PlayerVideo::prepare (function<AVPixelFormat (AVPixelFormat)> pixel_format, VideoRange video_range, Image::Alignment alignment, bool fast, bool proxy_only)
{
- _in->prepare (_inter_size);
+ _in->prepare (alignment, _inter_size);
boost::mutex::scoped_lock lm (_mutex);
- if (!_image) {
- make_image (pixel_format, video_range, aligned, fast);
+ if (!_image && !proxy_only) {
+ make_image (pixel_format, video_range, fast);
}
}
#define DCPOMATIC_PLAYER_VIDEO_H
-#include "types.h"
-#include "position.h"
-#include "dcpomatic_time.h"
#include "colour_conversion.h"
+#include "dcpomatic_time.h"
+#include "image.h"
+#include "position.h"
#include "position_image.h"
+#include "types.h"
extern "C" {
#include <libavutil/pixfmt.h>
}
std::shared_ptr<PlayerVideo> shallow_copy () const;
void set_text (PositionImage);
+ boost::optional<PositionImage> text () const {
+ return _text;
+ }
- void prepare (std::function<AVPixelFormat (AVPixelFormat)> pixel_format, VideoRange video_range, bool aligned, bool fast);
- std::shared_ptr<Image> image (std::function<AVPixelFormat (AVPixelFormat)> pixel_format, VideoRange video_range, bool aligned, bool fast) const;
+ void prepare (std::function<AVPixelFormat (AVPixelFormat)> pixel_format, VideoRange video_range, Image::Alignment alignment, bool fast, bool proxy_only);
+ std::shared_ptr<Image> image (std::function<AVPixelFormat (AVPixelFormat)> pixel_format, VideoRange video_range, bool fast) const;
+ std::shared_ptr<const Image> raw_image () const;
static AVPixelFormat force (AVPixelFormat, AVPixelFormat);
static AVPixelFormat keep_xyz_or_rgb (AVPixelFormat);
return _inter_size;
}
+ dcp::Size out_size () const {
+ return _out_size;
+ }
+
bool same (std::shared_ptr<const PlayerVideo> other) const;
size_t memory_used () const;
}
private:
- void make_image (std::function<AVPixelFormat (AVPixelFormat)> pixel_format, VideoRange video_range, bool aligned, bool fast) const;
+ void make_image (std::function<AVPixelFormat (AVPixelFormat)> pixel_format, VideoRange video_range, bool fast) const;
std::shared_ptr<const ImageProxy> _in;
Crop _crop;
public:
PositionImage () {}
- PositionImage (std::shared_ptr<Image> i, Position<int> p)
+ PositionImage (std::shared_ptr<const Image> i, Position<int> p)
: image (i)
, position (p)
{}
- std::shared_ptr<Image> image;
+ std::shared_ptr<const Image> image;
Position<int> position;
bool same (PositionImage const & other) const;
xml->number_child<int>("Width"), xml->number_child<int>("Height")
);
- _image = make_shared<Image>(static_cast<AVPixelFormat>(xml->number_child<int>("PixelFormat")), size, true);
+ _image = make_shared<Image>(static_cast<AVPixelFormat>(xml->number_child<int>("PixelFormat")), size, Image::Alignment::PADDED);
_image->read_from_socket (socket);
}
ImageProxy::Result
-RawImageProxy::image (optional<dcp::Size>) const
+RawImageProxy::image (Image::Alignment alignment, optional<dcp::Size>) const
{
- return Result (_image, 0);
+ /* This ensure_alignment could be wasteful */
+ return Result (Image::ensure_alignment(_image, alignment), 0);
}
return false;
}
- return (*_image.get()) == (*rp->image().image.get());
+ return (*_image.get()) == (*rp->image(_image->alignment()).image.get());
}
RawImageProxy (std::shared_ptr<cxml::Node> xml, std::shared_ptr<Socket> socket);
Result image (
+ Image::Alignment alignment,
boost::optional<dcp::Size> size = boost::optional<dcp::Size> ()
) const;
using std::pair;
using std::shared_ptr;
using std::string;
-using boost::optional;
-using boost::algorithm::replace_all;
using namespace dcpomatic;
static shared_ptr<Image>
create_image (dcp::Size size)
{
- /* FFmpeg BGRA means first byte blue, second byte green, third byte red, fourth byte alpha */
- auto image = make_shared<Image>(AV_PIX_FMT_BGRA, size, false);
+ /* FFmpeg BGRA means first byte blue, second byte green, third byte red, fourth byte alpha.
+ * This must be COMPACT as we're using it with Cairo::ImageSurface::create
+ */
+ auto image = make_shared<Image>(AV_PIX_FMT_BGRA, size, Image::Alignment::COMPACT);
image->make_black ();
return image;
}
static Cairo::RefPtr<Cairo::ImageSurface>
create_surface (shared_ptr<Image> image)
{
+ /* XXX: I don't think it's guaranteed that format_stride_for_width will return a stride without any padding,
+ * so it's lucky that this works.
+ */
+ DCPOMATIC_ASSERT (image->alignment() == Image::Alignment::COMPACT);
+ DCPOMATIC_ASSERT (image->pixel_format() == AV_PIX_FMT_BGRA);
return Cairo::ImageSurface::create (
image->data()[0],
Cairo::FORMAT_ARGB32,
* of the video frame)
*/
void
-TextDecoder::emit_bitmap_start (ContentTime from, shared_ptr<Image> image, dcpomatic::Rect<double> rect)
+TextDecoder::emit_bitmap_start (ContentTime from, shared_ptr<const Image> image, dcpomatic::Rect<double> rect)
{
BitmapStart (ContentBitmapText (from, image, rect));
_position = from;
* of the video frame)
*/
void
-TextDecoder::emit_bitmap (ContentTimePeriod period, shared_ptr<Image> image, dcpomatic::Rect<double> rect)
+TextDecoder::emit_bitmap (ContentTimePeriod period, shared_ptr<const Image> image, dcpomatic::Rect<double> rect)
{
emit_bitmap_start (period.from, image, rect);
emit_stop (period.to);
return _position;
}
- void emit_bitmap_start (dcpomatic::ContentTime from, std::shared_ptr<Image> image, dcpomatic::Rect<double> rect);
- void emit_bitmap (dcpomatic::ContentTimePeriod period, std::shared_ptr<Image> image, dcpomatic::Rect<double> rect);
+ void emit_bitmap_start (dcpomatic::ContentTime from, std::shared_ptr<const Image> image, dcpomatic::Rect<double> rect);
+ void emit_bitmap (dcpomatic::ContentTimePeriod period, std::shared_ptr<const Image> image, dcpomatic::Rect<double> rect);
void emit_plain_start (dcpomatic::ContentTime from, std::list<dcp::SubtitleString> s);
void emit_plain_start (dcpomatic::ContentTime from, sub::Subtitle const & subtitle);
void emit_plain (dcpomatic::ContentTimePeriod period, std::list<dcp::SubtitleString> s);
* @brief Some utility functions and classes.
*/
+
#define UNICODE 1
-#include "util.h"
-#include "exceptions.h"
-#include "dcp_content_type.h"
-#include "filter.h"
+
+#include "audio_buffers.h"
+#include "audio_processor.h"
#include "cinema_sound_processor.h"
+#include "compose.hpp"
#include "config.h"
-#include "ratio.h"
-#include "job.h"
#include "cross.h"
-#include "video_content.h"
-#include "rect.h"
-#include "digester.h"
-#include "audio_processor.h"
#include "crypto.h"
-#include "compose.hpp"
-#include "audio_buffers.h"
-#include "string_text.h"
-#include "font.h"
-#include "render_text.h"
+#include "dcp_content_type.h"
+#include "digester.h"
+#include "exceptions.h"
#include "ffmpeg_image_proxy.h"
+#include "filter.h"
+#include "font.h"
#include "image.h"
-#include "text_decoder.h"
+#include "job.h"
#include "job_manager.h"
+#include "ratio.h"
+#include "rect.h"
+#include "render_text.h"
+#include "string_text.h"
+#include "text_decoder.h"
+#include "util.h"
+#include "video_content.h"
#include "warnings.h"
#include <dcp/decrypted_kdm.h>
#include <dcp/locale_convert.h>
#include "i18n.h"
-using std::string;
-using std::wstring;
-using std::setfill;
-using std::ostream;
+
+using std::bad_alloc;
+using std::cout;
using std::endl;
-using std::vector;
-using std::min;
-using std::max;
-using std::map;
-using std::list;
-using std::multimap;
using std::istream;
+using std::list;
+using std::make_pair;
+using std::make_shared;
+using std::map;
+using std::min;
+using std::ostream;
using std::pair;
-using std::cout;
-using std::bad_alloc;
using std::set_terminate;
-using std::make_pair;
using std::shared_ptr;
-using std::make_shared;
+using std::string;
+using std::vector;
+using std::wstring;
using boost::thread;
using boost::optional;
using boost::lexical_cast;
using dcp::locale_convert;
using namespace dcpomatic;
+
/** Path to our executable, required by the stacktrace stuff and filled
* in during App::onInit().
*/
{
/* XXX: this is rather inefficient; decoding the image just to get its size */
FFmpegImageProxy proxy (sub.png_image());
- auto image = proxy.image().image;
+ auto image = proxy.image(Image::Alignment::PADDED).image;
/* set up rect with height and width */
dcpomatic::Rect<double> rect(0, 0, image->size().width / double(size.width), image->size().height / double(size.height));
using std::pair;
using std::shared_ptr;
using std::string;
-using std::vector;
VideoFilterGraph::VideoFilterGraph (dcp::Size s, AVPixelFormat p, dcp::Fraction r)
list<pair<shared_ptr<Image>, int64_t>> images;
if (_copy) {
- images.push_back (make_pair(make_shared<Image>(frame), frame->best_effort_timestamp));
+ images.push_back (make_pair(make_shared<Image>(frame, Image::Alignment::PADDED), frame->best_effort_timestamp));
} else {
int r = av_buffersrc_write_frame (_buffer_src_context, frame);
if (r < 0) {
break;
}
- images.push_back (make_pair(make_shared<Image>(_frame), frame->best_effort_timestamp));
+ images.push_back (make_pair(make_shared<Image>(_frame, Image::Alignment::PADDED), frame->best_effort_timestamp));
av_frame_unref (_frame);
}
}
{
public:
DOMFrame ()
- : wxFrame (0, -1, _("DCP-o-matic Player"))
- , _dual_screen (0)
- , _update_news_requested (false)
- , _info (0)
+ : wxFrame (nullptr, -1, _("DCP-o-matic Player"))
, _mode (Config::instance()->player_mode())
- , _config_dialog (0)
- , _file_menu (0)
- , _history_items (0)
- , _history_position (0)
- , _history_separator (0)
- , _system_information_dialog (0)
- , _view_full_screen (0)
- , _view_dual_screen (0)
- , _main_sizer (new wxBoxSizer (wxVERTICAL))
+ , _main_sizer (new wxBoxSizer(wxVERTICAL))
{
dcpomatic_log = make_shared<NullLog>();
*/
_overall_panel = new wxPanel (this, wxID_ANY);
- _viewer.reset (new FilmViewer (_overall_panel));
+ _viewer = make_shared<FilmViewer>(_overall_panel);
if (Config::instance()->player_mode() == Config::PLAYER_MODE_DUAL) {
auto pc = new PlaylistControls (_overall_panel, _viewer);
_controls = pc;
_controls = new StandardControls (_overall_panel, _viewer, false);
}
_viewer->set_dcp_decode_reduction (Config::instance()->decode_reduction ());
+ _viewer->set_optimise_for_j2k (true);
_viewer->PlaybackPermitted.connect (bind(&DOMFrame::playback_permitted, this));
_viewer->Started.connect (bind(&DOMFrame::playback_started, this, _1));
_viewer->Stopped.connect (bind(&DOMFrame::playback_stopped, this, _1));
reset_film ();
- UpdateChecker::instance()->StateChanged.connect (boost::bind (&DOMFrame::update_checker_state_changed, this));
+ UpdateChecker::instance()->StateChanged.connect (boost::bind(&DOMFrame::update_checker_state_changed, this));
setup_screen ();
_stress.LoadDCP.connect (boost::bind(&DOMFrame::load_dcp, this, _1));
_viewer->seek (_film->length() - _viewer->one_video_frame(), true);
}
- wxFrame* _dual_screen;
- bool _update_news_requested;
- PlayerInformation* _info;
+ wxFrame* _dual_screen = nullptr;
+ bool _update_news_requested = false;
+ PlayerInformation* _info = nullptr;
Config::PlayerMode _mode;
- wxPreferencesEditor* _config_dialog;
- wxPanel* _overall_panel;
- wxMenu* _file_menu;
- wxMenuItem* _view_cpl;
- wxMenu* _cpl_menu;
- int _history_items;
- int _history_position;
- wxMenuItem* _history_separator;
+ wxPreferencesEditor* _config_dialog = nullptr;
+ wxPanel* _overall_panel = nullptr;
+ wxMenu* _file_menu = nullptr;
+ wxMenuItem* _view_cpl = nullptr;
+ wxMenu* _cpl_menu = nullptr;
+ int _history_items = 0;
+ int _history_position = 0;
+ wxMenuItem* _history_separator = nullptr;
shared_ptr<FilmViewer> _viewer;
Controls* _controls;
- SystemInformationDialog* _system_information_dialog;
+ SystemInformationDialog* _system_information_dialog = nullptr;
std::shared_ptr<Film> _film;
boost::signals2::scoped_connection _config_changed_connection;
boost::signals2::scoped_connection _examine_job_connection;
- wxMenuItem* _file_add_ov;
- wxMenuItem* _file_add_kdm;
- wxMenuItem* _tools_verify;
- wxMenuItem* _view_full_screen;
- wxMenuItem* _view_dual_screen;
- wxSizer* _main_sizer;
+ wxMenuItem* _file_add_ov = nullptr;
+ wxMenuItem* _file_add_kdm = nullptr;
+ wxMenuItem* _tools_verify = nullptr;
+ wxMenuItem* _view_full_screen = nullptr;
+ wxMenuItem* _view_dual_screen = nullptr;
+ wxSizer* _main_sizer = nullptr;
PlayerStressTester _stress;
};
public:
App ()
: wxApp ()
- , _frame (0)
{
#ifdef DCPOMATIC_LINUX
XInitThreads ();
bool OnInit ()
{
- wxSplashScreen* splash = 0;
+ wxSplashScreen* splash = nullptr;
try {
wxInitAllImageHandlers ();
_frame->Maximize ();
if (splash) {
splash->Destroy ();
- splash = 0;
+ splash = nullptr;
}
_frame->Show ();
message_dialog (_frame, std_to_wx (m));
}
- DOMFrame* _frame;
+ DOMFrame* _frame = nullptr;
string _dcp_to_load;
boost::optional<string> _stress;
};
film = make_shared<Film>(film_dir);
film->read_metadata ();
- auto player = make_shared<Player>(film);
+ auto player = make_shared<Player>(film, Image::Alignment::COMPACT);
player->Video.connect (bind(&process_video, _1));
while (!player->pass ()) {}
} catch (std::exception& e) {
_jump_to_selected->SetValue (Config::instance()->jump_to_selected ());
}
- _viewer->Started.connect (boost::bind(&Controls::started, this));
- _viewer->Stopped.connect (boost::bind(&Controls::stopped, this));
+ viewer->Started.connect (boost::bind(&Controls::started, this));
+ viewer->Stopped.connect (boost::bind(&Controls::stopped, this));
Bind (wxEVT_TIMER, boost::bind(&Controls::update_position, this));
_timer.Start (80, wxTIMER_CONTINUOUS);
- set_film (_viewer->film());
+ set_film (viewer->film());
setup_sensitivity ();
void
Controls::update_position ()
{
- if (!_slider_being_moved && !_viewer->pending_idle_get()) {
+ auto viewer = _viewer.lock ();
+ if (!viewer) {
+ return;
+ }
+
+ if (!_slider_being_moved && !viewer->pending_idle_get()) {
update_position_label ();
update_position_slider ();
}
void
Controls::eye_changed ()
{
- _viewer->set_eyes (_eye->GetSelection() == 0 ? Eyes::LEFT : Eyes::RIGHT);
+ auto viewer = _viewer.lock ();
+ if (!viewer) {
+ return;
+ }
+
+ viewer->set_eyes (_eye->GetSelection() == 0 ? Eyes::LEFT : Eyes::RIGHT);
}
void
Controls::outline_content_changed ()
{
- _viewer->set_outline_content (_outline_content->GetValue());
+ auto viewer = _viewer.lock ();
+ if (!viewer) {
+ return;
+ }
+
+ viewer->set_outline_content (_outline_content->GetValue());
}
void
Controls::slider_moved (bool page)
{
- if (!_film) {
+ auto viewer = _viewer.lock ();
+ if (!_film || !viewer) {
return;
}
if (!page && !_slider_being_moved) {
/* This is the first event of a drag; stop playback for the duration of the drag */
- _viewer->suspend ();
+ viewer->suspend ();
_slider_being_moved = true;
}
*/
bool accurate = false;
if (t >= _film->length ()) {
- t = _film->length() - _viewer->one_video_frame();
+ t = _film->length() - viewer->one_video_frame();
accurate = true;
}
- _viewer->seek (t, accurate);
+ viewer->seek (t, accurate);
update_position_label ();
log (
void
Controls::slider_released ()
{
+ auto viewer = _viewer.lock ();
+ if (!viewer) {
+ return;
+ }
+
/* Restart after a drag */
- _viewer->resume ();
+ viewer->resume ();
_slider_being_moved = false;
}
return;
}
+ auto viewer = _viewer.lock ();
+ if (!viewer) {
+ return;
+ }
+
auto const len = _film->length ();
if (len.get ()) {
- int const new_slider_position = 4096 * _viewer->position().get() / len.get();
+ int const new_slider_position = 4096 * viewer->position().get() / len.get();
if (new_slider_position != _slider->GetValue()) {
_slider->SetValue (new_slider_position);
}
return;
}
+ auto viewer = _viewer.lock ();
+ if (!viewer) {
+ return;
+ }
+
double const fps = _film->video_frame_rate ();
/* Count frame number from 1 ... not sure if this is the best idea */
- checked_set (_frame_number, wxString::Format (wxT("%ld"), lrint (_viewer->position().seconds() * fps) + 1));
- checked_set (_timecode, time_to_timecode (_viewer->position(), fps));
+ checked_set (_frame_number, wxString::Format (wxT("%ld"), lrint (viewer->position().seconds() * fps) + 1));
+ checked_set (_timecode, time_to_timecode (viewer->position(), fps));
}
DCPTime
Controls::nudge_amount (wxKeyboardState& ev)
{
- auto amount = _viewer->one_video_frame ();
+ auto viewer = _viewer.lock ();
+ if (!viewer) {
+ return {};
+ }
+
+ auto amount = viewer->one_video_frame ();
if (ev.ShiftDown() && !ev.ControlDown()) {
amount = DCPTime::from_seconds (1);
void
Controls::rewind_clicked (wxMouseEvent& ev)
{
- _viewer->seek (DCPTime(), true);
+ auto viewer = _viewer.lock ();
+ if (viewer) {
+ viewer->seek (DCPTime(), true);
+ }
ev.Skip();
}
void
Controls::back_frame ()
{
- _viewer->seek_by (-_viewer->one_video_frame(), true);
+ auto viewer = _viewer.lock ();
+ if (viewer) {
+ viewer->seek_by (-viewer->one_video_frame(), true);
+ }
}
void
Controls::forward_frame ()
{
- _viewer->seek_by (_viewer->one_video_frame(), true);
+ auto viewer = _viewer.lock ();
+ if (viewer) {
+ viewer->seek_by (viewer->one_video_frame(), true);
+ }
}
void
Controls::back_clicked (wxKeyboardState& ev)
{
- _viewer->seek_by (-nudge_amount(ev), true);
+ auto viewer = _viewer.lock ();
+ if (viewer) {
+ viewer->seek_by (-nudge_amount(ev), true);
+ }
}
void
Controls::forward_clicked (wxKeyboardState& ev)
{
- _viewer->seek_by (nudge_amount(ev), true);
+ auto viewer = _viewer.lock ();
+ if (viewer) {
+ viewer->seek_by (nudge_amount(ev), true);
+ }
}
void
Controls::timecode_clicked ()
{
- auto dialog = new PlayheadToTimecodeDialog (this, _viewer->position(), _film->video_frame_rate());
+ auto viewer = _viewer.lock ();
+ if (!viewer) {
+ return;
+ }
+
+ auto dialog = new PlayheadToTimecodeDialog (this, viewer->position(), _film->video_frame_rate());
if (dialog->ShowModal() == wxID_OK) {
- _viewer->seek (dialog->get(), true);
+ viewer->seek (dialog->get(), true);
}
dialog->Destroy ();
}
void
Controls::frame_number_clicked ()
{
- auto dialog = new PlayheadToFrameDialog (this, _viewer->position(), _film->video_frame_rate());
+ auto viewer = _viewer.lock ();
+ if (!viewer) {
+ return;
+ }
+
+ auto dialog = new PlayheadToFrameDialog (this, viewer->position(), _film->video_frame_rate());
if (dialog->ShowModal() == wxID_OK) {
- _viewer->seek (dialog->get(), true);
+ viewer->seek (dialog->get(), true);
}
dialog->Destroy ();
}
wxBoxSizer* _button_sizer;
std::shared_ptr<Film> _film;
wxSlider* _slider;
- std::shared_ptr<FilmViewer> _viewer;
+ std::weak_ptr<FilmViewer> _viewer;
boost::optional<std::string> _active_job;
private:
using std::bad_alloc;
using std::cout;
using std::dynamic_pointer_cast;
-using std::exception;
-using std::list;
-using std::make_pair;
using std::make_shared;
using std::max;
-using std::min;
-using std::pair;
using std::shared_ptr;
using std::string;
using std::vector;
-using std::weak_ptr;
using boost::optional;
#if BOOST_VERSION >= 106100
using namespace boost::placeholders;
{
switch (Config::instance()->video_view_type()) {
case Config::VIDEO_VIEW_OPENGL:
- _video_view = new GLVideoView (this, p);
+ _video_view = std::make_shared<GLVideoView>(this, p);
break;
case Config::VIDEO_VIEW_SIMPLE:
- _video_view = new SimpleVideoView (this, p);
+ _video_view = std::make_shared<SimpleVideoView>(this, p);
break;
}
}
try {
- _player = make_shared<Player>(_film);
+ _player = make_shared<Player>(_film, _optimise_for_j2k ? Image::Alignment::COMPACT : Image::Alignment::PADDED);
_player->set_fast ();
if (_dcp_decode_reduction) {
_player->set_dcp_decode_reduction (_dcp_decode_reduction);
return;
}
+ auto const j2k_gl_optimised = dynamic_pointer_cast<GLVideoView>(_video_view) && _optimise_for_j2k;
+
_butler = std::make_shared<Butler>(
_film,
_player,
_audio_channels,
bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24),
VideoRange::FULL,
- false,
- true
+ j2k_gl_optimised ? Image::Alignment::COMPACT : Image::Alignment::PADDED,
+ true,
+ j2k_gl_optimised
);
if (!Config::instance()->sound() && !_audio.isStreamOpen()) {
auto const view_ratio = float(_video_view->get()->GetSize().x) / _video_view->get()->GetSize().y;
auto const film_ratio = container ? container->ratio () : 1.78;
+ dcp::Size out_size;
if (view_ratio < film_ratio) {
/* panel is less widscreen than the film; clamp width */
- _out_size.width = _video_view->get()->GetSize().x;
- _out_size.height = lrintf (_out_size.width / film_ratio);
+ out_size.width = _video_view->get()->GetSize().x;
+ out_size.height = lrintf (out_size.width / film_ratio);
} else {
/* panel is more widescreen than the film; clamp height */
- _out_size.height = _video_view->get()->GetSize().y;
- _out_size.width = lrintf (_out_size.height * film_ratio);
+ out_size.height = _video_view->get()->GetSize().y;
+ out_size.width = lrintf (out_size.height * film_ratio);
}
/* Catch silly values */
- _out_size.width = max (64, _out_size.width);
- _out_size.height = max (64, _out_size.height);
+ out_size.width = max (64, out_size.width);
+ out_size.height = max (64, out_size.height);
- _player->set_video_container_size (_out_size);
+ _player->set_video_container_size (out_size);
}
{
emit (boost::bind(boost::ref(ImageChanged), pv));
}
+
+
+void
+FilmViewer::set_optimise_for_j2k (bool o)
+{
+ _optimise_for_j2k = o;
+ _video_view->set_optimise_for_j2k (o);
+}
+
return _video_view->get();
}
- VideoView const * video_view () const {
+ std::shared_ptr<const VideoView> video_view () const {
return _video_view;
}
void set_outline_subtitles (boost::optional<dcpomatic::Rect<double>>);
void set_eyes (Eyes e);
void set_pad_black (bool p);
+ void set_optimise_for_j2k (bool o);
void slow_refresh ();
}
/* Some accessors and utility methods that VideoView classes need */
- dcp::Size out_size () const {
- return _out_size;
- }
bool outline_content () const {
return _outline_content;
}
std::shared_ptr<Film> _film;
std::shared_ptr<Player> _player;
- VideoView* _video_view = nullptr;
+ std::shared_ptr<VideoView> _video_view;
bool _coalesce_player_changes = false;
std::vector<int> _pending_player_changes;
- /** Size of our output (including padding if we have any) */
- dcp::Size _out_size;
-
RtAudio _audio;
int _audio_channels = 0;
unsigned int _audio_block_size = 1024;
boost::optional<int> _dcp_decode_reduction;
+ /** true to assume that this viewer is only being used for JPEG2000 sources
+ * so it can optimise accordingly.
+ */
+ bool _optimise_for_j2k = false;
+
ClosedCaptionsDialog* _closed_captions_dialog = nullptr;
bool _outline_content = false;
/*
- Copyright (C) 2018-2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2018-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
*/
+
+#ifdef DCPOMATIC_WINDOWS
+#include <GL/glew.h>
+#endif
+
#include "gl_video_view.h"
#include "film_viewer.h"
#include "wx_util.h"
#include <iostream>
#ifdef DCPOMATIC_OSX
-#include <OpenGL/glu.h>
-#include <OpenGL/glext.h>
-#include <OpenGL/CGLTypes.h>
+#define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED
#include <OpenGL/OpenGL.h>
+#include <OpenGL/gl3.h>
#endif
#ifdef DCPOMATIC_LINUX
#ifdef DCPOMATIC_WINDOWS
#include <GL/glu.h>
-#include <GL/glext.h>
#include <GL/wglext.h>
#endif
+
using std::cout;
using std::shared_ptr;
+using std::string;
using boost::optional;
#if BOOST_VERSION >= 106100
using namespace boost::placeholders;
GLVideoView::GLVideoView (FilmViewer* viewer, wxWindow *parent)
: VideoView (viewer)
, _context (nullptr)
- , _have_storage (false)
, _vsync_enabled (false)
, _playing (false)
, _one_shot (false)
{
- _canvas = new wxGLCanvas (parent, wxID_ANY, 0, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE);
+ wxGLAttributes attributes;
+ /* We don't need a depth buffer, and indeed there is apparently a bug with Windows/Intel HD 630
+ * which puts green lines over the OpenGL display if you have a non-zero depth buffer size.
+ * https://community.intel.com/t5/Graphics/Request-for-details-on-Intel-HD-630-green-lines-in-OpenGL-apps/m-p/1202179
+ */
+ attributes.PlatformDefaults().MinRGBA(8, 8, 8, 8).DoubleBuffer().Depth(0).EndList();
+ _canvas = new wxGLCanvas (
+ parent, attributes, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE
+ );
_canvas->Bind (wxEVT_PAINT, boost::bind(&GLVideoView::update, this));
_canvas->Bind (wxEVT_SIZE, boost::bind(&GLVideoView::size_changed, this, _1));
_thread.interrupt ();
_thread.join ();
} catch (...) {}
-
- glDeleteTextures (1, &_id);
}
void
return;
}
+ /* It appears important to do this from the GUI thread; if we do it from the GL thread
+ * on Linux we get strange failures to create the context for any version of GL higher
+ * than 3.2.
+ */
+ ensure_context ();
+
#ifdef DCPOMATIC_OSX
/* macOS gives errors if we don't do this (and therefore [NSOpenGLContext setView:]) from the main thread */
- ensure_context ();
+ if (!_setup_shaders_done) {
+ setup_shaders ();
+ _setup_shaders_done = true;
+ }
#endif
if (!_thread.joinable()) {
}
request_one_shot ();
+
+ rethrow ();
}
+static constexpr char vertex_source[] =
+"#version 330 core\n"
+"\n"
+"layout (location = 0) in vec3 in_pos;\n"
+"layout (location = 1) in vec2 in_tex_coord;\n"
+"\n"
+"out vec2 TexCoord;\n"
+"\n"
+"void main()\n"
+"{\n"
+" gl_Position = vec4(in_pos, 1.0);\n"
+" TexCoord = in_tex_coord;\n"
+"}\n";
+
+
+/* Bicubic interpolation stolen from https://stackoverflow.com/questions/13501081/efficient-bicubic-filtering-code-in-glsl */
+static constexpr char fragment_source[] =
+"#version 330 core\n"
+"\n"
+"in vec2 TexCoord;\n"
+"\n"
+"uniform sampler2D texture_sampler;\n"
+/* type = 0: draw border
+ * type = 1: draw XYZ image
+ * type = 2: draw RGB image
+ */
+"uniform int type = 0;\n"
+"uniform vec4 border_colour;\n"
+"uniform mat4 colour_conversion;\n"
+"\n"
+"out vec4 FragColor;\n"
+"\n"
+"vec4 cubic(float x)\n"
+"\n"
+"#define IN_GAMMA 2.2\n"
+"#define OUT_GAMMA 0.384615385\n" // 1 / 2.6
+"#define DCI_COEFFICIENT 0.91655528\n" // 48 / 53.37
+"\n"
+"{\n"
+" float x2 = x * x;\n"
+" float x3 = x2 * x;\n"
+" vec4 w;\n"
+" w.x = -x3 + 3 * x2 - 3 * x + 1;\n"
+" w.y = 3 * x3 - 6 * x2 + 4;\n"
+" w.z = -3 * x3 + 3 * x2 + 3 * x + 1;\n"
+" w.w = x3;\n"
+" return w / 6.f;\n"
+"}\n"
+"\n"
+"vec4 texture_bicubic(sampler2D sampler, vec2 tex_coords)\n"
+"{\n"
+" vec2 tex_size = textureSize(sampler, 0);\n"
+" vec2 inv_tex_size = 1.0 / tex_size;\n"
+"\n"
+" tex_coords = tex_coords * tex_size - 0.5;\n"
+"\n"
+" vec2 fxy = fract(tex_coords);\n"
+" tex_coords -= fxy;\n"
+"\n"
+" vec4 xcubic = cubic(fxy.x);\n"
+" vec4 ycubic = cubic(fxy.y);\n"
+"\n"
+" vec4 c = tex_coords.xxyy + vec2 (-0.5, +1.5).xyxy;\n"
+"\n"
+" vec4 s = vec4(xcubic.xz + xcubic.yw, ycubic.xz + ycubic.yw);\n"
+" vec4 offset = c + vec4 (xcubic.yw, ycubic.yw) / s;\n"
+"\n"
+" offset *= inv_tex_size.xxyy;\n"
+"\n"
+" vec4 sample0 = texture(sampler, offset.xz);\n"
+" vec4 sample1 = texture(sampler, offset.yz);\n"
+" vec4 sample2 = texture(sampler, offset.xw);\n"
+" vec4 sample3 = texture(sampler, offset.yw);\n"
+"\n"
+" float sx = s.x / (s.x + s.y);\n"
+" float sy = s.z / (s.z + s.w);\n"
+"\n"
+" return mix(\n"
+" mix(sample3, sample2, sx), mix(sample1, sample0, sx)\n"
+" , sy);\n"
+"}\n"
+"\n"
+"void main()\n"
+"{\n"
+" switch (type) {\n"
+" case 0:\n"
+" FragColor = border_colour;\n"
+" break;\n"
+" case 1:\n"
+" FragColor = texture_bicubic(texture_sampler, TexCoord);\n"
+" FragColor.x = pow(FragColor.x, IN_GAMMA) / DCI_COEFFICIENT;\n"
+" FragColor.y = pow(FragColor.y, IN_GAMMA) / DCI_COEFFICIENT;\n"
+" FragColor.z = pow(FragColor.z, IN_GAMMA) / DCI_COEFFICIENT;\n"
+" FragColor = colour_conversion * FragColor;\n"
+" FragColor.x = pow(FragColor.x, OUT_GAMMA);\n"
+" FragColor.y = pow(FragColor.y, OUT_GAMMA);\n"
+" FragColor.z = pow(FragColor.z, OUT_GAMMA);\n"
+" break;\n"
+" case 2:\n"
+" FragColor = texture_bicubic(texture_sampler, TexCoord);\n"
+" break;\n"
+" }\n"
+"}\n";
+
+
void
GLVideoView::ensure_context ()
{
if (!_context) {
- _context = new wxGLContext (_canvas);
- _canvas->SetCurrent (*_context);
+ wxGLContextAttrs attrs;
+ attrs.PlatformDefaults().CoreProfile().OGLVersion(4, 1).EndList();
+ _context = new wxGLContext (_canvas, nullptr, &attrs);
+ if (!_context->IsOK()) {
+ throw GLError ("Making GL context", -1);
+ }
}
}
+
+/* Offset of video texture triangles in indices */
+static constexpr int indices_video_texture = 0;
+/* Offset of subtitle texture triangles in indices */
+static constexpr int indices_subtitle_texture = 6;
+/* Offset of border lines in indices */
+static constexpr int indices_border = 12;
+
+static constexpr unsigned int indices[] = {
+ 0, 1, 3, // video texture triangle #1
+ 1, 2, 3, // video texture triangle #2
+ 4, 5, 7, // subtitle texture triangle #1
+ 5, 6, 7, // subtitle texture triangle #2
+ 8, 9, // border line #1
+ 9, 10, // border line #2
+ 10, 11, // border line #3
+ 11, 8, // border line #4
+};
+
+
void
-GLVideoView::draw (Position<int> inter_position, dcp::Size inter_size)
+GLVideoView::setup_shaders ()
{
- glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- check_gl_error ("glClear");
+ DCPOMATIC_ASSERT (_canvas);
+ DCPOMATIC_ASSERT (_context);
+ auto r = _canvas->SetCurrent (*_context);
+ DCPOMATIC_ASSERT (r);
+
+#ifdef DCPOMATIC_WINDOWS
+ r = glewInit();
+ if (r != GLEW_OK) {
+ throw GLError(reinterpret_cast<char const*>(glewGetErrorString(r)));
+ }
+#endif
- glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
- check_gl_error ("glClearColor");
- glEnable (GL_TEXTURE_2D);
- check_gl_error ("glEnable GL_TEXTURE_2D");
+ auto get_information = [this](GLenum name) {
+ auto s = glGetString (name);
+ if (s) {
+ _information[name] = std::string (reinterpret_cast<char const *>(s));
+ }
+ };
+
+ get_information (GL_VENDOR);
+ get_information (GL_RENDERER);
+ get_information (GL_VERSION);
+ get_information (GL_SHADING_LANGUAGE_VERSION);
+
+ glGenVertexArrays(1, &_vao);
+ check_gl_error ("glGenVertexArrays");
+ GLuint vbo;
+ glGenBuffers(1, &vbo);
+ check_gl_error ("glGenBuffers");
+ GLuint ebo;
+ glGenBuffers(1, &ebo);
+ check_gl_error ("glGenBuffers");
+
+ glBindVertexArray(_vao);
+ check_gl_error ("glBindVertexArray");
+
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ check_gl_error ("glBindBuffer");
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
+ check_gl_error ("glBindBuffer");
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
+ check_gl_error ("glBufferData");
+
+ /* position attribute to vertex shader (location = 0) */
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), nullptr);
+ glEnableVertexAttribArray(0);
+ /* texture coord attribute to vertex shader (location = 1) */
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), reinterpret_cast<void*>(3 * sizeof(float)));
+ glEnableVertexAttribArray(1);
+ check_gl_error ("glEnableVertexAttribArray");
+
+ auto compile = [](GLenum type, char const* source) -> GLuint {
+ auto shader = glCreateShader(type);
+ DCPOMATIC_ASSERT (shader);
+ GLchar const * src[] = { static_cast<GLchar const *>(source) };
+ glShaderSource(shader, 1, src, nullptr);
+ check_gl_error ("glShaderSource");
+ glCompileShader(shader);
+ check_gl_error ("glCompileShader");
+ GLint ok;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
+ if (!ok) {
+ GLint log_length;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
+ string log;
+ if (log_length > 0) {
+ char* log_char = new char[log_length];
+ glGetShaderInfoLog(shader, log_length, nullptr, log_char);
+ log = string(log_char);
+ delete[] log_char;
+ }
+ glDeleteShader(shader);
+ throw GLError(String::compose("Could not compile shader (%1)", log).c_str(), -1);
+ }
+ return shader;
+ };
+
+ auto vertex_shader = compile (GL_VERTEX_SHADER, vertex_source);
+ auto fragment_shader = compile (GL_FRAGMENT_SHADER, fragment_source);
+
+ auto program = glCreateProgram();
+ check_gl_error ("glCreateProgram");
+ glAttachShader (program, vertex_shader);
+ check_gl_error ("glAttachShader");
+ glAttachShader (program, fragment_shader);
+ check_gl_error ("glAttachShader");
+ glLinkProgram (program);
+ check_gl_error ("glLinkProgram");
+ GLint ok;
+ glGetProgramiv (program, GL_LINK_STATUS, &ok);
+ if (!ok) {
+ GLint log_length;
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
+ string log;
+ if (log_length > 0) {
+ char* log_char = new char[log_length];
+ glGetProgramInfoLog(program, log_length, nullptr, log_char);
+ log = string(log_char);
+ delete[] log_char;
+ }
+ glDeleteProgram (program);
+ throw GLError(String::compose("Could not link shader (%1)", log).c_str(), -1);
+ }
+ glDeleteShader (vertex_shader);
+ glDeleteShader (fragment_shader);
+
+ glUseProgram (program);
+
+ _fragment_type = glGetUniformLocation (program, "type");
+ check_gl_error ("glGetUniformLocation");
+ set_border_colour (program);
+
+ auto conversion = dcp::ColourConversion::rec709_to_xyz();
+ boost::numeric::ublas::matrix<double> matrix = conversion.xyz_to_rgb ();
+ GLfloat gl_matrix[] = {
+ static_cast<float>(matrix(0, 0)), static_cast<float>(matrix(0, 1)), static_cast<float>(matrix(0, 2)), 0.0f,
+ static_cast<float>(matrix(1, 0)), static_cast<float>(matrix(1, 1)), static_cast<float>(matrix(1, 2)), 0.0f,
+ static_cast<float>(matrix(2, 0)), static_cast<float>(matrix(2, 1)), static_cast<float>(matrix(2, 2)), 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+
+ auto colour_conversion = glGetUniformLocation (program, "colour_conversion");
+ check_gl_error ("glGetUniformLocation");
+ glUniformMatrix4fv (colour_conversion, 1, GL_TRUE, gl_matrix);
+
+ glLineWidth (2.0f);
glEnable (GL_BLEND);
- check_gl_error ("glEnable GL_BLEND");
- glDisable (GL_DEPTH_TEST);
- check_gl_error ("glDisable GL_DEPTH_TEST");
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ /* Reserve space for the GL_ARRAY_BUFFER */
+ glBufferData(GL_ARRAY_BUFFER, 12 * 5 * sizeof(float), nullptr, GL_STATIC_DRAW);
+ check_gl_error ("glBufferData");
+}
+
+
+void
+GLVideoView::set_border_colour (GLuint program)
+{
+ auto uniform = glGetUniformLocation (program, "border_colour");
+ check_gl_error ("glGetUniformLocation");
+ auto colour = outline_content_colour ();
+ glUniform4f (uniform, colour.Red() / 255.0f, colour.Green() / 255.0f, colour.Blue() / 255.0f, 1.0f);
+ check_gl_error ("glUniform4f");
+}
+
+
+void
+GLVideoView::draw (Position<int>, dcp::Size)
+{
+ auto pad = pad_colour();
+ glClearColor(pad.Red() / 255.0, pad.Green() / 255.0, pad.Blue() / 255.0, 1.0);
+ glClear (GL_COLOR_BUFFER_BIT);
+ check_gl_error ("glClear");
+
auto const size = _canvas_size.load();
int const width = size.GetWidth();
int const height = size.GetHeight();
glViewport (0, 0, width, height);
check_gl_error ("glViewport");
- glMatrixMode (GL_PROJECTION);
- glLoadIdentity ();
-
-DCPOMATIC_DISABLE_WARNINGS
- gluOrtho2D (0, width, height, 0);
-DCPOMATIC_ENABLE_WARNINGS
- check_gl_error ("gluOrtho2d");
- glMatrixMode (GL_MODELVIEW);
- glLoadIdentity ();
-
- glTranslatef (0, 0, 0);
-
- dcp::Size const out_size = _viewer->out_size ();
-
- if (_size) {
- /* Render our image (texture) */
- glBegin (GL_QUADS);
- glTexCoord2f (0, 1);
- glVertex2f (0, _size->height);
- glTexCoord2f (1, 1);
- glVertex2f (_size->width, _size->height);
- glTexCoord2f (1, 0);
- glVertex2f (_size->width, 0);
- glTexCoord2f (0, 0);
- glVertex2f (0, 0);
- glEnd ();
- } else {
- /* No image, so just fill with black */
- glBegin (GL_QUADS);
- glColor3ub (0, 0, 0);
- glVertex2f (0, 0);
- glVertex2f (out_size.width, 0);
- glVertex2f (out_size.width, out_size.height);
- glVertex2f (0, out_size.height);
- glVertex2f (0, 0);
- glEnd ();
- }
- if (!_viewer->pad_black() && out_size.width < width) {
- glBegin (GL_QUADS);
- /* XXX: these colours are right for GNOME; may need adjusting for other OS */
- glColor3ub (240, 240, 240);
- glVertex2f (out_size.width, 0);
- glVertex2f (width, 0);
- glVertex2f (width, height);
- glVertex2f (out_size.width, height);
- glEnd ();
- glColor3ub (255, 255, 255);
+ glBindVertexArray(_vao);
+ check_gl_error ("glBindVertexArray");
+ glUniform1i(_fragment_type, _optimise_for_j2k ? 1 : 2);
+ _video_texture->bind();
+ glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_INT, reinterpret_cast<void*>(indices_video_texture * sizeof(int)));
+ if (_have_subtitle_to_render) {
+ glUniform1i(_fragment_type, 2);
+ _subtitle_texture->bind();
+ glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_INT, reinterpret_cast<void*>(indices_subtitle_texture * sizeof(int)));
}
-
- if (!_viewer->pad_black() && out_size.height < height) {
- glColor3ub (240, 240, 240);
- int const gap = (height - out_size.height) / 2;
- glBegin (GL_QUADS);
- glVertex2f (0, 0);
- glVertex2f (width, 0);
- glVertex2f (width, gap);
- glVertex2f (0, gap);
- glEnd ();
- glBegin (GL_QUADS);
- glVertex2f (0, gap + out_size.height + 1);
- glVertex2f (width, gap + out_size.height + 1);
- glVertex2f (width, 2 * gap + out_size.height + 2);
- glVertex2f (0, 2 * gap + out_size.height + 2);
- glEnd ();
- glColor3ub (255, 255, 255);
- }
-
if (_viewer->outline_content()) {
- glColor3ub (255, 0, 0);
- glBegin (GL_LINE_LOOP);
- glVertex2f (inter_position.x, inter_position.y + (height - out_size.height) / 2);
- glVertex2f (inter_position.x + inter_size.width, inter_position.y + (height - out_size.height) / 2);
- glVertex2f (inter_position.x + inter_size.width, inter_position.y + (height - out_size.height) / 2 + inter_size.height);
- glVertex2f (inter_position.x, inter_position.y + (height - out_size.height) / 2 + inter_size.height);
- glEnd ();
- glColor3ub (255, 255, 255);
+ glUniform1i(_fragment_type, 0);
+ glDrawElements (GL_LINES, 8, GL_UNSIGNED_INT, reinterpret_cast<void*>(indices_border * sizeof(int)));
+ check_gl_error ("glDrawElements");
}
glFlush();
_canvas->SwapBuffers();
}
+
void
-GLVideoView::set_image (shared_ptr<const Image> image)
+GLVideoView::set_image (shared_ptr<const PlayerVideo> pv)
{
- if (!image) {
- _size = optional<dcp::Size>();
- return;
+ shared_ptr<const Image> video = _optimise_for_j2k ? pv->raw_image() : pv->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, true);
+
+ /* Only the player's black frames should be aligned at this stage, so this should
+ * almost always have no work to do.
+ */
+ video = Image::ensure_alignment (video, Image::Alignment::COMPACT);
+
+ /** If _optimise_for_j2k is true we render a XYZ image, doing the colourspace
+ * conversion, scaling and video range conversion in the GL shader.
+ * Othewise we render a RGB image without any shader-side processing.
+ */
+
+ /* XXX: video range conversion */
+
+ _video_texture->set (video);
+
+ auto const text = pv->text();
+ _have_subtitle_to_render = static_cast<bool>(text) && _optimise_for_j2k;
+ if (_have_subtitle_to_render) {
+ /* opt: only do this if it's a new subtitle? */
+ DCPOMATIC_ASSERT (text->image->alignment() == Image::Alignment::COMPACT);
+ _subtitle_texture->set (text->image);
}
- DCPOMATIC_ASSERT (image->pixel_format() == AV_PIX_FMT_RGB24);
- DCPOMATIC_ASSERT (!image->aligned());
- if (image->size() != _size) {
- _have_storage = false;
+ auto const canvas_size = _canvas_size.load();
+ int const canvas_width = canvas_size.GetWidth();
+ int const canvas_height = canvas_size.GetHeight();
+ auto inter_position = player_video().first->inter_position();
+ auto inter_size = player_video().first->inter_size();
+ auto out_size = player_video().first->out_size();
+
+ _last_canvas_size.set_next (canvas_size);
+ _last_video_size.set_next (video->size());
+ _last_inter_position.set_next (inter_position);
+ _last_inter_size.set_next (inter_size);
+ _last_out_size.set_next (out_size);
+
+ auto x_pixels_to_gl = [canvas_width](int x) {
+ return (x * 2.0f / canvas_width) - 1.0f;
+ };
+
+ auto y_pixels_to_gl = [canvas_height](int y) {
+ return (y * 2.0f / canvas_height) - 1.0f;
+ };
+
+ if (_last_canvas_size.changed() || _last_inter_position.changed() || _last_inter_size.changed() || _last_out_size.changed()) {
+ float const video_x1 = x_pixels_to_gl(_optimise_for_j2k ? inter_position.x : 0);
+ float const video_x2 = x_pixels_to_gl(_optimise_for_j2k ? (inter_position.x + inter_size.width) : out_size.width);
+ float const video_y1 = y_pixels_to_gl(_optimise_for_j2k ? inter_position.y : 0);
+ float const video_y2 = y_pixels_to_gl(_optimise_for_j2k ? (inter_position.y + inter_size.height) : out_size.height);
+ float video_vertices[] = {
+ // positions // texture coords
+ video_x2, video_y2, 0.0f, 1.0f, 0.0f, // video texture top right (index 0)
+ video_x2, video_y1, 0.0f, 1.0f, 1.0f, // video texture bottom right (index 1)
+ video_x1, video_y1, 0.0f, 0.0f, 1.0f, // video texture bottom left (index 2)
+ video_x1, video_y2, 0.0f, 0.0f, 0.0f, // video texture top left (index 3)
+ };
+
+ glBufferSubData (GL_ARRAY_BUFFER, 0, sizeof(video_vertices), video_vertices);
+ check_gl_error ("glBufferSubData (video)");
+
+ float const border_x1 = x_pixels_to_gl(inter_position.x);
+ float const border_y1 = y_pixels_to_gl(inter_position.y);
+ float const border_x2 = x_pixels_to_gl(inter_position.x + inter_size.width);
+ float const border_y2 = y_pixels_to_gl(inter_position.y + inter_size.height);
+
+ float border_vertices[] = {
+ // positions // texture coords
+ border_x1, border_y1, 0.0f, 0.0f, 0.0f, // border bottom left (index 4)
+ border_x1, border_y2, 0.0f, 0.0f, 0.0f, // border top left (index 5)
+ border_x2, border_y2, 0.0f, 0.0f, 0.0f, // border top right (index 6)
+ border_x2, border_y1, 0.0f, 0.0f, 0.0f, // border bottom right (index 7)
+ };
+
+ glBufferSubData (GL_ARRAY_BUFFER, 8 * 5 * sizeof(float), sizeof(border_vertices), border_vertices);
+ check_gl_error ("glBufferSubData (border)");
}
- _size = image->size ();
- glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
- check_gl_error ("glPixelStorei");
- if (_have_storage) {
- glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, _size->width, _size->height, GL_RGB, GL_UNSIGNED_BYTE, image->data()[0]);
- check_gl_error ("glTexSubImage2D");
- } else {
- glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB8, _size->width, _size->height, 0, GL_RGB, GL_UNSIGNED_BYTE, image->data()[0]);
- _have_storage = true;
- check_gl_error ("glTexImage2D");
+ if (_have_subtitle_to_render) {
+ float const subtitle_x1 = x_pixels_to_gl(inter_position.x + text->position.x);
+ float const subtitle_x2 = x_pixels_to_gl(inter_position.x + text->position.x + text->image->size().width);
+ float const subtitle_y1 = y_pixels_to_gl(inter_position.y + text->position.y + text->image->size().height);
+ float const subtitle_y2 = y_pixels_to_gl(inter_position.y + text->position.y);
+
+ float vertices[] = {
+ // positions // texture coords
+ subtitle_x2, subtitle_y1, 0.0f, 1.0f, 0.0f, // subtitle texture top right (index 4)
+ subtitle_x2, subtitle_y2, 0.0f, 1.0f, 1.0f, // subtitle texture bottom right (index 5)
+ subtitle_x1, subtitle_y2, 0.0f, 0.0f, 1.0f, // subtitle texture bottom left (index 6)
+ subtitle_x1, subtitle_y1, 0.0f, 0.0f, 0.0f, // subtitle texture top left (index 7)
+ };
+
+ glBufferSubData (GL_ARRAY_BUFFER, 4 * 5 * sizeof(float), sizeof(vertices), vertices);
+ check_gl_error ("glBufferSubData (subtitle)");
}
+ /* opt: where should these go? */
+
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
check_gl_error ("glTexParameteri");
check_gl_error ("glTexParameterf");
}
+
void
GLVideoView::start ()
{
GLVideoView::thread_playing ()
{
if (length() != dcpomatic::DCPTime()) {
- dcpomatic::DCPTime const next = position() + one_video_frame();
+ auto const next = position() + one_video_frame();
if (next >= length()) {
_viewer->finished ();
void
GLVideoView::set_image_and_draw ()
{
- shared_ptr<PlayerVideo> pv = player_video().first;
+ auto pv = player_video().first;
if (pv) {
- set_image (pv->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true));
+ set_image (pv);
draw (pv->inter_position(), pv->inter_size());
_viewer->image_changed (pv);
}
*/
WXGLSetCurrentContext (_context->GetWXGLContext());
#else
- /* We must call this here on Linux otherwise we get no image (for reasons
- * that aren't clear). However, doing ensure_context() from this thread
- * on macOS gives
- * "[NSOpenGLContext setView:] must be called from the main thread".
- */
- ensure_context ();
+ if (!_setup_shaders_done) {
+ setup_shaders ();
+ _setup_shaders_done = true;
+ }
#endif
#if defined(DCPOMATIC_LINUX) && defined(DCPOMATIC_HAVE_GLX_SWAP_INTERVAL_EXT)
_vsync_enabled = true;
#endif
- glGenTextures (1, &_id);
- check_gl_error ("glGenTextures");
- glBindTexture (GL_TEXTURE_2D, _id);
- check_gl_error ("glBindTexture");
- glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
- check_gl_error ("glPixelStorei");
+ _video_texture.reset(new Texture(_optimise_for_j2k ? 2 : 1));
+ _subtitle_texture.reset(new Texture(1));
while (true) {
boost::mutex::scoped_lock lm (_playing_mutex);
* without also deleting the wxGLCanvas.
*/
}
-catch (boost::thread_interrupted& e)
+catch (...)
{
store_current ();
}
_thread_work_condition.notify_all ();
}
+
+Texture::Texture (GLint unpack_alignment)
+ : _unpack_alignment (unpack_alignment)
+{
+ glGenTextures (1, &_name);
+ check_gl_error ("glGenTextures");
+}
+
+
+Texture::~Texture ()
+{
+ glDeleteTextures (1, &_name);
+}
+
+
+void
+Texture::bind ()
+{
+ glBindTexture(GL_TEXTURE_2D, _name);
+ check_gl_error ("glBindTexture");
+}
+
+
+void
+Texture::set (shared_ptr<const Image> image)
+{
+ auto const create = !_size || image->size() != _size;
+ _size = image->size();
+
+ glPixelStorei (GL_UNPACK_ALIGNMENT, _unpack_alignment);
+ check_gl_error ("glPixelStorei");
+
+ DCPOMATIC_ASSERT (image->alignment() == Image::Alignment::COMPACT);
+
+ GLint internal_format;
+ GLenum format;
+ GLenum type;
+
+ switch (image->pixel_format()) {
+ case AV_PIX_FMT_BGRA:
+ internal_format = GL_RGBA8;
+ format = GL_BGRA;
+ type = GL_UNSIGNED_BYTE;
+ break;
+ case AV_PIX_FMT_RGBA:
+ internal_format = GL_RGBA8;
+ format = GL_RGBA;
+ type = GL_UNSIGNED_BYTE;
+ break;
+ case AV_PIX_FMT_RGB24:
+ internal_format = GL_RGBA8;
+ format = GL_RGB;
+ type = GL_UNSIGNED_BYTE;
+ break;
+ case AV_PIX_FMT_XYZ12:
+ internal_format = GL_RGBA12;
+ format = GL_RGB;
+ type = GL_UNSIGNED_SHORT;
+ break;
+ default:
+ throw PixelFormatError ("Texture::set", image->pixel_format());
+ }
+
+ bind ();
+
+ if (create) {
+ glTexImage2D (GL_TEXTURE_2D, 0, internal_format, _size->width, _size->height, 0, format, type, image->data()[0]);
+ check_gl_error ("glTexImage2D");
+ } else {
+ glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, _size->width, _size->height, format, type, image->data()[0]);
+ check_gl_error ("glTexSubImage2D");
+ }
+}
+
#undef Success
#undef Status
+
+class Texture
+{
+public:
+ Texture (GLint unpack_alignment);
+ ~Texture ();
+
+ Texture (Texture const&) = delete;
+ Texture& operator= (Texture const&) = delete;
+
+ void bind ();
+ void set (std::shared_ptr<const Image> image);
+
+private:
+ GLuint _name;
+ GLint _unpack_alignment;
+ boost::optional<dcp::Size> _size;
+};
+
+
class GLVideoView : public VideoView
{
public:
GLVideoView (FilmViewer* viewer, wxWindow* parent);
~GLVideoView ();
- wxWindow* get () const {
+ wxWindow* get () const override {
return _canvas;
}
- void update ();
- void start ();
- void stop ();
+ void update () override;
+ void start () override;
+ void stop () override;
- NextFrameResult display_next_frame (bool);
+ NextFrameResult display_next_frame (bool) override;
bool vsync_enabled () const {
return _vsync_enabled;
}
+ std::map<GLenum, std::string> information () const {
+ return _information;
+ }
+
private:
- void set_image (std::shared_ptr<const Image> image);
+ void set_image (std::shared_ptr<const PlayerVideo> pv);
void set_image_and_draw ();
void draw (Position<int> inter_position, dcp::Size inter_size);
void thread ();
void check_for_butler_errors ();
void ensure_context ();
void size_changed (wxSizeEvent const &);
+ void setup_shaders ();
+ void set_border_colour (GLuint program);
wxGLCanvas* _canvas;
wxGLContext* _context;
- boost::atomic<wxSize> _canvas_size;
+ template <class T>
+ class Last
+ {
+ public:
+ void set_next (T const& next) {
+ _next = next;
+ }
+
+ bool changed () const {
+ return !_value || *_value != _next;
+ }
+
+ void update () {
+ _value = _next;
+ }
+
+ private:
+ boost::optional<T> _value;
+ T _next;
+ };
+
+ Last<wxSize> _last_canvas_size;
+ Last<dcp::Size> _last_video_size;
+ Last<Position<int>> _last_inter_position;
+ Last<dcp::Size> _last_inter_size;
+ Last<dcp::Size> _last_out_size;
- GLuint _id;
- boost::optional<dcp::Size> _size;
- bool _have_storage;
+ boost::atomic<wxSize> _canvas_size;
+ std::unique_ptr<Texture> _video_texture;
+ std::unique_ptr<Texture> _subtitle_texture;
+ bool _have_subtitle_to_render = false;
bool _vsync_enabled;
boost::thread _thread;
boost::atomic<bool> _playing;
boost::atomic<bool> _one_shot;
+ GLuint _vao;
+ GLint _fragment_type;
+ bool _setup_shaders_done = false;
+
std::shared_ptr<wxTimer> _timer;
+
+ std::map<GLenum, std::string> _information;
};
_previous_button->Bind (wxEVT_BUTTON, boost::bind(&PlaylistControls::previous_clicked, this));
_spl_view->Bind (wxEVT_LIST_ITEM_SELECTED, boost::bind(&PlaylistControls::spl_selection_changed, this));
_spl_view->Bind (wxEVT_LIST_ITEM_DESELECTED, boost::bind(&PlaylistControls::spl_selection_changed, this));
- _viewer->Finished.connect (boost::bind(&PlaylistControls::viewer_finished, this));
+ viewer->Finished.connect (boost::bind(&PlaylistControls::viewer_finished, this));
_refresh_spl_view->Bind (wxEVT_BUTTON, boost::bind(&PlaylistControls::update_playlist_directory, this));
_refresh_content_view->Bind (wxEVT_BUTTON, boost::bind(&ContentView::update, _content_view));
void
PlaylistControls::play_clicked ()
{
- _viewer->start ();
+ auto viewer = _viewer.lock ();
+ if (viewer) {
+ viewer->start ();
+ }
}
void
PlaylistControls::setup_sensitivity ()
{
+ auto viewer = _viewer.lock ();
+ if (!viewer) {
+ return;
+ }
+
Controls::setup_sensitivity ();
bool const active_job = _active_job && *_active_job != "examine_content";
bool const c = _film && !_film->content().empty() && !active_job;
- _play_button->Enable (c && !_viewer->playing());
- _pause_button->Enable (_viewer->playing());
- _spl_view->Enable (!_viewer->playing());
+ _play_button->Enable (c && !viewer->playing());
+ _pause_button->Enable (viewer->playing());
+ _spl_view->Enable (!viewer->playing());
_next_button->Enable (can_do_next());
_previous_button->Enable (can_do_previous());
}
void
PlaylistControls::pause_clicked ()
{
- _viewer->stop ();
+ auto viewer = _viewer.lock ();
+ if (viewer) {
+ viewer->stop ();
+ }
}
void
PlaylistControls::stop_clicked ()
{
- _viewer->stop ();
- _viewer->seek (DCPTime(), true);
+ auto viewer = _viewer.lock ();
+ if (!viewer) {
+ return;
+ }
+
+ viewer->stop ();
+ viewer->seek (DCPTime(), true);
if (_selected_playlist) {
_selected_playlist_position = 0;
update_current_content ();
void
PlaylistControls::viewer_finished ()
{
- if (!_selected_playlist) {
+ auto viewer = _viewer.lock ();
+ if (!_selected_playlist || !viewer) {
return;
}
if (_selected_playlist_position < int(_playlists[*_selected_playlist].get().size())) {
/* Next piece of content on the SPL */
update_current_content ();
- _viewer->start ();
+ viewer->start ();
} else {
/* Finished the whole SPL */
_selected_playlist_position = 0;
/*
- Copyright (C) 2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2019-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
*/
-#include "simple_video_view.h"
+
+#include "closed_captions_dialog.h"
#include "film_viewer.h"
+#include "simple_video_view.h"
#include "wx_util.h"
-#include "closed_captions_dialog.h"
-#include "lib/image.h"
-#include "lib/dcpomatic_log.h"
#include "lib/butler.h"
+#include "lib/dcpomatic_log.h"
+#include "lib/image.h"
#include <dcp/util.h>
#include <wx/wx.h>
#include <boost/bind/bind.hpp>
+
using std::max;
+using std::shared_ptr;
using std::string;
using boost::optional;
-using std::shared_ptr;
#if BOOST_VERSION >= 106100
using namespace boost::placeholders;
#endif
_timer.Bind (wxEVT_TIMER, boost::bind(&SimpleVideoView::timer, this));
}
+
void
SimpleVideoView::paint ()
{
_state_timer.set("paint-panel");
wxPaintDC dc (_panel);
- dcp::Size const out_size = _viewer->out_size ();
- wxSize const panel_size = _panel->GetSize ();
+ auto const panel_size = _panel->GetSize ();
- if (!out_size.width || !out_size.height || !_image || out_size != _image->size()) {
+ dcp::Size out_size;
+ if (!_image) {
dc.Clear ();
} else {
+ DCPOMATIC_ASSERT (_image->alignment() == Image::Alignment::COMPACT);
+ out_size = _image->size();
wxImage frame (out_size.width, out_size.height, _image->data()[0], true);
wxBitmap frame_bitmap (frame);
dc.DrawBitmap (frame_bitmap, 0, max(0, (panel_size.GetHeight() - out_size.height) / 2));
_state_timer.unset();
}
+
void
SimpleVideoView::refresh_panel ()
{
_state_timer.unset ();
}
+
void
SimpleVideoView::timer ()
{
}
}
+
void
SimpleVideoView::start ()
{
timer ();
}
+
/** Try to get a frame from the butler and display it.
* @param non_blocking true to return false quickly if no video is available quickly (i.e. we are waiting for the butler).
* false to ask the butler to block until it has video (unless it is suspended).
return SUCCESS;
}
+
void
SimpleVideoView::update ()
{
if (!player_video().first) {
- set_image (shared_ptr<Image>());
+ _image.reset ();
refresh_panel ();
return;
}
_state_timer.set ("get image");
- set_image (
- player_video().first->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true)
- );
+ _image = player_video().first->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, true);
_state_timer.set ("ImageChanged");
_viewer->image_changed (player_video().first);
public:
SimpleVideoView (FilmViewer* viewer, wxWindow* parent);
- wxWindow* get () const {
+ wxWindow* get () const override {
return _panel;
}
- void update ();
- void start ();
- NextFrameResult display_next_frame (bool non_blocking);
+ void update () override;
+ void start () override;
+ NextFrameResult display_next_frame (bool non_blocking) override;
private:
- void set_image (std::shared_ptr<const Image> image) {
- _image = image;
- }
-
void refresh_panel ();
void paint ();
void timer ();
void
StandardControls::check_play_state ()
{
- if (!_film || _film->video_frame_rate() == 0) {
+ auto viewer = _viewer.lock ();
+ if (!_film || _film->video_frame_rate() == 0 || !viewer) {
return;
}
if (_play_button->GetValue()) {
- _viewer->start ();
+ viewer->start ();
} else {
- _viewer->stop ();
+ viewer->stop ();
}
}
/*
- Copyright (C) 2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2019-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
*/
+
+#include "film_viewer.h"
+#include "gl_video_view.h"
#include "system_information_dialog.h"
#include "wx_util.h"
-#include "gl_video_view.h"
-#include "film_viewer.h"
+
#ifdef DCPOMATIC_OSX
#include <OpenGL/glu.h>
#include <GL/glext.h>
#endif
+
using std::string;
using std::weak_ptr;
using std::shared_ptr;
+
SystemInformationDialog::SystemInformationDialog (wxWindow* parent, weak_ptr<FilmViewer> weak_viewer)
: TableDialog (parent, _("System information"), 2, 1, false)
{
- shared_ptr<FilmViewer> viewer = weak_viewer.lock ();
- GLVideoView const * gl = viewer ? dynamic_cast<GLVideoView const *>(viewer->video_view()) : 0;
+ auto viewer = weak_viewer.lock ();
+ shared_ptr<const GLVideoView> gl;
+ if (viewer) {
+ gl = std::dynamic_pointer_cast<const GLVideoView>(viewer->video_view());
+ }
if (!gl) {
add (_("OpenGL version"), true);
add (_("unknown (OpenGL not enabled in DCP-o-matic)"), false);
} else {
- add (_("OpenGL version"), true);
- char const * v = (char const *) glGetString (GL_VERSION);
- if (v) {
- add (std_to_wx(v), false);
- } else {
- add (_("unknown"), false);
- }
+
+ auto information = gl->information();
+ auto add_string = [this, &information](GLenum name, wxString label) {
+ add (label, true);
+ auto i = information.find(name);
+ if (i != information.end()) {
+ add (std_to_wx(i->second), false);
+ } else {
+ add (_("unknown"), false);
+ }
+ };
+
+ add_string (GL_VENDOR, _("Vendor"));
+ add_string (GL_RENDERER, _("Renderer"));
+ add_string (GL_VERSION, _("Version"));
+ add_string (GL_SHADING_LANGUAGE_VERSION, _("Shading language version"));
+
add (_("vsync"), true);
add (gl->vsync_enabled() ? _("enabled") : _("not enabled"), false);
}
/*
- Copyright (C) 2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2019-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
class FilmViewer;
+
class SystemInformationDialog : public TableDialog
{
public:
SystemInformationDialog (wxWindow* parent, std::weak_ptr<FilmViewer> viewer);
-
};
#include <sys/time.h>
-using std::pair;
using std::shared_ptr;
using boost::optional;
_three_d = t;
}
+ void set_optimise_for_j2k (bool o) {
+ _optimise_for_j2k = o;
+ }
+
protected:
NextFrameResult get_next_frame (bool non_blocking);
boost::optional<int> time_until_next_frame () const;
StateTimer _state_timer;
+ bool _optimise_for_j2k = false;
+
private:
/** Mutex protecting all the state in this class */
mutable boost::mutex _mutex;
auto const image_size = _image->size();
int const waveform_height = GetSize().GetHeight() - _vertical_margin * 2;
- _waveform = make_shared<Image>(AV_PIX_FMT_RGB24, dcp::Size (image_size.width, waveform_height), true);
+ _waveform = make_shared<Image>(AV_PIX_FMT_RGB24, dcp::Size (image_size.width, waveform_height), Image::Alignment::PADDED);
for (int x = 0; x < image_size.width; ++x) {
_waveform = _waveform->scale (
dcp::Size (GetSize().GetWidth() - _x_axis_width, waveform_height),
- dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, false, false
+ dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, Image::Alignment::COMPACT, false
);
}
mandatory=True)
if conf.env.TARGET_LINUX:
- conf.env.append_value('CXXFLAGS', ['-DGLX_GLXEXT_PROTOTYPES'])
+ conf.env.append_value('CXXFLAGS', ['-DGL_GLEXT_PROTOTYPES', '-DGLX_GLXEXT_PROTOTYPES'])
if conf.env.TARGET_WINDOWS:
conf.env.append_value('CXXFLAGS', ['-DWGL_WGLEXT_PROTOTYPES'])
if conf.env.TARGET_WINDOWS or conf.env.TARGET_LINUX:
conf.check_cfg(package='gl', args='--cflags --libs', uselib_store='GL', mandatory=True)
conf.check_cfg(package='glu', args='--cflags --libs', uselib_store='GLU', mandatory=True)
+ if conf.env.TARGET_WINDOWS:
+ conf.check_cfg(package='glew', args='--cflags --libs', uselib_store='GLEW', mandatory=True)
else:
conf.env.STLIB_GL = 'gl'
conf.env.STLIB_GLU = 'glu'
if bld.env.TARGET_LINUX:
obj.uselib += 'GTK GL GLU '
if bld.env.TARGET_WINDOWS:
- obj.uselib += 'WINSOCK2 OLE32 DSOUND WINMM KSUSER GL GLU '
+ obj.uselib += 'WINSOCK2 OLE32 DSOUND WINMM KSUSER GL GLU GLEW '
if bld.env.TARGET_OSX:
obj.framework = ['CoreAudio', 'OpenGL']
obj.use = 'libdcpomatic2'
map.set (i, i, 1);
}
- Butler butler (film, make_shared<Player>(film), map, 6, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, false);
+ Butler butler (film, make_shared<Player>(film, Image::Alignment::COMPACT), map, 6, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, Image::Alignment::COMPACT, false, false);
BOOST_CHECK (butler.get_video(true, 0).second == DCPTime());
BOOST_CHECK (butler.get_video(true, 0).second == DCPTime::from_frames(1, 24));
BOOST_AUTO_TEST_CASE (client_server_test_rgb)
{
- auto image = make_shared<Image>(AV_PIX_FMT_RGB24, dcp::Size (1998, 1080), true);
+ auto image = make_shared<Image>(AV_PIX_FMT_RGB24, dcp::Size (1998, 1080), Image::Alignment::PADDED);
uint8_t* p = image->data()[0];
for (int y = 0; y < 1080; ++y) {
p += image->stride()[0];
}
- auto sub_image = make_shared<Image>(AV_PIX_FMT_BGRA, dcp::Size (100, 200), true);
+ auto sub_image = make_shared<Image>(AV_PIX_FMT_BGRA, dcp::Size (100, 200), Image::Alignment::PADDED);
p = sub_image->data()[0];
for (int y = 0; y < 200; ++y) {
uint8_t* q = p;
BOOST_AUTO_TEST_CASE (client_server_test_yuv)
{
- auto image = make_shared<Image>(AV_PIX_FMT_YUV420P, dcp::Size (1998, 1080), true);
+ auto image = make_shared<Image>(AV_PIX_FMT_YUV420P, dcp::Size (1998, 1080), Image::Alignment::PADDED);
for (int i = 0; i < image->planes(); ++i) {
uint8_t* p = image->data()[i];
}
}
- auto sub_image = make_shared<Image>(AV_PIX_FMT_BGRA, dcp::Size (100, 200), true);
+ auto sub_image = make_shared<Image>(AV_PIX_FMT_BGRA, dcp::Size (100, 200), Image::Alignment::PADDED);
uint8_t* p = sub_image->data()[0];
for (int y = 0; y < 200; ++y) {
uint8_t* q = p;
BOOST_AUTO_TEST_CASE (client_server_test_j2k)
{
- auto image = make_shared<Image>(AV_PIX_FMT_YUV420P, dcp::Size (1998, 1080), true);
+ auto image = make_shared<Image>(AV_PIX_FMT_YUV420P, dcp::Size (1998, 1080), Image::Alignment::PADDED);
for (int i = 0; i < image->planes(); ++i) {
uint8_t* p = image->data()[i];
ov_content = make_shared<DCPContent>(ov->dir(ov->dcp_name(false)));
test->examine_and_add_content (ov_content);
BOOST_REQUIRE (!wait_for_jobs());
- auto player = make_shared<Player>(test);
+ auto player = make_shared<Player>(test, Image::Alignment::COMPACT);
auto decoder = std::dynamic_pointer_cast<DCPDecoder>(player->_pieces.front()->decoder);
BOOST_REQUIRE (decoder);
auto vf_content = make_shared<DCPContent>(vf->dir(vf->dcp_name(false)));
test->examine_and_add_content (vf_content);
BOOST_REQUIRE (!wait_for_jobs());
- player.reset (new Player(test));
+ player = make_shared<Player>(test, Image::Alignment::COMPACT);
decoder = std::dynamic_pointer_cast<DCPDecoder>(player->_pieces.front()->decoder);
BOOST_REQUIRE (decoder);
auto encrypted_content = make_shared<DCPContent>(encrypted->dir(encrypted->dcp_name(false)));
test->examine_and_add_content (encrypted_content);
BOOST_REQUIRE (!wait_for_jobs());
- player = make_shared<Player>(test);
+ player = make_shared<Player>(test, Image::Alignment::COMPACT);
decoder = std::dynamic_pointer_cast<DCPDecoder>(player->_pieces.front()->decoder);
BOOST_REQUIRE (decoder);
using std::make_shared;
-using std::pair;
-using std::shared_ptr;
-using boost::optional;
+using std::make_shared;
#if BOOST_VERSION >= 106100
using namespace boost::placeholders;
#endif
auto butler = std::make_shared<Butler>(
film,
- shared_ptr<Player>(new Player(film)),
+ make_shared<Player>(film, Image::Alignment::PADDED),
AudioMapping(6, 6),
6,
bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24),
VideoRange::FULL,
- false,
- true
+ Image::Alignment::PADDED,
+ true,
+ false
);
auto audio_buffer = new float[2000 * 6];
}
/* assuming DCP is 24fps/48kHz */
butler->get_audio (audio_buffer, 2000);
- p.first->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true);
+ p.first->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, true);
}
delete[] audio_buffer;
}
ref_buffer_size = info.samplerate * info.channels;
ref_buffer = new float[ref_buffer_size];
- auto player = make_shared<Player>(film);
+ auto player = make_shared<Player>(film, Image::Alignment::COMPACT);
player->Audio.connect (bind (&audio, _1, info.channels));
while (!player->pass ()) {}
film->examine_and_add_content (content);
BOOST_REQUIRE (!wait_for_jobs ());
- auto player = make_shared<Player>(film);
+ auto player = make_shared<Player>(film, Image::Alignment::COMPACT);
while (!player->pass ()) {}
}
film->examine_and_add_content (content);
BOOST_REQUIRE (!wait_for_jobs ());
- auto player = make_shared<Player>(film);
+ auto player = make_shared<Player>(film, Image::Alignment::COMPACT);
player->set_fast ();
while (!player->pass ()) {}
}
film->examine_and_add_content (content);
BOOST_REQUIRE (!wait_for_jobs ());
- auto player = make_shared<Player>(film);
+ auto player = make_shared<Player>(film, Image::Alignment::COMPACT);
player->set_fast ();
BOOST_CHECK_NO_THROW (while (!player->pass()) {});
}
film->examine_and_add_content (content);
BOOST_REQUIRE (!wait_for_jobs());
film->write_metadata ();
- auto player = make_shared<Player>(film);
+ auto player = make_shared<Player>(film, Image::Alignment::COMPACT);
BOOST_REQUIRE (content->video_frame_rate());
BOOST_CHECK_CLOSE (content->video_frame_rate().get(), fps, 0.01);
using std::cout;
using std::list;
using std::make_shared;
-using std::shared_ptr;
using std::string;
BOOST_AUTO_TEST_CASE (aligned_image_test)
{
- auto s = new Image (AV_PIX_FMT_RGB24, dcp::Size (50, 50), true);
+ auto s = new Image (AV_PIX_FMT_RGB24, dcp::Size (50, 50), Image::Alignment::PADDED);
BOOST_CHECK_EQUAL (s->planes(), 1);
/* 192 is 150 aligned to the nearest 64 bytes */
BOOST_CHECK_EQUAL (s->stride()[0], 192);
BOOST_CHECK_EQUAL (t->stride()[0], s->stride()[0]);
/* assignment operator */
- auto u = new Image (AV_PIX_FMT_YUV422P, dcp::Size (150, 150), false);
+ auto u = new Image (AV_PIX_FMT_YUV422P, dcp::Size (150, 150), Image::Alignment::COMPACT);
*u = *s;
BOOST_CHECK_EQUAL (u->planes(), 1);
BOOST_CHECK_EQUAL (u->stride()[0], 192);
BOOST_AUTO_TEST_CASE (compact_image_test)
{
- auto s = new Image (AV_PIX_FMT_RGB24, dcp::Size (50, 50), false);
+ auto s = new Image (AV_PIX_FMT_RGB24, dcp::Size (50, 50), Image::Alignment::COMPACT);
BOOST_CHECK_EQUAL (s->planes(), 1);
BOOST_CHECK_EQUAL (s->stride()[0], 50 * 3);
BOOST_CHECK_EQUAL (s->line_size()[0], 50 * 3);
BOOST_CHECK_EQUAL (t->stride()[0], s->stride()[0]);
/* assignment operator */
- auto u = new Image (AV_PIX_FMT_YUV422P, dcp::Size (150, 150), true);
+ auto u = new Image (AV_PIX_FMT_YUV422P, dcp::Size (150, 150), Image::Alignment::PADDED);
*u = *s;
BOOST_CHECK_EQUAL (u->planes(), 1);
BOOST_CHECK_EQUAL (u->stride()[0], 50 * 3);
alpha_blend_test_one (AVPixelFormat format, string suffix)
{
auto proxy = make_shared<FFmpegImageProxy>(TestPaths::private_data() / "prophet_frame.tiff");
- auto raw = proxy->image().image;
- auto background = raw->convert_pixel_format (dcp::YUVToRGB::REC709, format, true, false);
+ auto raw = proxy->image(Image::Alignment::PADDED).image;
+ auto background = raw->convert_pixel_format (dcp::YUVToRGB::REC709, format, Image::Alignment::PADDED, false);
- auto overlay = make_shared<Image>(AV_PIX_FMT_BGRA, dcp::Size(431, 891), true);
+ auto overlay = make_shared<Image>(AV_PIX_FMT_BGRA, dcp::Size(431, 891), Image::Alignment::PADDED);
overlay->make_transparent ();
for (int y = 0; y < 128; ++y) {
background->alpha_blend (overlay, Position<int> (13, 17));
- auto save = background->convert_pixel_format (dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, false, false);
+ auto save = background->convert_pixel_format (dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, Image::Alignment::COMPACT, false);
write_image (save, "build/test/image_test_" + suffix + ".png");
check_image ("build/test/image_test_" + suffix + ".png", TestPaths::private_data() / ("image_test_" + suffix + ".png"));
{
int const stride = 48 * 4;
- auto A = make_shared<Image>(AV_PIX_FMT_BGRA, dcp::Size (48, 48), false);
+ auto A = make_shared<Image>(AV_PIX_FMT_BGRA, dcp::Size (48, 48), Image::Alignment::COMPACT);
A->make_transparent ();
auto a = A->data()[0];
list<PositionImage> all;
all.push_back (PositionImage (A, Position<int>(0, 0)));
- auto merged = merge (all);
+ auto merged = merge (all, Image::Alignment::COMPACT);
BOOST_CHECK (merged.position == Position<int>(0, 0));
BOOST_CHECK_EQUAL (memcmp (merged.image->data()[0], A->data()[0], stride * 48), 0);
/** Test merge (list<PositionImage>) with two images */
BOOST_AUTO_TEST_CASE (merge_test2)
{
- auto A = make_shared<Image>(AV_PIX_FMT_BGRA, dcp::Size (48, 1), false);
+ auto A = make_shared<Image>(AV_PIX_FMT_BGRA, dcp::Size (48, 1), Image::Alignment::COMPACT);
A->make_transparent ();
auto a = A->data()[0];
for (int x = 0; x < 16; ++x) {
a[x * 4 + 3] = 255;
}
- auto B = make_shared<Image>(AV_PIX_FMT_BGRA, dcp::Size (48, 1), false);
+ auto B = make_shared<Image>(AV_PIX_FMT_BGRA, dcp::Size (48, 1), Image::Alignment::COMPACT);
B->make_transparent ();
auto b = B->data()[0];
for (int x = 0; x < 16; ++x) {
list<PositionImage> all;
all.push_back (PositionImage(A, Position<int>(0, 0)));
all.push_back (PositionImage(B, Position<int>(0, 0)));
- auto merged = merge (all);
+ auto merged = merge (all, Image::Alignment::COMPACT);
BOOST_CHECK (merged.position == Position<int>(0, 0));
BOOST_AUTO_TEST_CASE (crop_scale_window_test)
{
auto proxy = make_shared<FFmpegImageProxy>("test/data/flat_red.png");
- auto raw = proxy->image().image;
+ auto raw = proxy->image(Image::Alignment::PADDED).image;
auto out = raw->crop_scale_window(
- Crop(), dcp::Size(1998, 836), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_YUV420P, VideoRange::FULL, true, false
+ Crop(), dcp::Size(1998, 836), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_YUV420P, VideoRange::FULL, Image::Alignment::PADDED, false
);
- auto save = out->scale(dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, false, false);
+ auto save = out->scale(dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, Image::Alignment::COMPACT, false);
write_image(save, "build/test/crop_scale_window_test.png");
check_image("test/data/crop_scale_window_test.png", "build/test/crop_scale_window_test.png");
}
/** Special cases of Image::crop_scale_window which triggered some valgrind warnings */
BOOST_AUTO_TEST_CASE (crop_scale_window_test2)
{
- auto image = make_shared<Image>(AV_PIX_FMT_XYZ12LE, dcp::Size(2048, 858), true);
+ auto image = make_shared<Image>(AV_PIX_FMT_XYZ12LE, dcp::Size(2048, 858), Image::Alignment::PADDED);
image->crop_scale_window (
- Crop(279, 0, 0, 0), dcp::Size(1069, 448), dcp::Size(1069, 578), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, false, false
+ Crop(279, 0, 0, 0), dcp::Size(1069, 448), dcp::Size(1069, 578), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, Image::Alignment::COMPACT, false
);
image->crop_scale_window (
- Crop(2048, 0, 0, 0), dcp::Size(1069, 448), dcp::Size(1069, 578), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, false, false
+ Crop(2048, 0, 0, 0), dcp::Size(1069, 448), dcp::Size(1069, 578), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, Image::Alignment::COMPACT, false
);
}
BOOST_AUTO_TEST_CASE (crop_scale_window_test3)
{
auto proxy = make_shared<FFmpegImageProxy>(TestPaths::private_data() / "player_seek_test_0.png");
- auto xyz = proxy->image().image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, true, false);
+ auto xyz = proxy->image(Image::Alignment::PADDED).image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, Image::Alignment::PADDED, false);
auto cropped = xyz->crop_scale_window(
- Crop(512, 0, 0, 0), dcp::Size(1486, 1080), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, false, false
+ Crop(512, 0, 0, 0), dcp::Size(1486, 1080), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, Image::Alignment::COMPACT, false
);
write_image(cropped, "build/test/crop_scale_window_test3.png");
check_image("test/data/crop_scale_window_test3.png", "build/test/crop_scale_window_test3.png");
BOOST_AUTO_TEST_CASE (crop_scale_window_test4)
{
auto proxy = make_shared<FFmpegImageProxy>(TestPaths::private_data() / "player_seek_test_0.png");
- auto xyz = proxy->image().image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, true, false);
+ auto xyz = proxy->image(Image::Alignment::PADDED).image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGB24, Image::Alignment::PADDED, false);
auto cropped = xyz->crop_scale_window(
- Crop(512, 0, 0, 0), dcp::Size(1486, 1080), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_XYZ12LE, VideoRange::FULL, false, false
+ Crop(512, 0, 0, 0), dcp::Size(1486, 1080), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_XYZ12LE, VideoRange::FULL, Image::Alignment::COMPACT, false
);
write_image(cropped, "build/test/crop_scale_window_test4.png");
check_image("test/data/crop_scale_window_test4.png", "build/test/crop_scale_window_test4.png", 35000);
BOOST_AUTO_TEST_CASE (crop_scale_window_test5)
{
auto proxy = make_shared<FFmpegImageProxy>(TestPaths::private_data() / "player_seek_test_0.png");
- auto xyz = proxy->image().image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_XYZ12LE, true, false);
+ auto xyz = proxy->image(Image::Alignment::PADDED).image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_XYZ12LE, Image::Alignment::PADDED, false);
auto cropped = xyz->crop_scale_window(
- Crop(512, 0, 0, 0), dcp::Size(1486, 1080), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, false, false
+ Crop(512, 0, 0, 0), dcp::Size(1486, 1080), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, Image::Alignment::COMPACT, false
);
write_image(cropped, "build/test/crop_scale_window_test5.png");
check_image("test/data/crop_scale_window_test5.png", "build/test/crop_scale_window_test5.png");
BOOST_AUTO_TEST_CASE (crop_scale_window_test6)
{
auto proxy = make_shared<FFmpegImageProxy>(TestPaths::private_data() / "player_seek_test_0.png");
- auto xyz = proxy->image().image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_XYZ12LE, true, false);
+ auto xyz = proxy->image(Image::Alignment::PADDED).image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_XYZ12LE, Image::Alignment::PADDED, false);
auto cropped = xyz->crop_scale_window(
- Crop(512, 0, 0, 0), dcp::Size(1486, 1080), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_XYZ12LE, VideoRange::FULL, false, false
+ Crop(512, 0, 0, 0), dcp::Size(1486, 1080), dcp::Size(1998, 1080), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_XYZ12LE, VideoRange::FULL, Image::Alignment::COMPACT, false
);
write_image(cropped, "build/test/crop_scale_window_test6.png");
check_image("test/data/crop_scale_window_test6.png", "build/test/crop_scale_window_test6.png", 35000);
using namespace boost::filesystem;
for (int left_crop = 0; left_crop < 8; ++left_crop) {
auto proxy = make_shared<FFmpegImageProxy>("test/data/rgb_grey_testcard.png");
- auto yuv = proxy->image().image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_YUV420P, true, false);
+ auto yuv = proxy->image(Image::Alignment::PADDED).image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_YUV420P, Image::Alignment::PADDED, false);
int rounded = left_crop - (left_crop % 2);
auto cropped = yuv->crop_scale_window(
Crop(left_crop, 0, 0, 0),
VideoRange::VIDEO,
AV_PIX_FMT_RGB24,
VideoRange::VIDEO,
- true,
+ Image::Alignment::PADDED,
false
);
path file = String::compose("crop_scale_window_test7-%1.png", left_crop);
BOOST_AUTO_TEST_CASE (as_png_test)
{
auto proxy = make_shared<FFmpegImageProxy>("test/data/3d_test/000001.png");
- auto image_rgb = proxy->image().image;
- auto image_bgr = image_rgb->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_BGRA, true, false);
+ auto image_rgb = proxy->image(Image::Alignment::PADDED).image;
+ auto image_bgr = image_rgb->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_BGRA, Image::Alignment::PADDED, false);
image_rgb->as_png().write ("build/test/as_png_rgb.png");
image_bgr->as_png().write ("build/test/as_png_bgr.png");
static void
fade_test_format_black (AVPixelFormat f, string name)
{
- Image yuv (f, dcp::Size(640, 480), true);
+ Image yuv (f, dcp::Size(640, 480), Image::Alignment::PADDED);
yuv.make_black ();
yuv.fade (0);
string const filename = "fade_test_black_" + name + ".png";
- yuv.convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, true, false)->as_png().write("build/test/" + filename);
+ yuv.convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, Image::Alignment::PADDED, false)->as_png().write("build/test/" + filename);
check_image ("test/data/" + filename, "build/test/" + filename);
}
fade_test_format_red (AVPixelFormat f, float amount, string name)
{
auto proxy = make_shared<FFmpegImageProxy>("test/data/flat_red.png");
- auto red = proxy->image().image->convert_pixel_format(dcp::YUVToRGB::REC709, f, true, false);
+ auto red = proxy->image(Image::Alignment::PADDED).image->convert_pixel_format(dcp::YUVToRGB::REC709, f, Image::Alignment::PADDED, false);
red->fade (amount);
string const filename = "fade_test_red_" + name + ".png";
- red->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, true, false)->as_png().write("build/test/" + filename);
+ red->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, Image::Alignment::PADDED, false)->as_png().write("build/test/" + filename);
check_image ("test/data/" + filename, "build/test/" + filename);
}
int N = 0;
for (auto i: pix_fmts) {
- auto foo = make_shared<Image>(i, in_size, true);
+ auto foo = make_shared<Image>(i, in_size, Image::Alignment::PADDED);
foo->make_black ();
- auto bar = foo->scale (out_size, dcp::YUVToRGB::REC601, AV_PIX_FMT_RGB24, true, false);
+ auto bar = foo->scale (out_size, dcp::YUVToRGB::REC601, AV_PIX_FMT_RGB24, Image::Alignment::PADDED, false);
uint8_t* p = bar->data()[0];
for (int y = 0; y < bar->size().height; ++y) {
BOOST_AUTO_TEST_CASE (make_part_black_test)
{
auto proxy = make_shared<FFmpegImageProxy>("test/data/flat_red.png");
- auto original = proxy->image().image;
+ auto original = proxy->image(Image::Alignment::PADDED).image;
list<AVPixelFormat> pix_fmts = {
AV_PIX_FMT_RGB24,
int N = 0;
for (auto i: pix_fmts) {
for (auto j: positions) {
- auto foo = original->convert_pixel_format(dcp::YUVToRGB::REC601, i, true, false);
+ auto foo = original->convert_pixel_format(dcp::YUVToRGB::REC601, i, Image::Alignment::PADDED, false);
foo->make_part_black (j.first, j.second);
- auto bar = foo->convert_pixel_format (dcp::YUVToRGB::REC601, AV_PIX_FMT_RGB24, true, false);
+ auto bar = foo->convert_pixel_format (dcp::YUVToRGB::REC601, AV_PIX_FMT_RGB24, Image::Alignment::PADDED, false);
auto p = bar->data()[0];
for (int y = 0; y < bar->size().height; ++y) {
*/
BOOST_AUTO_TEST_CASE (over_crop_test)
{
- auto image = make_shared<Image>(AV_PIX_FMT_RGB24, dcp::Size(128, 128), true);
+ auto image = make_shared<Image>(AV_PIX_FMT_RGB24, dcp::Size(128, 128), Image::Alignment::PADDED);
image->make_black ();
auto scaled = image->crop_scale_window (
- Crop(0, 0, 128, 128), dcp::Size(1323, 565), dcp::Size(1349, 565), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, true, true
+ Crop(0, 0, 128, 128), dcp::Size(1323, 565), dcp::Size(1349, 565), dcp::YUVToRGB::REC709, VideoRange::FULL, AV_PIX_FMT_RGB24, VideoRange::FULL, Image::Alignment::PADDED, true
);
string const filename = "over_crop_test.png";
write_image (scaled, "build/test/" + filename);
BOOST_AUTO_TEST_CASE (low_bitrate_test)
{
- auto image = make_shared<Image>(AV_PIX_FMT_RGB24, dcp::Size(1998, 1080), true);
+ auto image = make_shared<Image>(AV_PIX_FMT_RGB24, dcp::Size(1998, 1080), Image::Alignment::PADDED);
image->make_black ();
+
auto proxy = make_shared<RawImageProxy>(image);
- auto frame = make_shared<PlayerVideo>(proxy, Crop(), boost::optional<double>(), dcp::Size(1998, 1080), dcp::Size(1998, 1080), Eyes::BOTH, Part::WHOLE, boost::optional<ColourConversion>(), VideoRange::FULL, std::weak_ptr<Content>(), boost::optional<Frame>(), false);
+
+ auto frame = make_shared<PlayerVideo>(
+ proxy,
+ Crop(),
+ boost::optional<double>(),
+ dcp::Size(1998, 1080),
+ dcp::Size(1998, 1080),
+ Eyes::BOTH,
+ Part::WHOLE,
+ boost::optional<ColourConversion>(),
+ VideoRange::FULL,
+ std::weak_ptr<Content>(),
+ boost::optional<Frame>(),
+ false
+ );
+
auto dcp_video = make_shared<DCPVideo>(frame, 0, 24, 100000000, Resolution::TWO_K);
auto j2k = dcp_video->encode_locally();
BOOST_REQUIRE (j2k.size() >= 16536);
using std::dynamic_pointer_cast;
using std::make_shared;
-using std::shared_ptr;
BOOST_AUTO_TEST_CASE (overlap_video_test1)
B->video->set_length (24);
B->set_position (film, dcpomatic::DCPTime::from_seconds(1));
- auto player = make_shared<Player>(film);
+ auto player = make_shared<Player>(film, Image::Alignment::COMPACT);
auto pieces = player->_pieces;
BOOST_REQUIRE_EQUAL (pieces.size(), 2U);
BOOST_CHECK_EQUAL (pieces.front()->content, A);
f->height = 480;
f->format = static_cast<int> (i.format);
av_frame_get_buffer (f, true);
- Image t (f);
+ Image t (f, Image::Alignment::COMPACT);
BOOST_CHECK_EQUAL(t.planes(), i.planes);
BOOST_CHECK_EQUAL(t.sample_size(0).height, i.lines[0]);
BOOST_CHECK_EQUAL(t.sample_size(1).height, i.lines[1]);
*/
-#include "lib/film.h"
-#include "lib/ffmpeg_content.h"
-#include "lib/dcp_content_type.h"
-#include "lib/ratio.h"
#include "lib/audio_buffers.h"
-#include "lib/player.h"
-#include "lib/video_content.h"
-#include "lib/image_content.h"
-#include "lib/string_text_file_content.h"
-#include "lib/content_factory.h"
-#include "lib/dcp_content.h"
-#include "lib/text_content.h"
#include "lib/butler.h"
#include "lib/compose.hpp"
+#include "lib/content_factory.h"
#include "lib/cross.h"
+#include "lib/dcp_content.h"
+#include "lib/dcp_content_type.h"
+#include "lib/ffmpeg_content.h"
+#include "lib/film.h"
+#include "lib/image_content.h"
+#include "lib/player.h"
+#include "lib/ratio.h"
+#include "lib/string_text_file_content.h"
+#include "lib/text_content.h"
+#include "lib/video_content.h"
#include "test.h"
#include <boost/test/unit_test.hpp>
#include <boost/algorithm/string.hpp>
using std::cout;
using std::list;
-using std::pair;
using std::shared_ptr;
using std::make_shared;
using boost::bind;
accumulated = std::make_shared<AudioBuffers>(film->audio_channels(), 0);
- auto player = std::make_shared<Player>(film);
+ auto player = std::make_shared<Player>(film, Image::Alignment::COMPACT);
player->Audio.connect (bind (&accumulate, _1, _2));
while (!player->pass ()) {}
BOOST_REQUIRE (accumulated->frames() >= 48000);
/* Length should be rounded up from B's length to the next video frame */
BOOST_CHECK (film->length() == DCPTime::from_frames(3 * 24 + 1, 24));
- auto player = std::make_shared<Player>(film);
+ auto player = std::make_shared<Player>(film, Image::Alignment::COMPACT);
player->setup_pieces ();
BOOST_REQUIRE_EQUAL (player->_black._periods.size(), 1U);
BOOST_CHECK (player->_black._periods.front() == DCPTimePeriod(DCPTime::from_frames(3 * 24, 24), DCPTime::from_frames(3 * 24 + 1, 24)));
film->examine_and_add_content (s);
BOOST_REQUIRE (!wait_for_jobs ());
- auto player = std::make_shared<Player>(film);
+ auto player = std::make_shared<Player>(film, Image::Alignment::COMPACT);
player->Video.connect (bind (&video, _1, _2));
player->Audio.connect (bind (&audio, _1, _2));
video_frames = audio_frames = 0;
BOOST_REQUIRE (!wait_for_jobs ());
dcp->only_text()->set_use (true);
- auto player = std::make_shared<Player>(film);
+ auto player = std::make_shared<Player>(film, Image::Alignment::COMPACT);
player->set_fast ();
player->set_always_burn_open_subtitles ();
player->set_play_referenced ();
- auto butler = std::make_shared<Butler>(film, player, AudioMapping(), 2, bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true);
+ auto butler = std::make_shared<Butler>(film, player, AudioMapping(), 2, bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, Image::Alignment::PADDED, true, false);
butler->disable_audio();
for (int i = 0; i < 10; ++i) {
butler->seek (t, true);
auto video = butler->get_video(true, 0);
BOOST_CHECK_EQUAL(video.second.get(), t.get());
- write_image(video.first->image(bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true), String::compose("build/test/player_seek_test_%1.png", i));
+ write_image(video.first->image(bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, true), String::compose("build/test/player_seek_test_%1.png", i));
/* This 14.08 is empirically chosen (hopefully) to accept changes in rendering between the reference and a test machine
(17.10 and 16.04 seem to anti-alias a little differently) but to reject gross errors e.g. missing fonts or missing
text altogether.
BOOST_REQUIRE (!wait_for_jobs ());
dcp->only_text()->set_use (true);
- auto player = std::make_shared<Player>(film);
+ auto player = std::make_shared<Player>(film, Image::Alignment::COMPACT);
player->set_fast ();
player->set_always_burn_open_subtitles ();
player->set_play_referenced ();
- auto butler = std::make_shared<Butler>(film, player, AudioMapping(), 2, bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true);
+ auto butler = std::make_shared<Butler>(film, player, AudioMapping(), 2, bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, Image::Alignment::PADDED, true, false);
butler->disable_audio();
butler->seek(DCPTime::from_seconds(5), true);
auto video = butler->get_video(true, 0);
BOOST_CHECK_EQUAL(video.second.get(), t.get());
write_image(
- video.first->image(bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true), String::compose("build/test/player_seek_test2_%1.png", i)
+ video.first->image(bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, true), String::compose("build/test/player_seek_test2_%1.png", i)
);
check_image(TestPaths::private_data() / String::compose("player_seek_test2_%1.png", i), String::compose("build/test/player_seek_test2_%1.png", i), 14.08);
}
text->only_text()->set_type (TextType::CLOSED_CAPTION);
text->only_text()->set_use (true);
- auto player = std::make_shared<Player>(film);
+ auto player = std::make_shared<Player>(film, Image::Alignment::COMPACT);
player->set_ignore_video ();
player->set_ignore_audio ();
film->examine_and_add_content (boon);
BOOST_REQUIRE (!wait_for_jobs());
- auto player = std::make_shared<Player>(film);
+ auto player = std::make_shared<Player>(film, Image::Alignment::COMPACT);
player->set_fast ();
- auto butler = std::make_shared<Butler>(film, player, AudioMapping(), 6, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true);
+ auto butler = std::make_shared<Butler>(film, player, AudioMapping(), 6, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, Image::Alignment::COMPACT, true, false);
/* Wait for the butler to fill */
dcpomatic_sleep_seconds (5);
rms_error (boost::filesystem::path ref, boost::filesystem::path check)
{
FFmpegImageProxy ref_proxy (ref);
- auto ref_image = ref_proxy.image().image;
+ auto ref_image = ref_proxy.image(Image::Alignment::COMPACT).image;
FFmpegImageProxy check_proxy (check);
- auto check_image = check_proxy.image().image;
+ auto check_image = check_proxy.image(Image::Alignment::COMPACT).image;
BOOST_REQUIRE_EQUAL (ref_image->pixel_format(), check_image->pixel_format());
AVPixelFormat const format = ref_image->pixel_format();
using std::list;
using std::make_shared;
-using std::shared_ptr;
using std::string;
using namespace dcpomatic;
film->set_sequence (false);
film->add_content (content);
- auto player = make_shared<Player>(film);
+ auto player = make_shared<Player>(film, Image::Alignment::COMPACT);
/* Position 0, no trim, content rate = DCP rate */
content->set_position (film, DCPTime());
film->set_video_frame_rate (24);
player->setup_pieces ();
BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1U);
- shared_ptr<Piece> piece = player->_pieces.front ();
+ auto piece = player->_pieces.front();
BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.5)), 12);
BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.0)), 72);
film->set_sequence (false);
film->add_content (content);
- auto player = make_shared<Player>(film);
+ auto player = make_shared<Player>(film, Image::Alignment::COMPACT);
/* Position 0, no trim, content rate = DCP rate */
content->set_position (film, DCPTime());
film->set_video_frame_rate (24);
player->setup_pieces ();
BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1U);
- shared_ptr<Piece> piece = player->_pieces.front ();
+ auto piece = player->_pieces.front ();
BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0).get(), 0);
BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 12).get(), DCPTime::from_seconds(0.5).get());
BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 72).get(), DCPTime::from_seconds(3.0).get());
film->set_sequence (false);
film->add_content (content);
- auto player = make_shared<Player>(film);
+ auto player = make_shared<Player>(film, Image::Alignment::COMPACT);
/* Position 0, no trim, video/audio content rate = video/audio DCP rate */
content->set_position (film, DCPTime());
Ls = sf_open ("build/test/upmixer_a_test/Ls.wav", SFM_WRITE, &info);
Rs = sf_open ("build/test/upmixer_a_test/Rs.wav", SFM_WRITE, &info);
- auto player = make_shared<Player>(film);
+ auto player = make_shared<Player>(film, Image::Alignment::COMPACT);
player->Audio.connect (bind (&write, _1, _2));
while (!player->pass()) {}
make_and_verify_dcp (vf, {dcp::VerificationNote::Code::EXTERNAL_ASSET});
/* Check that the selected reel assets are right */
- auto player = make_shared<Player>(vf);
+ auto player = make_shared<Player>(vf, Image::Alignment::COMPACT);
auto a = player->get_reel_assets();
BOOST_REQUIRE_EQUAL (a.size(), 4U);
auto i = a.begin();
using std::min;
-using std::make_pair;
using std::max;
using std::pair;
using std::string;
shared_ptr<Image>
grey_image (dcp::Size size, uint8_t pixel)
{
- auto grey = make_shared<Image>(AV_PIX_FMT_RGB24, size, true);
+ auto grey = make_shared<Image>(AV_PIX_FMT_RGB24, size, Image::Alignment::PADDED);
for (int y = 0; y < size.height; ++y) {
uint8_t* p = grey->data()[0] + y * grey->stride()[0];
for (int x = 0; x < size.width; ++x) {
write_image (grey_image(size, grey_pixel), file);
FFmpegImageProxy proxy (file);
- ImageProxy::Result result = proxy.image ();
+ ImageProxy::Result result = proxy.image (Image::Alignment::COMPACT);
BOOST_REQUIRE (!result.error);
for (int y = 0; y < size.height; ++y) {
BOOST_REQUIRE (!player->pass());
}
- auto image = player_video->image ([](AVPixelFormat f) { return f; }, VideoRange::FULL, true, false);
+ auto image = player_video->image ([](AVPixelFormat f) { return f; }, VideoRange::FULL, false);
for (int y = 0; y < size.height; ++y) {
uint8_t* p = image->data()[0] + y * image->stride()[0];
BOOST_REQUIRE (!decoder->pass());
}
- return pixel_range (content_video->image->image().image);
+ return pixel_range (content_video->image->image(Image::Alignment::COMPACT).image);
}