Fix tests.
authorCarl Hetherington <cth@carlh.net>
Sun, 24 Aug 2014 20:10:13 +0000 (21:10 +0100)
committerCarl Hetherington <cth@carlh.net>
Sun, 24 Aug 2014 20:10:13 +0000 (21:10 +0100)
doc/design/player_get_audio.svg [new file with mode: 0644]
doc/design/timing.svg [new file with mode: 0644]
doc/design/who_fills_the_gaps.tex [new file with mode: 0644]
test/player_test.cc
test/test.cc
test/test.h
test/upmixer_a_test.cc

diff --git a/doc/design/player_get_audio.svg b/doc/design/player_get_audio.svg
new file mode 100644 (file)
index 0000000..fe7bdd5
--- /dev/null
@@ -0,0 +1,399 @@
+<?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#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="player_get_audio.svg">
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.2517416"
+     inkscape:cx="368.22037"
+     inkscape:cy="938.8543"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:window-width="1366"
+     inkscape:window-height="714"
+     inkscape:window-x="0"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1" />
+  <defs
+     id="defs4">
+    <marker
+       inkscape:stockid="Arrow1Mstart"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mstart"
+       style="overflow:visible">
+      <path
+         id="path3983"
+         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 "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
+         transform="scale(0.4) translate(10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path3986"
+         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 "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Mstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Mstart-1"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3983-6"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(0.4,0,0,0.4,4,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Mend-4"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3986-5"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1MstartQ"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1MstartQ"
+       style="overflow:visible">
+      <path
+         id="path4874"
+         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 "
+         style="stroke:#008000;stroke-width:1.0pt;fill:#008000;fill-rule:evenodd"
+         transform="scale(0.4) translate(10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Mendh"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mendh"
+       style="overflow:visible;">
+      <path
+         id="path4877"
+         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 "
+         style="stroke:#008000;stroke-width:1.0pt;fill:#008000;fill-rule:evenodd"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Mstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Mstart-2"
+       style="overflow:visible">
+      <path
+         id="path3983-60"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(0.4,0,0,0.4,4,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Mend-9"
+       style="overflow:visible">
+      <path
+         id="path3986-52"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.4,0,0,-0.4,-4,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1MstartM"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1MstartM"
+       style="overflow:visible">
+      <path
+         id="path5026"
+         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 "
+         style="stroke:#ff0000;stroke-width:1.0pt;fill:#ff0000;fill-rule:evenodd"
+         transform="scale(0.4) translate(10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1MendT"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1MendT"
+       style="overflow:visible;">
+      <path
+         id="path5029"
+         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 "
+         style="stroke:#ff0000;stroke-width:1.0pt;fill:#ff0000;fill-rule:evenodd"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1MstartM"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1MstartM-0"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path5026-3"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill:#ff0000;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt"
+         transform="matrix(0.4,0,0,0.4,4,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1MendT"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1MendT-0"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path5029-9"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill:#ff0000;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt"
+         transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+    </marker>
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 55,34.711899 55,198.7119"
+       id="path2985"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 47,190.36218 641,0"
+       id="path2987"
+       inkscape:connector-curvature="0" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Latin Modern Mono;-inkscape-font-specification:Latin Modern Mono"
+       x="25.429111"
+       y="210.57095"
+       id="text2989"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan2991"
+         x="25.429111"
+         y="210.57095">DCP time 0</tspan></text>
+    <rect
+       style="color:#000000;fill:#000000;fill-opacity:0.15425535;stroke:none;stroke-width:0.99999988px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2995"
+       width="267.44409"
+       height="153.85982"
+       x="205.08385"
+       y="-190.34831"
+       transform="scale(1,-1)" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 205.14391,36.525554 0,164.454206"
+       id="path3783"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 472.50163,36.353991 0,164.625769"
+       id="path3785"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:125%;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Latin Modern Mono;-inkscape-font-specification:Latin Modern Mono"
+       x="191.90874"
+       y="212.87964"
+       id="text3787"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3789"
+         x="191.90874"
+         y="212.87964">time</tspan></text>
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Mstart);marker-mid:none;marker-end:url(#Arrow1Mend)"
+       d="m 207.02561,30.692594 263.76528,0"
+       id="path3791"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:125%;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Latin Modern Mono;-inkscape-font-specification:Latin Modern Mono"
+       x="319.72653"
+       y="23.80699"
+       id="text4787"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan4789"
+         x="319.72653"
+         y="23.80699">length</tspan></text>
+    <path
+       style="fill:none;stroke:#008000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 206.07602,19.432227 0,210.960753"
+       id="path4817"
+       inkscape:connector-curvature="0" />
+    <path
+       style="stroke-linejoin:miter;marker-end:url(#Arrow1Mendh);stroke-opacity:1;marker-start:url(#Arrow1MstartQ);stroke:#008000;stroke-linecap:butt;stroke-width:1px;marker-mid:none;fill:none"
+       d="m 207.02561,13.263911 263.76528,0"
+       id="path3791-5"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:125%;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Latin Modern Mono;-inkscape-font-specification:Latin Modern Mono"
+       x="297.97812"
+       y="6.3783064"
+       id="text4787-3"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan4789-8"
+         x="297.97812"
+         y="6.3783064">length_frames</tspan></text>
+    <text
+       sodipodi:linespacing="125%"
+       id="text4929"
+       y="238.74654"
+       x="205.10674"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:125%;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Latin Modern Mono;-inkscape-font-specification:Latin Modern Mono"
+       xml:space="preserve"><tspan
+         y="238.74654"
+         x="205.10674"
+         id="tspan4931"
+         sodipodi:role="line">out</tspan><tspan
+         id="tspan4933"
+         y="253.74654"
+         x="205.10674"
+         sodipodi:role="line" /></text>
+    <rect
+       y="67.863129"
+       x="123.76559"
+       height="71.25898"
+       width="448.18149"
+       id="rect4973"
+       style="color:#000000;fill:#ff0000;fill-opacity:0.30319148;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:1" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path4975"
+       d="m 125.66194,148.65781 77.93059,0"
+       style="color:#000000;fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;marker-start:url(#Arrow1MstartM);marker-end:url(#Arrow1MendT);visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       sodipodi:nodetypes="cc" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:125%;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Latin Modern Mono;-inkscape-font-specification:Latin Modern Mono"
+       x="85.083427"
+       y="163.35722"
+       id="text5098"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan5100"
+         x="85.083427"
+         y="163.35722">dcp_to_content_audio(time)</tspan><tspan
+         sodipodi:role="line"
+         x="85.083427"
+         y="178.35722"
+         id="tspan5102" /></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:125%;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Latin Modern Mono;-inkscape-font-specification:Latin Modern Mono"
+       x="126.75607"
+       y="78.363503"
+       id="text5123"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan5125"
+         x="126.75607"
+         y="78.363503">Content</tspan></text>
+    <rect
+       style="color:#000000;fill:#ff0000;fill-opacity:0.48404256;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect5148"
+       width="204.37869"
+       height="70.190666"
+       x="239.47403"
+       y="68.041344" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:125%;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Latin Modern Mono;-inkscape-font-specification:Latin Modern Mono"
+       x="244.01578"
+       y="78.363503"
+       id="text5567"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan5569"
+         x="244.01578"
+         y="78.363503">in</tspan></text>
+    <path
+       inkscape:connector-curvature="0"
+       id="path4975-9"
+       d="m 125.66194,111.10032 112.28273,0"
+       style="color:#000000;fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;marker-start:url(#Arrow1MstartM);marker-end:url(#Arrow1MendT);visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       sodipodi:nodetypes="cc" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:125%;letter-spacing:0px;word-spacing:0px;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Latin Modern Mono;-inkscape-font-specification:Latin Modern Mono"
+       x="135.21161"
+       y="106.87954"
+       id="text5620"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan5622"
+         x="135.21161"
+         y="106.87954">in-&gt;frame</tspan></text>
+  </g>
+</svg>
diff --git a/doc/design/timing.svg b/doc/design/timing.svg
new file mode 100644 (file)
index 0000000..30325e7
--- /dev/null
@@ -0,0 +1,645 @@
+<?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#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="1052.3622"
+   height="744.09448"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="timing.svg">
+  <defs
+     id="defs4">
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path3830"
+         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 "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Mend-9"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3830-0"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Mend-2"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3830-7"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Mend-7"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3830-77"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.7392904"
+     inkscape:cx="260.70009"
+     inkscape:cy="491.51669"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="1680"
+     inkscape:window-height="1023"
+     inkscape:window-x="1366"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-308.2677)">
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:TeX Gyre Schola;-inkscape-font-specification:TeX Gyre Schola"
+       x="17"
+       y="22.094482"
+       id="text2985"
+       sodipodi:linespacing="125%"
+       transform="translate(0,308.2677)"><tspan
+         sodipodi:role="line"
+         id="tspan2987"
+         x="17"
+         y="22.094482">FFmpeg sources are by far the most complicated, so we consider those only.</tspan><tspan
+         sodipodi:role="line"
+         x="17"
+         y="37.094482"
+         id="tspan2989"></tspan><tspan
+         sodipodi:role="line"
+         x="17"
+         y="52.094482"
+         id="tspan4675">Hardest video case:</tspan><tspan
+         sodipodi:role="line"
+         x="17"
+         y="67.094482"
+         id="tspan4584" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="82.094482"
+         id="tspan4586" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="97.094482"
+         id="tspan4588" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="112.09448"
+         id="tspan4590" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="127.09448"
+         id="tspan4592" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="142.09448"
+         id="tspan4594" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="157.09448"
+         id="tspan4596" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="172.09448"
+         id="tspan4598" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="187.09448"
+         id="tspan4600" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="202.09448"
+         id="tspan4602" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="217.09448"
+         id="tspan4604" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="232.09448"
+         id="tspan4606" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="247.09448"
+         id="tspan4608" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="262.09448"
+         id="tspan4610" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="277.09448"
+         id="tspan4612">Content frames arrive with ContentTime; this is converted to DCP time and checked for validity against</tspan><tspan
+         sodipodi:role="line"
+         x="17"
+         y="292.09448"
+         id="tspan4622">_video_position.  _video_position is incremented by one DCP frame period each time a frame is emitted.</tspan><tspan
+         sodipodi:role="line"
+         x="17"
+         y="307.09448"
+         id="tspan4657">Emission is timestamped with _video_position.</tspan><tspan
+         sodipodi:role="line"
+         x="17"
+         y="322.09448"
+         id="tspan4661" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="337.09448"
+         id="tspan4663">In general, the Decoded::dcp_time is used as a check against the actual position in the DCP (based</tspan><tspan
+         sodipodi:role="line"
+         x="17"
+         y="352.09448"
+         id="tspan4630">on what has been emitted).</tspan><tspan
+         sodipodi:role="line"
+         x="17"
+         y="367.09448"
+         id="tspan4671" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="382.09448"
+         id="tspan4673">Hardest audio case:</tspan><tspan
+         sodipodi:role="line"
+         x="17"
+         y="397.09448"
+         id="tspan4785" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="412.09448"
+         id="tspan4787" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="427.09448"
+         id="tspan4789" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="442.09448"
+         id="tspan4791" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="457.09448"
+         id="tspan4793" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="472.09448"
+         id="tspan4795" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="487.09448"
+         id="tspan4797" /><tspan
+         sodipodi:role="line"
+         x="17"
+         y="502.09448"
+         id="tspan4799">Timestamps are not sample-accurate, here B should be after A but its timestamp says different.  Things</tspan><tspan
+         sodipodi:role="line"
+         x="17"
+         y="517.09448"
+         id="tspan4801">are further complicated by resampling, which renders timestamps invalid.  The upshot is that audio</tspan><tspan
+         sodipodi:role="line"
+         x="17"
+         y="532.09448"
+         id="tspan4803">timestamps are basically useless.  However, since audio is (apparently) always continuous in content files</tspan><tspan
+         sodipodi:role="line"
+         x="17"
+         y="547.09448"
+         id="tspan4805">we can make our own timestamps.</tspan></text>
+    <rect
+       style="color:#000000;fill:#de8787;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2991-9"
+       width="30.424219"
+       height="37.906269"
+       x="311.70773"
+       y="461.45099" />
+    <rect
+       style="color:#000000;fill:#de8787;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2991-9-5"
+       width="30.424219"
+       height="37.906269"
+       x="405.98038"
+       y="461.45099" />
+    <rect
+       style="color:#000000;fill:#de8787;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2991-9-5-5"
+       width="30.424219"
+       height="37.906269"
+       x="217.43507"
+       y="461.45099" />
+    <g
+       id="g4368"
+       transform="translate(185.74311,19.474125)">
+      <rect
+         y="363.08694"
+         x="61.408226"
+         height="37.906269"
+         width="42.547859"
+         id="rect2991"
+         style="color:#000000;fill:#ffb380;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+      <text
+         sodipodi:linespacing="125%"
+         id="text4319"
+         y="373.75745"
+         x="64.765747"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
+         xml:space="preserve"><tspan
+           y="373.75745"
+           x="64.765747"
+           id="tspan4321"
+           sodipodi:role="line">A</tspan></text>
+    </g>
+    <g
+       id="g4363"
+       transform="translate(185.7431,19.474125)">
+      <rect
+         y="363.08694"
+         x="104.95609"
+         height="37.906269"
+         width="42.547859"
+         id="rect2991-4"
+         style="color:#000000;fill:#ffb380;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+      <text
+         sodipodi:linespacing="125%"
+         id="text4323"
+         y="373.75745"
+         x="108.47467"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
+         xml:space="preserve"><tspan
+           y="373.75745"
+           x="108.47467"
+           id="tspan4325"
+           sodipodi:role="line">B</tspan></text>
+    </g>
+    <g
+       id="g4358"
+       transform="translate(185.74312,19.474125)">
+      <rect
+         y="363.08694"
+         x="148.50394"
+         height="37.906269"
+         width="42.547859"
+         id="rect2991-4-1"
+         style="color:#000000;fill:#ffb380;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+      <text
+         sodipodi:linespacing="125%"
+         id="text4327"
+         y="373.75745"
+         x="151.86452"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
+         xml:space="preserve"><tspan
+           y="373.75745"
+           x="151.86452"
+           id="tspan4329"
+           sodipodi:role="line">C</tspan></text>
+    </g>
+    <g
+       id="g4353"
+       transform="translate(183.96221,19.474125)">
+      <rect
+         y="363.08694"
+         x="237.38057"
+         height="37.906269"
+         width="42.547859"
+         id="rect2991-4-1-7"
+         style="color:#000000;fill:#ffb380;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+      <text
+         sodipodi:linespacing="125%"
+         id="text4331"
+         y="373.75745"
+         x="240.5585"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
+         xml:space="preserve"><tspan
+           y="373.75745"
+           x="240.5585"
+           id="tspan4333"
+           sodipodi:role="line">D</tspan></text>
+    </g>
+    <rect
+       style="color:#000000;fill:#de8787;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2991-9-5-5-3"
+       width="30.424219"
+       height="37.906269"
+       x="248.85928"
+       y="461.45099" />
+    <rect
+       style="color:#000000;fill:#de8787;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2991-9-5-5-2"
+       width="30.424219"
+       height="37.906269"
+       x="280.28351"
+       y="461.45099" />
+    <rect
+       style="color:#000000;fill:#de8787;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2991-9-5-5-1"
+       width="30.424219"
+       height="37.906269"
+       x="343.13196"
+       y="461.45099" />
+    <rect
+       style="color:#000000;fill:#de8787;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2991-9-5-5-6"
+       width="30.424219"
+       height="37.906269"
+       x="374.55618"
+       y="461.45099" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
+       x="-190.66861"
+       y="507.70966"
+       id="text4412"
+       sodipodi:linespacing="125%"
+       transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,0,0)"><tspan
+         sodipodi:role="line"
+         id="tspan4414"
+         x="-190.66861"
+         y="507.70966">BLACK</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
+       x="251.85396"
+       y="472.95575"
+       id="text4430"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan4432"
+         x="251.85396"
+         y="472.95575">A</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
+       x="376.83502"
+       y="472.95575"
+       id="text4438"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan4440"
+         x="376.83502"
+         y="472.95575">D</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
+       x="283.88882"
+       y="472.95575"
+       id="text4442"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan4444"
+         x="283.88882"
+         y="472.95575">B</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
+       x="314.1189"
+       y="472.95575"
+       id="text4446"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan4448"
+         x="314.1189"
+         y="472.95575">C</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
+       x="346.7153"
+       y="472.95575"
+       id="text4446-9"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan4448-9"
+         x="346.7153"
+         y="472.95575">C</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
+       x="-56.312008"
+       y="640.36365"
+       id="text4412-5"
+       sodipodi:linespacing="125%"
+       transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,0,0)"><tspan
+         sodipodi:role="line"
+         id="tspan4414-1"
+         x="-56.312008"
+         y="640.36365">BLACK</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
+       x="144.21622"
+       y="541.08624"
+       id="text4492"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan4494"
+         x="144.21622"
+         y="541.08624">(outside content, so black)</tspan></text>
+    <path
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;marker-end:url(#Arrow1Mend);visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 220.72149,530.25751 c 1.80478,-3.15836 7.07827,-26.41646 7.07827,-26.41646"
+       id="path4496"
+       inkscape:connector-curvature="0" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
+       x="334.42267"
+       y="559.13403"
+       id="text4521"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan4523"
+         x="334.42267"
+         y="559.13403">(repeat)</tspan></text>
+    <path
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;marker-end:url(#Arrow1Mend);visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 358.45245,547.88911 c -1.80478,-3.15836 -8.88305,-42.65947 -8.88305,-42.65947"
+       id="path4496-5"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;marker-end:url(#Arrow1Mend);visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 227.48942,529.80632 c 57.58855,-44.73312 159.20595,24.81179 194.4651,-25.26693"
+       id="path4549"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000080;fill-opacity:1;stroke:none;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
+       x="68.27523"
+       y="399.59995"
+       id="text4574"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan4576"
+         x="68.27523"
+         y="399.59995">CONTENT</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000080;fill-opacity:1;stroke:none;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
+       x="68.119232"
+       y="476.80835"
+       id="text4578"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan4580"
+         x="68.119232"
+         y="476.80835">DCP</tspan><tspan
+         sodipodi:role="line"
+         x="68.119232"
+         y="491.80835"
+         id="tspan4582">(at higher frame rate)</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
+       x="255.87259"
+       y="280.20578"
+       id="text4616"
+       sodipodi:linespacing="125%"
+       transform="translate(0,308.2677)"><tspan
+         sodipodi:role="line"
+         id="tspan4618"
+         x="255.87259"
+         y="280.20578" /></text>
+    <g
+       id="g4368-8"
+       transform="translate(77.477495,337.87916)">
+      <rect
+         y="363.08694"
+         x="61.408226"
+         height="37.906269"
+         width="42.547859"
+         id="rect2991-5"
+         style="color:#000000;fill:#ffb380;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+      <text
+         sodipodi:linespacing="125%"
+         id="text4319-7"
+         y="373.75745"
+         x="64.765747"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
+         xml:space="preserve"><tspan
+           y="373.75745"
+           x="64.765747"
+           id="tspan4321-8"
+           sodipodi:role="line">A</tspan></text>
+    </g>
+    <g
+       id="g4368-8-8"
+       transform="translate(108.10564,376.16434)">
+      <rect
+         y="363.08694"
+         x="61.408226"
+         height="37.906269"
+         width="42.547859"
+         id="rect2991-5-0"
+         style="color:#000000;fill:#ffb380;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+      <text
+         sodipodi:linespacing="125%"
+         id="text4319-7-8"
+         y="373.75745"
+         x="64.765747"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
+         xml:space="preserve"><tspan
+           y="373.75745"
+           x="64.765747"
+           id="tspan4321-8-1"
+           sodipodi:role="line">B</tspan></text>
+    </g>
+    <g
+       id="g4368-8-8-9"
+       transform="translate(166.7546,336.60299)">
+      <rect
+         y="363.08694"
+         x="61.408226"
+         height="37.906269"
+         width="42.547859"
+         id="rect2991-5-0-9"
+         style="color:#000000;fill:#ffb380;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+      <text
+         sodipodi:linespacing="125%"
+         id="text4319-7-8-0"
+         y="373.75745"
+         x="64.765747"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
+         xml:space="preserve"><tspan
+           y="373.75745"
+           x="64.765747"
+           id="tspan4321-8-1-5"
+           sodipodi:role="line">C</tspan></text>
+    </g>
+    <g
+       id="g4368-8-8-9-2"
+       transform="translate(210.30246,336.60299)">
+      <rect
+         y="363.08694"
+         x="61.408226"
+         height="37.906269"
+         width="42.547859"
+         id="rect2991-5-0-9-0"
+         style="color:#000000;fill:#ffb380;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+      <text
+         sodipodi:linespacing="125%"
+         id="text4319-7-8-0-0"
+         y="373.75745"
+         x="64.765747"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
+         xml:space="preserve"><tspan
+           y="373.75745"
+           x="64.765747"
+           id="tspan4321-8-1-5-7"
+           sodipodi:role="line">D</tspan></text>
+    </g>
+  </g>
+</svg>
diff --git a/doc/design/who_fills_the_gaps.tex b/doc/design/who_fills_the_gaps.tex
new file mode 100644 (file)
index 0000000..00e8ac3
--- /dev/null
@@ -0,0 +1,30 @@
+\documentclass{article}
+\begin{document}
+
+There is a lot of dancing about to handle potential gaps and sync
+problems in the FFmpeg decoder.  It might be nicer if
+\texttt{FFmpegDecoder} could just spit out video and audio with
+timestamps and let the player sort it out, since the player must
+already handle insertion of black and silence.
+
+The first question would be what time unit the decoder should use to
+stamp its output.  Initially we have the PTS, in some time base, and
+we can convert that to seconds at the content's frame rate; this is
+basically a \texttt{Time}.  So we could emit video and audio content
+with \texttt{Time} stamps.
+
+Then the player receives video frames, and can fill in gaps.
+
+The FFmpeg decoder would still have to account for non-zero initial
+PTS, as it is expected that such `dead time' is trimmed from the
+source implicitly.
+
+The snag with this is that hitherto \texttt{Time} has meant DCP time,
+not time at a content's rates (before the content is potentially sped
+up).  As it stands, seek takes a \texttt{Time} in the DCP and the
+content class converts it to content frames.  This is then (rather
+grottily) converted back to time again via the content frame rate.
+All a bit grim.  Everything should probably work in time rather than
+frame rates.
+
+\end{document}
index d480602422b0ee1a810cfc74a1e38c0ad575eb1b..b6f864f8250e9762f0975eb16e6e79b38af8e360 100644 (file)
@@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE (player_overlaps_test)
        film->examine_and_add_content (C);
        wait_for_jobs ();
 
-       BOOST_CHECK_EQUAL (A->full_length(), DCPTime (280000));
+       BOOST_CHECK_EQUAL (A->full_length(), DCPTime (288000));
 
        A->set_position (DCPTime::from_seconds (0));
        B->set_position (DCPTime::from_seconds (10));
index cbf4b5d4d6f84024cdcff4a3258d2d027b165a53..0211c2cb8ae9d8e88c60a677b4b471f702daad06 100644 (file)
@@ -24,6 +24,7 @@
 #include <vector>
 #include <list>
 #include <Magick++.h>
+#include <sndfile.h>
 #include <libxml++/libxml++.h>
 #include <dcp/dcp.h>
 #include "lib/config.h"
@@ -108,6 +109,45 @@ new_test_film (string name)
        return f;
 }
 
+void
+check_audio_file (boost::filesystem::path ref, boost::filesystem::path check)
+{
+       SF_INFO ref_info;
+       ref_info.format = 0;
+       SNDFILE* ref_file = sf_open (ref.string().c_str(), SFM_READ, &ref_info);
+       BOOST_CHECK (ref_file);
+       
+       SF_INFO check_info;
+       check_info.format = 0;
+       SNDFILE* check_file = sf_open (check.string().c_str(), SFM_READ, &check_info);
+       BOOST_CHECK (check_file);
+
+       BOOST_CHECK_EQUAL (ref_info.frames, check_info.frames);
+       BOOST_CHECK_EQUAL (ref_info.samplerate, check_info.samplerate);
+       BOOST_CHECK_EQUAL (ref_info.channels, check_info.channels);
+       BOOST_CHECK_EQUAL (ref_info.format, check_info.format);
+
+       /* buffer_size is in frames */
+       sf_count_t const buffer_size = 65536 * ref_info.channels;
+       int32_t* ref_buffer = new int32_t[buffer_size];
+       int32_t* check_buffer = new int32_t[buffer_size];
+       
+       sf_count_t N = ref_info.frames;
+       while (N) {
+               sf_count_t this_time = min (buffer_size, N);
+               sf_count_t r = sf_readf_int (ref_file, ref_buffer, this_time);
+               BOOST_CHECK_EQUAL (r, this_time);
+               r = sf_readf_int (check_file, check_buffer, this_time);
+               BOOST_CHECK_EQUAL (r, this_time);
+
+               for (sf_count_t i = 0; i < this_time; ++i) {
+                       BOOST_CHECK (fabs (ref_buffer[i] - check_buffer[i]) <= 65536);
+               }
+
+               N -= this_time;
+       }
+}
+
 void
 check_file (boost::filesystem::path ref, boost::filesystem::path check)
 {
@@ -122,6 +162,9 @@ check_file (boost::filesystem::path ref, boost::filesystem::path check)
        uint8_t* ref_buffer = new uint8_t[buffer_size];
        uint8_t* check_buffer = new uint8_t[buffer_size];
 
+       SafeStringStream error;
+       error << "File " << check.string() << " differs from reference " << ref.string();
+       
        while (N) {
                uintmax_t this_time = min (uintmax_t (buffer_size), N);
                size_t r = fread (ref_buffer, 1, this_time, ref_file);
@@ -129,7 +172,11 @@ check_file (boost::filesystem::path ref, boost::filesystem::path check)
                r = fread (check_buffer, 1, this_time, check_file);
                BOOST_CHECK_EQUAL (r, this_time);
 
-               BOOST_CHECK_EQUAL (memcmp (ref_buffer, check_buffer, this_time), 0);
+               BOOST_CHECK_MESSAGE (memcmp (ref_buffer, check_buffer, this_time) == 0, error.str ());
+               if (memcmp (ref_buffer, check_buffer, this_time)) {
+                       break;
+               }
+               
                N -= this_time;
        }
 
index 57ea32c5792d6a59e8000b4ffe9f327f0d60e89c..c9e477e02b53fffbce03b3f5fe2d7e0522bb3d11 100644 (file)
@@ -28,6 +28,7 @@ extern void wait_for_jobs ();
 extern boost::shared_ptr<Film> new_test_film (std::string);
 extern void check_dcp (boost::filesystem::path, boost::filesystem::path);
 extern void check_file (boost::filesystem::path ref, boost::filesystem::path check);
+extern void check_audio_file (boost::filesystem::path ref, boost::filesystem::path check);
 extern void check_xml (boost::filesystem::path, boost::filesystem::path, std::list<std::string>);
 extern void check_file (boost::filesystem::path, boost::filesystem::path);
 extern boost::filesystem::path test_film_dir (std::string);
index 67e909ed26a9e2d7028232a1db5512301f1d914b..b115db21bff72fe96a3fcddeafc74ef08cddbf3b 100644 (file)
@@ -71,10 +71,10 @@ BOOST_AUTO_TEST_CASE (upmixer_a_test)
        sf_close (Ls);
        sf_close (Rs);
 
-       check_file ("test/data/upmixer_a_test/L.wav", "build/test/upmixer_a_test/L.wav");
-       check_file ("test/data/upmixer_a_test/R.wav", "build/test/upmixer_a_test/R.wav");
-       check_file ("test/data/upmixer_a_test/C.wav", "build/test/upmixer_a_test/C.wav");
-       check_file ("test/data/upmixer_a_test/Lfe.wav", "build/test/upmixer_a_test/Lfe.wav");
-       check_file ("test/data/upmixer_a_test/Ls.wav", "build/test/upmixer_a_test/Ls.wav");
-       check_file ("test/data/upmixer_a_test/Rs.wav", "build/test/upmixer_a_test/Rs.wav");
+       check_audio_file ("test/data/upmixer_a_test/L.wav", "build/test/upmixer_a_test/L.wav");
+       check_audio_file ("test/data/upmixer_a_test/R.wav", "build/test/upmixer_a_test/R.wav");
+       check_audio_file ("test/data/upmixer_a_test/C.wav", "build/test/upmixer_a_test/C.wav");
+       check_audio_file ("test/data/upmixer_a_test/Lfe.wav", "build/test/upmixer_a_test/Lfe.wav");
+       check_audio_file ("test/data/upmixer_a_test/Ls.wav", "build/test/upmixer_a_test/Ls.wav");
+       check_audio_file ("test/data/upmixer_a_test/Rs.wav", "build/test/upmixer_a_test/Rs.wav");
 }