feat: hardware decoding

This commit is contained in:
kieran 2024-11-05 10:59:12 +00:00
parent cbaf4069c7
commit bc39a2ad99
No known key found for this signature in database
GPG Key ID: DE71CEB3925BE941
5 changed files with 125 additions and 99 deletions

BIN
cashu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

View File

@ -1,66 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
version="1.1"
width="135"
height="153"
shape-rendering="crispEdges"
id="svg29096"
sodipodi:docname="cashu.svg"
inkscape:version="1.1.2 (0a00cf5, 2022-02-04)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs29100" />
<sodipodi:namedview
id="namedview29098"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:pageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="1.9146341"
inkscape:cx="-5.4840764"
inkscape:cy="91.923567"
inkscape:window-width="1440"
inkscape:window-height="838"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg29096"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" />
<path
id="rect2"
d="m 18,0 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 V 8 7 6 5 4 3 2 1 0 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 z m 0,9 H 17 16 15 14 13 12 11 10 9 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 V 17 16 15 14 13 12 11 10 Z M 9,18 H 8 7 6 5 4 3 2 1 0 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 H 1 2 3 4 5 6 7 8 9 V 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 Z M 0,53 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 H 8 7 6 V 60 59 58 57 H 5 4 3 V 56 55 54 53 H 2 1 Z m 9,55 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 z m 9,18 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 z m 9,9 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 z m 9,9 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 z m 81,0 h 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 v 1 1 1 1 1 1 1 1 z"
style="fill:#b89563;fill-opacity:1" />
<path
id="rect38"
d="m 36,0 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 V 8 7 6 5 4 3 2 1 0 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 z m 45,9 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 V 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 h -1 -1 -1 -1 -1 -1 -1 -1 z m 0,27 h -1 -1 -1 -1 -1 -1 -1 -1 -1 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 V 44 43 42 41 40 39 38 37 Z M 63,64 v 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 z m 9,8 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 z m 9,18 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 z m 36,9 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 z m 9,9 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 z"
style="fill:#e2d2b3;fill-opacity:1" />
<path
id="rect1154"
d="m 18,9 v 1 1 1 1 1 1 1 1 1 H 17 16 15 14 13 12 11 10 9 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 h 1 1 1 1 1 1 1 1 1 V 17 16 15 14 13 12 11 10 9 H 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 Z M 9,61 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 v -1 -1 -1 z"
style="fill:#c5a77f;fill-opacity:1" />
<path
id="rect1190"
d="m 36,9 v 1 1 1 1 1 1 1 1 1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h 1 1 1 1 1 1 1 1 1 V 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 z m 9,40 v 1 1 1 1 1 1 h -1 -1 v 1 1 1 h -1 -1 -1 v 1 1 1 h -1 -1 -1 -1 v 1 1 1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 v -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 v -1 -1 -1 h -1 -1 -1 v -1 -1 -1 -1 h -1 -1 -1 -1 v -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 z"
style="fill:#dbbf98;fill-opacity:1" />
<path
id="rect7292"
d="m 0,45 v 1 1 1 1 1 1 1 1 h 1 1 1 v 1 1 1 1 h 1 1 1 v 1 1 1 1 h 1 1 1 1 v 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 v -1 -1 -1 h 1 1 1 1 v -1 -1 -1 h 1 1 1 v -1 -1 -1 h 1 1 v -1 -1 -1 -1 -1 -1 h 1 1 1 1 1 1 v 1 1 1 1 1 1 1 1 h 1 1 1 1 v 1 1 1 1 h 1 1 1 v 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 v -1 -1 -1 h 1 1 1 1 v -1 -1 -1 -1 h 1 1 1 1 v -1 -1 -1 -1 h 1 1 1 1 V 52 51 50 49 48 47 46 45 H 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 Z m 6,4 h 1 1 1 1 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 -1 h 1 1 1 1 v 1 1 1 1 h 1 1 1 1 v 1 1 1 1 h 1 1 1 1 v 1 1 1 1 h -1 -1 -1 -1 v -1 -1 -1 -1 h -1 -1 -1 -1 v 1 1 1 1 H 17 16 15 14 V 60 59 58 57 H 13 12 11 10 V 56 55 54 53 H 9 8 7 6 v -1 -1 -1 z m 8,8 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 -1 v 1 1 1 z m 44,-8 h 1 1 1 1 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 -1 h 1 1 1 1 v 1 1 1 1 h 1 1 1 1 v 1 1 1 1 h 1 1 1 1 v 1 1 1 1 h -1 -1 -1 -1 v -1 -1 -1 -1 h -1 -1 -1 -1 v 1 1 1 1 h -1 -1 -1 -1 v -1 -1 -1 -1 h -1 -1 -1 -1 v -1 -1 -1 -1 h -1 -1 -1 -1 v -1 -1 -1 z m 8,8 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 -1 v 1 1 1 z"
style="fill:#000000;fill-opacity:1" />
<path
id="rect8072"
d="m 6,49 v 1 1 1 1 h 1 1 1 1 V 52 51 50 49 H 9 8 7 Z m 4,4 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 z m 4,0 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 -1 v 1 1 1 z m 4,0 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 z m 4,4 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 z m -4,0 h -1 -1 -1 -1 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 z m 40,-8 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 z m 4,4 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 z m 4,0 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 -1 v 1 1 1 z m 4,0 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 z m 4,4 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 z m -4,0 h -1 -1 -1 -1 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 z"
style="fill:#ffffff;fill-opacity:1" />
<path
id="rect17144"
d="m 99,99 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 z"
style="fill:#f7f8f3;fill-opacity:1" />
</svg>

Before

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -1,6 +1,6 @@
use ffmpeg_rs_raw::{Decoder, Demuxer}; use ffmpeg_rs_raw::{Decoder, Demuxer, DemuxerInfo};
use ffmpeg_sys_the_third::AVHWDeviceType::{AV_HWDEVICE_TYPE_CUDA, AV_HWDEVICE_TYPE_VDPAU};
use ffmpeg_sys_the_third::{av_frame_free, av_packet_free}; use ffmpeg_sys_the_third::{av_frame_free, av_packet_free};
use std::collections::HashMap;
use std::env::args; use std::env::args;
use std::fs::File; use std::fs::File;
use std::io::{Cursor, Read}; use std::io::{Cursor, Read};
@ -20,20 +20,6 @@ fn main() {
let fd = read_as_file(path.clone()); let fd = read_as_file(path.clone());
scan_input(fd); scan_input(fd);
let mut opt = HashMap::new();
opt.insert("analyzeduration".to_string(), "999".to_string());
let svg = include_bytes!("./cashu.svg");
let mut dx = Demuxer::new_custom_io(svg.as_slice(), Some("cashu.svg".to_string()));
dx.set_opt(opt.clone()).unwrap();
unsafe {
let mut decoder = Decoder::new();
let info = dx.probe_input().expect("probe failed");
for chan in &info.channels {
decoder.setup_decoder(chan, None).expect("setup failed");
}
loop_decoder(dx, decoder);
}
} }
fn read_as_custom_io(path: PathBuf) -> Demuxer { fn read_as_custom_io(path: PathBuf) -> Demuxer {
@ -51,12 +37,20 @@ fn scan_input(mut demuxer: Demuxer) {
unsafe { unsafe {
let info = demuxer.probe_input().expect("demuxer failed"); let info = demuxer.probe_input().expect("demuxer failed");
println!("{}", info); println!("{}", info);
decode_input(demuxer); decode_input(demuxer, info);
} }
} }
unsafe fn decode_input(demuxer: Demuxer) { unsafe fn decode_input(demuxer: Demuxer, info: DemuxerInfo) {
let decoder = Decoder::new(); let mut decoder = Decoder::new();
decoder.enable_hw_decoder(AV_HWDEVICE_TYPE_VDPAU);
decoder.enable_hw_decoder(AV_HWDEVICE_TYPE_CUDA);
for ref stream in info.channels {
decoder
.setup_decoder(stream, None)
.expect("decoder setup failed");
}
println!("{}", decoder);
loop_decoder(demuxer, decoder); loop_decoder(demuxer, decoder);
} }

View File

@ -1,21 +1,25 @@
use crate::{options_to_dict, StreamInfoChannel}; use crate::{options_to_dict, return_ffmpeg_error, StreamInfoChannel};
use std::collections::HashMap; use std::collections::{HashMap, HashSet};
use std::ffi::CStr; use std::ffi::CStr;
use std::fmt::{Display, Formatter};
use std::ptr; use std::ptr;
use anyhow::Error; use anyhow::Error;
use ffmpeg_sys_the_third::AVPictureType::AV_PICTURE_TYPE_NONE; use ffmpeg_sys_the_third::AVPictureType::AV_PICTURE_TYPE_NONE;
use ffmpeg_sys_the_third::{ use ffmpeg_sys_the_third::{
av_buffer_alloc, av_frame_alloc, avcodec_alloc_context3, avcodec_find_decoder, av_buffer_alloc, av_buffer_ref, av_frame_alloc, av_frame_copy_props, av_frame_free,
avcodec_free_context, avcodec_get_name, avcodec_open2, avcodec_parameters_to_context, av_hwdevice_ctx_create, av_hwdevice_get_type_name, av_hwframe_transfer_data,
avcodec_receive_frame, avcodec_send_packet, AVCodec, AVCodecContext, AVFrame, AVMediaType, avcodec_alloc_context3, avcodec_find_decoder, avcodec_free_context, avcodec_get_hw_config,
AVPacket, AVStream, AVERROR, AVERROR_EOF, avcodec_get_name, avcodec_open2, avcodec_parameters_to_context, avcodec_receive_frame,
avcodec_send_packet, AVCodec, AVCodecContext, AVCodecHWConfig, AVFrame, AVHWDeviceType,
AVMediaType, AVPacket, AVStream, AVERROR, AVERROR_EOF, AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX,
}; };
use libc::memcpy; use libc::memcpy;
pub struct DecoderCodecContext { pub struct DecoderCodecContext {
pub context: *mut AVCodecContext, pub context: *mut AVCodecContext,
pub codec: *const AVCodec, pub codec: *const AVCodec,
pub hw_config: *const AVCodecHWConfig,
} }
impl DecoderCodecContext { impl DecoderCodecContext {
@ -39,17 +43,61 @@ impl Drop for DecoderCodecContext {
} }
} }
impl Display for DecoderCodecContext {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
unsafe {
let codec_name = CStr::from_ptr(avcodec_get_name((*self.codec).id))
.to_str()
.unwrap();
write!(
f,
"DecoderCodecContext: codec={}, hw={}",
codec_name,
if self.hw_config.is_null() {
"no"
} else {
CStr::from_ptr(av_hwdevice_get_type_name((*self.hw_config).device_type))
.to_str()
.unwrap()
}
)
}
}
}
unsafe impl Send for DecoderCodecContext {} unsafe impl Send for DecoderCodecContext {}
unsafe impl Sync for DecoderCodecContext {} unsafe impl Sync for DecoderCodecContext {}
pub struct Decoder { pub struct Decoder {
codecs: HashMap<i32, DecoderCodecContext>, codecs: HashMap<i32, DecoderCodecContext>,
/// List of [AVHWDeviceType] which are enabled
hw_decoder_types: Option<HashSet<AVHWDeviceType>>,
} }
impl Display for Decoder {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
for (idx, codec) in &self.codecs {
writeln!(f, "{}: {}", idx, codec)?;
}
Ok(())
}
}
impl Decoder { impl Decoder {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
codecs: HashMap::new(), codecs: HashMap::new(),
hw_decoder_types: None,
}
}
/// Enable hardware decoding with [hw_type]
pub fn enable_hw_decoder(&mut self, hw_type: AVHWDeviceType) {
if let Some(ref mut t) = self.hw_decoder_types {
t.insert(hw_type);
} else {
let mut hwt = HashSet::new();
hwt.insert(hw_type);
self.hw_decoder_types = Some(hwt);
} }
} }
@ -91,8 +139,38 @@ impl Decoder {
if context.is_null() { if context.is_null() {
anyhow::bail!("Failed to alloc context") anyhow::bail!("Failed to alloc context")
} }
if avcodec_parameters_to_context(context, (*stream).codecpar) != 0 {
anyhow::bail!("Failed to copy codec parameters to context") let mut ret = avcodec_parameters_to_context(context, (*stream).codecpar);
return_ffmpeg_error!(ret, "Failed to copy codec parameters to context");
// try use HW decoder
let mut hw_config = ptr::null();
if let Some(ref hw_types) = self.hw_decoder_types {
let mut hw_buf_ref = ptr::null_mut();
let mut i = 0;
loop {
hw_config = avcodec_get_hw_config(codec, i);
i += 1;
if hw_config.is_null() {
break;
}
if !hw_types.contains(&(*hw_config).device_type) {
continue;
}
let hw_flag = AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX as libc::c_int;
if (*hw_config).methods & hw_flag == hw_flag {
ret = av_hwdevice_ctx_create(
&mut hw_buf_ref,
(*hw_config).device_type,
ptr::null_mut(),
ptr::null_mut(),
0,
);
return_ffmpeg_error!(ret, "Failed to create HW ctx");
(*context).hw_device_ctx = av_buffer_ref(hw_buf_ref);
break;
}
}
} }
let mut dict = if let Some(options) = options { let mut dict = if let Some(options) = options {
options_to_dict(options)? options_to_dict(options)?
@ -100,10 +178,14 @@ impl Decoder {
ptr::null_mut() ptr::null_mut()
}; };
if avcodec_open2(context, codec, &mut dict) < 0 { ret = avcodec_open2(context, codec, &mut dict);
anyhow::bail!("Failed to open codec") return_ffmpeg_error!(ret, "Failed to open codec");
}
Ok(e.insert(DecoderCodecContext { context, codec })) Ok(e.insert(DecoderCodecContext {
context,
codec,
hw_config,
}))
} else { } else {
anyhow::bail!("Decoder already setup"); anyhow::bail!("Decoder already setup");
} }
@ -146,7 +228,7 @@ impl Decoder {
let mut pkgs = Vec::new(); let mut pkgs = Vec::new();
while ret >= 0 { while ret >= 0 {
let frame = av_frame_alloc(); let mut frame = av_frame_alloc();
ret = avcodec_receive_frame(ctx.context, frame); ret = avcodec_receive_frame(ctx.context, frame);
if ret < 0 { if ret < 0 {
if ret == AVERROR_EOF || ret == AVERROR(libc::EAGAIN) { if ret == AVERROR_EOF || ret == AVERROR(libc::EAGAIN) {
@ -155,6 +237,17 @@ impl Decoder {
return Err(Error::msg(format!("Failed to decode {}", ret))); return Err(Error::msg(format!("Failed to decode {}", ret)));
} }
// copy frame from GPU
if !ctx.hw_config.is_null() {
let sw_frame = av_frame_alloc();
ret = av_hwframe_transfer_data(sw_frame, frame, 0);
return_ffmpeg_error!(ret, "Failed to transfer data from GPU");
av_frame_copy_props(sw_frame, frame);
av_frame_free(&mut frame);
frame = sw_frame;
}
(*frame).pict_type = AV_PICTURE_TYPE_NONE; // encoder prints warnings (*frame).pict_type = AV_PICTURE_TYPE_NONE; // encoder prints warnings
pkgs.push((frame, stream)); pkgs.push((frame, stream));
} }

View File

@ -17,7 +17,12 @@ mod stream_info;
macro_rules! return_ffmpeg_error { macro_rules! return_ffmpeg_error {
($x:expr) => { ($x:expr) => {
if $x < 0 { if $x < 0 {
return Err(Error::msg(get_ffmpeg_error_msg($x))); anyhow::bail!(crate::get_ffmpeg_error_msg($x))
}
};
($x:expr,$msg:expr) => {
if $x < 0 {
anyhow::bail!(format!("{}: {}", $msg, crate::get_ffmpeg_error_msg($x)))
} }
}; };
} }