mirror of
https://github.com/tuxbox-neutrino/libstb-hal.git
synced 2025-08-27 23:43:00 +02:00
Compare commits
560 Commits
v1.0.1-mpx
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
3ff02b06f2 | ||
|
da0d4290a3 | ||
|
9bd798def2 | ||
|
3869c32e82 | ||
|
ed8e3743d5 | ||
|
bc9eca8588 | ||
|
1e47a62926 | ||
|
4fecdd558a | ||
|
2e8aa93895 | ||
|
8d6b3f71c0 | ||
|
2673ba0940 | ||
|
78b3403303 | ||
|
dd01a95ddb | ||
|
3f9525e42e | ||
|
a47c399a19 | ||
|
056db018ab | ||
|
793ae7a605 | ||
|
29a96a35bd | ||
|
c723af9313 | ||
|
328c93fb0d | ||
|
6100244f5e | ||
|
41212e3c1a | ||
|
d1569e6114 | ||
|
497e31c3fd | ||
|
ef8868cbbd | ||
|
757cce78af | ||
|
9823295de1 | ||
|
c376875c39 | ||
|
0f857a1836 | ||
|
055803dbac | ||
|
809c9047ea | ||
|
c3f4432496 | ||
|
8709d3ad85 | ||
|
85819d69ee | ||
|
e8ad377b4f | ||
|
ca355eecd1 | ||
|
8a1bf4f41e | ||
|
89bd4b00c4 | ||
|
e68a82cd50 | ||
|
82a6c40bc4 | ||
|
4aed33ff9c | ||
|
d812ac52c5 | ||
|
dac47fd266 | ||
|
9715204498 | ||
|
9348cef2a6 | ||
|
0226277758 | ||
|
aa683951fc | ||
|
a5aeb217c5 | ||
|
575107b5e1 | ||
|
42fb4fe182 | ||
|
43a28b317c | ||
|
2525823506 | ||
|
95d07cdfc9 | ||
|
acac2e4f5a | ||
|
fd2f0f1fd4 | ||
|
db3ec7352e | ||
|
42267080f9 | ||
|
be9ebb472a | ||
|
635ce08a89 | ||
|
238f2636d6 | ||
|
23c64535be | ||
|
66cc42cb19 | ||
|
d7403705d9 | ||
|
444ccdad5d | ||
|
042057b565 | ||
|
18db6acbc2 | ||
|
d22660a4a1 | ||
|
7613411406 | ||
|
e7f5c17256 | ||
|
d863ebc181 | ||
|
a0037c51f0 | ||
|
49a9834ac5 | ||
|
ef2df97bde | ||
|
8f9a53e40c | ||
|
f163af47d2 | ||
|
00b856173d | ||
|
0a53f3467e | ||
|
9663f535cd | ||
|
3ba5512abc | ||
|
0ec87d5a95 | ||
|
908df1e86e | ||
|
ab076a85f8 | ||
|
0dc812e80f | ||
|
3b6333cc59 | ||
|
1df6cfc16d | ||
|
efb860f20d | ||
|
f5e9cceb64 | ||
|
5007debb3a | ||
|
5904b79e38 | ||
|
5830d4adc3 | ||
|
d09ff5bb29 | ||
|
2bb5b8e8a9 | ||
|
e878f5f751 | ||
|
860d6bdbe7 | ||
|
8e36402902 | ||
|
d1674e2327 | ||
|
62283244b4 | ||
|
4e02a62e48 | ||
|
8dd2a4091b | ||
|
2f24c2bcba | ||
|
c2d2be320f | ||
|
64f4702691 | ||
|
78f49580e0 | ||
|
100830e805 | ||
|
d4365037f6 | ||
|
dc5067e5d2 | ||
|
270e282d1f | ||
|
535b12d63a | ||
|
fc799dc6bf | ||
|
56e6d04719 | ||
|
746fe7bf87 | ||
|
757f7de70c | ||
|
67a6810022 | ||
|
79c203676f | ||
|
ad0b3175c1 | ||
|
099ccfe6bb | ||
|
d4a8c87ec3 | ||
|
760b46a373 | ||
|
8449c055e0 | ||
|
8dd6d00ef1 | ||
|
286955f888 | ||
|
e7381352d4 | ||
|
4e2ff2ce6d | ||
|
23d912c034 | ||
|
fe095b5a2c | ||
|
45576494e5 | ||
|
33726e48d0 | ||
|
96ae9b1d40 | ||
|
263f211cbe | ||
|
b0a734c607 | ||
|
3c2f594147 | ||
|
e7d95eb3d3 | ||
|
5ffbeafa49 | ||
|
65890b2e14 | ||
|
de993ea5b1 | ||
|
64a524ab5c | ||
|
5ab9e2deda | ||
|
ef58a765bb | ||
|
0fe0e5ce6d | ||
|
f9931b3b1b | ||
|
d195c29769 | ||
|
8128fe3289 | ||
|
32e8bd8252 | ||
|
35ff3bb69c | ||
|
1b4b110c26 | ||
|
fc658e27b0 | ||
|
40557ac647 | ||
|
dd7db83276 | ||
|
a6b0acda6d | ||
|
bdc242d29b | ||
|
6906e9f929 | ||
|
25811b99be | ||
|
c5426c8596 | ||
|
ae1bcb466b | ||
|
9d6397ac35 | ||
|
12845ab18c | ||
|
a3eb634030 | ||
|
06449fcbfd | ||
|
b4ec2c34b9 | ||
|
62d526f799 | ||
|
046da3c411 | ||
|
578dc39595 | ||
|
d53589353e | ||
|
4b648be6fa | ||
|
a8a2d917fb | ||
|
bbe2472f2d | ||
|
4da9260b54 | ||
|
1a808def2f | ||
|
6c594a7cda | ||
|
be26d8d46b | ||
|
478a83efad | ||
|
3f30607fbd | ||
|
5f340ec4a8 | ||
|
33d7a29134 | ||
|
6c340eb752 | ||
|
eafc00a861 | ||
|
2fc7cac404 | ||
|
7bb603a8af | ||
|
bfbe8ed51a | ||
|
cb3db6256c | ||
|
fcd1dc8399 | ||
|
5448fb35bf | ||
|
514398ad2a | ||
|
12c9643978 | ||
|
ca5effe1bc | ||
|
1112111e2d | ||
|
2067355059 | ||
|
6e37a5bcc1 | ||
|
f945fe34aa | ||
|
2777eb4788 | ||
|
85fcd7379d | ||
|
7bf5a5f290 | ||
|
d97d2a84d8 | ||
|
25948637ab | ||
|
06c260681f | ||
|
23bad752df | ||
|
9f9d1b64ce | ||
|
896a08e145 | ||
|
1a04102c23 | ||
|
2d0ca622f8 | ||
|
97f1aff64f | ||
|
15964474f3 | ||
|
4ccc66e6cc | ||
|
7a80a1f3e1 | ||
|
500e8e8eac | ||
|
ff13f75588 | ||
|
85bcfb4a17 | ||
|
5e2d44cc5d | ||
|
01144c864b | ||
|
a4baa13ed1 | ||
|
46cd3a2703 | ||
|
9fbb682eda | ||
|
ff24109403 | ||
|
794ced8b3d | ||
|
4f32aa4ea0 | ||
|
a0cd63ce87 | ||
|
9eb23c78f4 | ||
|
173880cb31 | ||
|
6fcfafc604 | ||
|
7767f23a0f | ||
|
243bbc3f5b | ||
|
dc9f75646c | ||
|
2c4979f6b5 | ||
|
77dce975a3 | ||
|
6572e5538c | ||
|
9393207c4c | ||
|
cd7c6086d2 | ||
|
f60e040d03 | ||
|
0e55c3f01b | ||
|
76a42bda44 | ||
|
d71950c4a2 | ||
|
bbb50fc606 | ||
|
3ff4fd923b | ||
|
043bde93c1 | ||
|
4e30d5ded6 | ||
|
39103f03d2 | ||
|
e3f53de4ae | ||
|
8da0fecb53 | ||
|
5fb12c8048 | ||
|
dd242bda4a | ||
|
0df645f5c7 | ||
|
1073220ff4 | ||
|
ff099b9356 | ||
|
80daefef90 | ||
|
6546462c4e | ||
|
51a920d26f | ||
|
31482f5286 | ||
|
6c84031759 | ||
|
32ec25ec4d | ||
|
62df38174e | ||
|
129206c5db | ||
|
c229a6019d | ||
|
051507623e | ||
|
455749f311 | ||
|
db48911f37 | ||
|
7142d4de2d | ||
|
9b1c3353de | ||
|
a2631567fe | ||
|
af5f30ae92 | ||
|
ed9299c780 | ||
|
be656d7cee | ||
|
beab047387 | ||
|
f082c8dcd0 | ||
|
4b8568d79a | ||
|
9b6880102e | ||
|
d76cf27929 | ||
|
4db66e226f | ||
|
2b1bb1f9ca | ||
|
76bdd325c1 | ||
|
b08a39c4c1 | ||
|
b6ba5ea298 | ||
|
8ce41532e7 | ||
|
e4dba8b30e | ||
|
f403e3b3e2 | ||
|
1590198998 | ||
|
2a720c6106 | ||
|
11191c62dd | ||
|
ad4a850426 | ||
|
4b5391ad4d | ||
|
76f873e191 | ||
|
6de629b4af | ||
|
7e39d85631 | ||
|
615f8d9708 | ||
|
6094f51e2d | ||
|
6fc19089c4 | ||
|
d61e9f4f2b | ||
|
5137575c11 | ||
|
db22215f9e | ||
|
a2a4651c46 | ||
|
068769c110 | ||
|
6cff3e3377 | ||
|
6b3062d3ec | ||
|
7738a24be1 | ||
|
fc06947ba7 | ||
|
e01a3d5312 | ||
|
ff63d40176 | ||
|
545a3208d4 | ||
|
7645863bfb | ||
|
f20fc1f81d | ||
|
60dd40a5ad | ||
|
07709ce1cd | ||
|
a51f79352b | ||
|
1a3ac317c2 | ||
|
37c573041a | ||
|
0fa7469487 | ||
|
95d724ced0 | ||
|
aa5f59c5e6 | ||
|
998607edfc | ||
|
6931fcd838 | ||
|
027660da47 | ||
|
3bc8b09638 | ||
|
5b9837b3a9 | ||
|
d9e8115cae | ||
|
75da827371 | ||
|
8e0c61ead0 | ||
|
9f27e84225 | ||
|
e7f0879153 | ||
|
185acae677 | ||
|
d301826998 | ||
|
864bd7d422 | ||
|
c550a79d7c | ||
|
5a255e9c4a | ||
|
019b2a5dca | ||
|
6395850a91 | ||
|
0c295bcfc0 | ||
|
10488303fc | ||
|
c212dae7b1 | ||
|
8ba924c471 | ||
|
e30ad7d035 | ||
|
c7ddfbf8be | ||
|
8f06d2558e | ||
|
e3f1d23acc | ||
|
1c296f02bf | ||
|
40b3c4459d | ||
|
396077ccb2 | ||
|
a49a33c983 | ||
|
852d4e69ea | ||
|
b59343cf69 | ||
|
80a86fa72f | ||
|
9d51907c5d | ||
|
51f112dabb | ||
|
f61395efdf | ||
|
b9c8d61b3a | ||
|
8affebdef6 | ||
|
12f6a51f49 | ||
|
22d4f40fb9 | ||
|
dfa1a3e32b | ||
|
dc85e1c284 | ||
|
5e38511807 | ||
|
0a386a264d | ||
|
8e64b9c7b1 | ||
|
96c0c7c3a5 | ||
|
c3bbda3e9c | ||
|
dd618fc883 | ||
|
fffbbacd74 | ||
|
267788f14e | ||
|
f5091bcd35 | ||
|
546eb23e0e | ||
|
9556f935bf | ||
|
4e0f7f9a91 | ||
|
9ce0d977b1 | ||
|
d5b57e281d | ||
|
9edd4277c3 | ||
|
2368ec790f | ||
|
fec74fdcc7 | ||
|
6106d014e9 | ||
|
8d3fba60a3 | ||
|
a2e60ad48a | ||
|
ed7c956e7f | ||
|
4569654545 | ||
|
9b2d5761a9 | ||
|
b976862530 | ||
|
aae498250b | ||
|
fb8c2f33d1 | ||
|
824b328ec1 | ||
|
a01b70f226 | ||
|
dc95df1150 | ||
|
78307db056 | ||
|
e99a8fd76a | ||
|
0bee4efa6e | ||
|
fd72343f69 | ||
|
525cd01c2c | ||
|
1c1d85e582 | ||
|
4cf92f8102 | ||
|
f0446eeeb2 | ||
|
1cc9619c49 | ||
|
e94b7daf85 | ||
|
d431e60284 | ||
|
8563837c8b | ||
|
4c74b822ca | ||
|
8f7e6e981f | ||
|
2dd8dd1d20 | ||
|
33b204df8a | ||
|
1b5a6076d9 | ||
|
e953af61c2 | ||
|
32d83d32c5 | ||
|
ecab8ca7c0 | ||
|
95a20e181b | ||
|
fc0300416b | ||
|
e746daaf5a | ||
|
d94e47c757 | ||
|
1311c58e35 | ||
|
1166d49486 | ||
|
69527185a9 | ||
|
5a56339925 | ||
|
77f26b69a6 | ||
|
60cc22c58a | ||
|
7434bcacae | ||
|
0bfaccd2ee | ||
|
50b1d46af1 | ||
|
9563559afb | ||
|
cc973092ed | ||
|
04ae3878cc | ||
|
ab3a145c63 | ||
|
d0a4a496ec | ||
|
91775a6029 | ||
|
ffc375869b | ||
|
de0950ffa9 | ||
|
c697d633aa | ||
|
03754e8bc5 | ||
|
0b1c4bcb9c | ||
|
a78e983d5f | ||
|
e0f5184900 | ||
|
824c602fb6 | ||
|
0e49bfdb00 | ||
|
2f7cb6401f | ||
|
2784941b7e | ||
|
b424d34536 | ||
|
4c13442e05 | ||
|
d71ae5b4f9 | ||
|
d736e87d4e | ||
|
48df8f882a | ||
|
fa1eadcc56 | ||
|
06035e8ea1 | ||
|
e9b6f6c88b | ||
|
510b655710 | ||
|
ec58e86ae4 | ||
|
19b0ff20e1 | ||
|
0f9bc4f95c | ||
|
7c942c3745 | ||
|
2f7d1b15e0 | ||
|
7d34affd1d | ||
|
370efa3852 | ||
|
d1a2ceaa67 | ||
|
f5f0eb0f26 | ||
|
2c6b721987 | ||
|
cb34d91c57 | ||
|
be2ae1cbd8 | ||
|
baff0efeb4 | ||
|
78ae8e8a62 | ||
|
45f4924ee4 | ||
|
9dd8efc76d | ||
|
9987291e36 | ||
|
3738572731 | ||
|
e11af5361b | ||
|
81aeb8f182 | ||
|
6147c3ef5e | ||
|
ef7ba87754 | ||
|
1215ab73a3 | ||
|
373976ca3d | ||
|
c004f52cca | ||
|
4433f4ad43 | ||
|
34cb8f4030 | ||
|
b6d6afc07f | ||
|
1fa3303cf7 | ||
|
6dba65cd53 | ||
|
0572e368df | ||
|
bed6d04851 | ||
|
fbb8780418 | ||
|
5734870578 | ||
|
23da35350a | ||
|
32f4d0b60b | ||
|
65f9fc02d4 | ||
|
2f34f9fd12 | ||
|
1523ad974e | ||
|
ccc7f61813 | ||
|
ac29852565 | ||
|
d461967885 | ||
|
23356fa5d8 | ||
|
a4f6f6e6b4 | ||
|
f8787493bf | ||
|
6bb00d7bc7 | ||
|
a1c809cd47 | ||
|
025e2082e9 | ||
|
44f19e563a | ||
|
876c7e95e1 | ||
|
ea4054f258 | ||
|
43f6a4cdb6 | ||
|
13a488c1e3 | ||
|
28a5f96c8b | ||
|
ec73a2bcd4 | ||
|
29d549ff3f | ||
|
233c330e4c | ||
|
42018c2f9c | ||
|
83756d1f9b | ||
|
59d83d0bd4 | ||
|
fcd2c1b246 | ||
|
4037122259 | ||
|
03c9c65bea | ||
|
b2eb2038d7 | ||
|
d2ee743530 | ||
|
17a2a6553a | ||
|
65e69b07fb | ||
|
997af12a20 | ||
|
429a9df2a5 | ||
|
4b5228cfb0 | ||
|
4f56cae01d | ||
|
6e25a6f00f | ||
|
0d54652815 | ||
|
076715fd68 | ||
|
b035d8ef59 | ||
|
7b8f5aede9 | ||
|
093b3fd51a | ||
|
4a7c1fb975 | ||
|
f3f3a49b87 | ||
|
76992e2f0c | ||
|
997d162cd3 | ||
|
9e74193f34 | ||
|
1a499b7054 | ||
|
bd87abd06b | ||
|
0cdfdc60ae | ||
|
f546bd5218 | ||
|
bf87a25c4d | ||
|
ee0e87dc05 | ||
|
78c53d1baa | ||
|
ba9ba931ed | ||
|
4417f2549d | ||
|
8d5e5a7cd2 | ||
|
d4c0cfe133 | ||
|
17f3713093 | ||
|
9bb9a8d5fd | ||
|
a367d1f5db | ||
|
3641f0ef6f | ||
|
3f2a7a8809 | ||
|
a8bb8bb705 | ||
|
0243da9367 | ||
|
83fe4c7174 | ||
|
0d9281063b | ||
|
4a7345e6e6 | ||
|
41daed4748 | ||
|
e544fab4f2 | ||
|
986b39c04e | ||
|
65c64c77b4 | ||
|
8b33e32cf8 | ||
|
bf7e63689d | ||
|
ed10c47327 | ||
|
c048f57223 | ||
|
df067953b4 | ||
|
07a0da1b99 | ||
|
4d1b35e4ac | ||
|
2627072d1d | ||
|
1bcc899430 | ||
|
60aeebb68e | ||
|
94d8b8b57d | ||
|
6f8ce7c8ca | ||
|
91582dc5af | ||
|
b83945b4ce | ||
|
ba958c809d | ||
|
2693d2a21e | ||
|
1005c3f53e |
10
.gitignore
vendored
10
.gitignore
vendored
@@ -1,21 +1,19 @@
|
||||
/aclocal.m4
|
||||
/autom4te.cache/
|
||||
Makefile.in
|
||||
/compile
|
||||
/config.guess
|
||||
/config.h.in
|
||||
/config.sub
|
||||
*/*-config.h
|
||||
*/*-config.h.in
|
||||
/configure
|
||||
/compile
|
||||
*.directory
|
||||
/depcomp
|
||||
/install-sh
|
||||
/ltmain.sh
|
||||
/m4/
|
||||
/missing
|
||||
*.*~
|
||||
*.a
|
||||
*.la
|
||||
*.lai
|
||||
*.lo
|
||||
*.o
|
||||
*.Plo
|
||||
*.Po
|
||||
|
46
Makefile.am
46
Makefile.am
@@ -2,15 +2,13 @@ ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
lib_LTLIBRARIES = libstb-hal.la
|
||||
libstb_hal_la_SOURCES =
|
||||
SUBDIRS = common tools libthread
|
||||
bin_PROGRAMS = libstb-hal-test
|
||||
SUBDIRS = common tools
|
||||
#bin_PROGRAMS = libstb-hal-test
|
||||
|
||||
libstb_hal_la_LIBADD = \
|
||||
common/libcommon.la \
|
||||
libthread/libthread.la
|
||||
common/libcommon.la
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/include
|
||||
libstb_hal_la_LDFLAGS = -version-info 1:0:1
|
||||
|
||||
libstb_hal_test_SOURCES = libtest.cpp
|
||||
libstb_hal_test_LDADD = libstb-hal.la
|
||||
@@ -38,24 +36,28 @@ libstb_hal_la_LIBADD += \
|
||||
endif
|
||||
endif
|
||||
if BOXTYPE_SPARK
|
||||
libstb_hal_test_LDADD += -lasound
|
||||
SUBDIRS += libspark libeplayer3
|
||||
libstb_hal_la_LIBADD += \
|
||||
libspark/libspark.la \
|
||||
libeplayer3/libeplayer3.la
|
||||
endif
|
||||
if BOXTYPE_DUCKBOX
|
||||
libstb_hal_test_LDADD += -lasound
|
||||
SUBDIRS += libduckbox libeplayer3 libdvbci
|
||||
libstb_hal_la_LIBADD += \
|
||||
libduckbox/libduckbox.la \
|
||||
libeplayer3/libeplayer3.la \
|
||||
libdvbci/libdvbci.la
|
||||
endif
|
||||
if BOXTYPE_ARMBOX
|
||||
libstb_hal_test_LDADD += -lasound
|
||||
SUBDIRS += libarmbox libdvbci
|
||||
libstb_hal_la_LIBADD += \
|
||||
libarmbox/libarmbox.la \
|
||||
libdvbci/libdvbci.la
|
||||
endif
|
||||
|
||||
pkginclude_HEADERS = \
|
||||
include/audio_hal.h \
|
||||
include/ca_cs.h \
|
||||
include/ca.h \
|
||||
include/cs_api.h \
|
||||
include/cs_types.h \
|
||||
include/dmx_cs.h \
|
||||
include/dmx_hal.h \
|
||||
include/glfb.h \
|
||||
include/hardware_caps.h \
|
||||
include/init_cs.h \
|
||||
include/init_td.h \
|
||||
include/mmi.h \
|
||||
include/playback.h \
|
||||
include/playback_hal.h \
|
||||
include/pwrmngr.h \
|
||||
include/record_hal.h \
|
||||
include/version_hal.h \
|
||||
include/video_cs.h
|
||||
|
240
acinclude.m4
240
acinclude.m4
@@ -84,6 +84,7 @@ AC_ARG_WITH($1,[ $6$7 [[PREFIX$4$5]]],[
|
||||
TARGET_$2=$_$2
|
||||
])
|
||||
|
||||
dnl automake <= 1.6 don't support this
|
||||
dnl AC_SUBST($2)
|
||||
AC_DEFINE_UNQUOTED($2,"$_$2",$7)
|
||||
AC_SUBST(TARGET_$2)
|
||||
@@ -104,25 +105,28 @@ if test "$TARGET" = "cdk"; then
|
||||
fi
|
||||
|
||||
TUXBOX_APPS_DIRECTORY_ONE(configdir,CONFIGDIR,localstatedir,/var,/tuxbox/config,
|
||||
[--with-configdir=PATH ],[where to find the config files])
|
||||
[--with-configdir=PATH ],[where to find the config files])
|
||||
|
||||
TUXBOX_APPS_DIRECTORY_ONE(datadir,DATADIR,datadir,/share,/tuxbox,
|
||||
[--with-datadir=PATH ],[where to find data])
|
||||
[--with-datadir=PATH ],[where to find data])
|
||||
|
||||
TUXBOX_APPS_DIRECTORY_ONE(fontdir,FONTDIR,datadir,/share,/fonts,
|
||||
[--with-fontdir=PATH ],[where to find the fonts])
|
||||
[--with-fontdir=PATH ],[where to find the fonts])
|
||||
|
||||
TUXBOX_APPS_DIRECTORY_ONE(gamesdir,GAMESDIR,localstatedir,/var,/tuxbox/games,
|
||||
[--with-gamesdir=PATH ],[where games data is stored])
|
||||
[--with-gamesdir=PATH ],[where games data is stored])
|
||||
|
||||
TUXBOX_APPS_DIRECTORY_ONE(libdir,LIBDIR,libdir,/lib,/tuxbox,
|
||||
[--with-libdir=PATH ],[where to find the internal libs])
|
||||
[--with-libdir=PATH ],[where to find the internal libs])
|
||||
|
||||
TUXBOX_APPS_DIRECTORY_ONE(plugindir,PLUGINDIR,libdir,/lib,/tuxbox/plugins,
|
||||
[--with-plugindir=PATH ],[where to find the plugins])
|
||||
[--with-plugindir=PATH ],[where to find the plugins])
|
||||
|
||||
TUXBOX_APPS_DIRECTORY_ONE(ucodedir,UCODEDIR,localstatedir,/var,/tuxbox/ucodes,
|
||||
[--with-ucodedir=PATH ],[where to find the ucodes])
|
||||
|
||||
TUXBOX_APPS_DIRECTORY_ONE(themesdir,THEMESDIR,datadir,/share,/tuxbox/neutrino/themes,
|
||||
[--with-themesdir=PATH ],[where to find the themes (don't change)])
|
||||
[--with-themesdir=PATH ],[where to find the themes (don't change)])
|
||||
])
|
||||
|
||||
dnl automake <= 1.6 needs this specifications
|
||||
@@ -132,95 +136,38 @@ AC_SUBST(FONTDIR)
|
||||
AC_SUBST(GAMESDIR)
|
||||
AC_SUBST(LIBDIR)
|
||||
AC_SUBST(PLUGINDIR)
|
||||
AC_SUBST(UCODEDIR)
|
||||
AC_SUBST(THEMESDIR)
|
||||
dnl end workaround
|
||||
|
||||
AC_DEFUN([TUXBOX_BOXTYPE],[
|
||||
AC_ARG_WITH(boxtype,
|
||||
[ --with-boxtype valid values: tripledragon,spark,azbox,generic,duckbox,spark7162,armbox],
|
||||
[ --with-boxtype valid values: dbox2,tripledragon,dreambox,ipbox,coolstream,spark,azbox,generic],
|
||||
[case "${withval}" in
|
||||
tripledragon|azbox|generic)
|
||||
dbox2|dreambox|ipbox|tripledragon|coolstream|spark|azbox|generic)
|
||||
BOXTYPE="$withval"
|
||||
;;
|
||||
spark|spark7162)
|
||||
BOXTYPE="spark"
|
||||
BOXMODEL="$withval"
|
||||
;;
|
||||
dm*)
|
||||
BOXTYPE="dreambox"
|
||||
BOXMODEL="$withval"
|
||||
;;
|
||||
ufs*)
|
||||
BOXTYPE="duckbox"
|
||||
BOXMODEL="$withval"
|
||||
;;
|
||||
atevio*)
|
||||
BOXTYPE="duckbox"
|
||||
BOXMODEL="$withval"
|
||||
;;
|
||||
fortis*)
|
||||
BOXTYPE="duckbox"
|
||||
BOXMODEL="$withval"
|
||||
;;
|
||||
octagon*)
|
||||
BOXTYPE="duckbox"
|
||||
BOXMODEL="$withval"
|
||||
;;
|
||||
hs7*)
|
||||
BOXTYPE="duckbox"
|
||||
BOXMODEL="$withval"
|
||||
;;
|
||||
dp*)
|
||||
BOXTYPE="duckbox"
|
||||
BOXMODEL="$withval"
|
||||
;;
|
||||
cuberevo*)
|
||||
BOXTYPE="duckbox"
|
||||
BOXMODEL="$withval"
|
||||
;;
|
||||
ipbox*)
|
||||
BOXTYPE="duckbox"
|
||||
BOXMODEL="$withval"
|
||||
;;
|
||||
arivalink200)
|
||||
BOXTYPE="duckbox"
|
||||
BOXMODEL="$withval"
|
||||
;;
|
||||
tf*)
|
||||
BOXTYPE="duckbox"
|
||||
BOXMODEL="$withval"
|
||||
;;
|
||||
hl101)
|
||||
BOXTYPE="duckbox"
|
||||
BOXMODEL="$withval"
|
||||
;;
|
||||
hd51)
|
||||
BOXTYPE="armbox"
|
||||
BOXMODEL="$withval"
|
||||
;;
|
||||
vusolo4k)
|
||||
BOXTYPE="armbox"
|
||||
BOXMODEL="$withval"
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR([bad value $withval for --with-boxtype]) ;;
|
||||
esac], [BOXTYPE="generic"])
|
||||
|
||||
AC_ARG_WITH(boxmodel,
|
||||
[ --with-boxmodel valid for generic: raspi
|
||||
valid for duckbox: ufs910, ufs912, ufs913, ufs922, atevio7500, fortis_hdbox, octagon1008, hs7110, hs7810a, hs7119, hs7819, dp7000, cuberevo, cuberevo_mini, cuberevo_mini2, cuberevo_250hd, cuberevo_2000hd, cuberevo_3000hd, ipbox9900, ipbox99, ipbox55, arivalink200, tf7700, hl101
|
||||
valid for spark: spark, spark7162
|
||||
valid for armbox: hd51, vusolo4k],
|
||||
[ --with-boxmodel valid for dreambox: dm500, dm500plus, dm600pvr, dm56x0, dm7000, dm7020, dm7025
|
||||
valid for ipbox: ip200, ip250, ip350, ip400],
|
||||
[case "${withval}" in
|
||||
ufs910|ufs912|ufs913|ufs922|atevio7500|fortis_hdbox|octagon1008|hs7110|hs7810a|hs7119|hs7819|dp7000|cuberevo|cuberevo_mini|cuberevo_mini2|cuberevo_250hd|cuberevo_2000hd|cuberevo_3000hd|ipbox9900|ipbox99|ipbox55|arivalink200|tf7700|hl101)
|
||||
if test "$BOXTYPE" = "duckbox"; then
|
||||
dm500|dm500plus|dm600pvr|dm56x0|dm7000|dm7020|dm7025)
|
||||
if test "$BOXTYPE" = "dreambox"; then
|
||||
BOXMODEL="$withval"
|
||||
else
|
||||
AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE])
|
||||
fi
|
||||
;;
|
||||
spark|spark7162)
|
||||
if test "$BOXTYPE" = "spark"; then
|
||||
ip200|ip250|ip350|ip400)
|
||||
if test "$BOXTYPE" = "ipbox"; then
|
||||
BOXMODEL="$withval"
|
||||
else
|
||||
AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE])
|
||||
@@ -233,141 +180,70 @@ AC_ARG_WITH(boxmodel,
|
||||
AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE])
|
||||
fi
|
||||
;;
|
||||
hd51)
|
||||
if test "$BOXTYPE" = "armbox"; then
|
||||
BOXMODEL="$withval"
|
||||
else
|
||||
AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE])
|
||||
fi
|
||||
;;
|
||||
vusolo4k)
|
||||
if test "$BOXTYPE" = "armbox"; then
|
||||
BOXMODEL="$withval"
|
||||
else
|
||||
AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE])
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR([unsupported value $withval for --with-boxmodel])
|
||||
;;
|
||||
esac])
|
||||
esac],
|
||||
[if test "$BOXTYPE" = "dreambox" -o "$BOXTYPE" = "ipbox" && test -z "$BOXMODEL"; then
|
||||
AC_MSG_ERROR([Dreambox/IPBox needs --with-boxmodel])
|
||||
fi])
|
||||
|
||||
AC_SUBST(BOXTYPE)
|
||||
AC_SUBST(BOXMODEL)
|
||||
|
||||
AM_CONDITIONAL(BOXTYPE_AZBOX, test "$BOXTYPE" = "azbox")
|
||||
AM_CONDITIONAL(BOXTYPE_DBOX2, test "$BOXTYPE" = "dbox2")
|
||||
AM_CONDITIONAL(BOXTYPE_TRIPLE, test "$BOXTYPE" = "tripledragon")
|
||||
AM_CONDITIONAL(BOXTYPE_SPARK, test "$BOXTYPE" = "spark")
|
||||
AM_CONDITIONAL(BOXTYPE_DREAMBOX, test "$BOXTYPE" = "dreambox")
|
||||
AM_CONDITIONAL(BOXTYPE_IPBOX, test "$BOXTYPE" = "ipbox")
|
||||
AM_CONDITIONAL(BOXTYPE_COOL, test "$BOXTYPE" = "coolstream")
|
||||
AM_CONDITIONAL(BOXTYPE_GENERIC, test "$BOXTYPE" = "generic")
|
||||
AM_CONDITIONAL(BOXTYPE_DUCKBOX, test "$BOXTYPE" = "duckbox")
|
||||
AM_CONDITIONAL(BOXTYPE_ARMBOX, test "$BOXTYPE" = "armbox")
|
||||
|
||||
AM_CONDITIONAL(BOXMODEL_UFS910,test "$BOXMODEL" = "ufs910")
|
||||
AM_CONDITIONAL(BOXMODEL_UFS912,test "$BOXMODEL" = "ufs912")
|
||||
AM_CONDITIONAL(BOXMODEL_UFS913,test "$BOXMODEL" = "ufs913")
|
||||
AM_CONDITIONAL(BOXMODEL_UFS922,test "$BOXMODEL" = "ufs922")
|
||||
AM_CONDITIONAL(BOXMODEL_SPARK,test "$BOXMODEL" = "spark")
|
||||
AM_CONDITIONAL(BOXMODEL_SPARK7162,test "$BOXMODEL" = "spark7162")
|
||||
AM_CONDITIONAL(BOXMODEL_ATEVIO7500,test "$BOXMODEL" = "atevio7500")
|
||||
AM_CONDITIONAL(BOXMODEL_FORTIS_HDBOX,test "$BOXMODEL" = "fortis_hdbox")
|
||||
AM_CONDITIONAL(BOXMODEL_OCTAGON1008,test "$BOXMODEL" = "octagon1008")
|
||||
AM_CONDITIONAL(BOXMODEL_HS7110,test "$BOXMODEL" = "hs7110")
|
||||
AM_CONDITIONAL(BOXMODEL_HS7810A,test "$BOXMODEL" = "hs7810a")
|
||||
AM_CONDITIONAL(BOXMODEL_HS7119,test "$BOXMODEL" = "hs7119")
|
||||
AM_CONDITIONAL(BOXMODEL_HS7819,test "$BOXMODEL" = "hs7819")
|
||||
AM_CONDITIONAL(BOXMODEL_DP7000,test "$BOXMODEL" = "dp7000")
|
||||
AM_CONDITIONAL(BOXMODEL_CUBEREVO,test "$BOXMODEL" = "cuberevo")
|
||||
AM_CONDITIONAL(BOXMODEL_CUBEREVO_MINI,test "$BOXMODEL" = "cuberevo_mini")
|
||||
AM_CONDITIONAL(BOXMODEL_CUBEREVO_MINI2,test "$BOXMODEL" = "cuberevo_mini2")
|
||||
AM_CONDITIONAL(BOXMODEL_CUBEREVO_250HD,test "$BOXMODEL" = "cuberevo_250hd")
|
||||
AM_CONDITIONAL(BOXMODEL_CUBEREVO_2000HD,test "$BOXMODEL" = "cuberevo_2000hd")
|
||||
AM_CONDITIONAL(BOXMODEL_CUBEREVO_3000HD,test "$BOXMODEL" = "cuberevo_3000hd")
|
||||
AM_CONDITIONAL(BOXMODEL_IPBOX9900,test "$BOXMODEL" = "ipbox9900")
|
||||
AM_CONDITIONAL(BOXMODEL_IPBOX99,test "$BOXMODEL" = "ipbox99")
|
||||
AM_CONDITIONAL(BOXMODEL_IPBOX55,test "$BOXMODEL" = "ipbox55")
|
||||
AM_CONDITIONAL(BOXMODEL_ARIVALINK200,test "$BOXMODEL" = "arivalink200")
|
||||
AM_CONDITIONAL(BOXMODEL_TF7700,test "$BOXMODEL" = "tf7700")
|
||||
AM_CONDITIONAL(BOXMODEL_HL101,test "$BOXMODEL" = "hl101")
|
||||
AM_CONDITIONAL(BOXMODEL_DM500,test "$BOXMODEL" = "dm500")
|
||||
AM_CONDITIONAL(BOXMODEL_DM500PLUS,test "$BOXMODEL" = "dm500plus")
|
||||
AM_CONDITIONAL(BOXMODEL_DM600PVR,test "$BOXMODEL" = "dm600pvr")
|
||||
AM_CONDITIONAL(BOXMODEL_DM56x0,test "$BOXMODEL" = "dm56x0")
|
||||
AM_CONDITIONAL(BOXMODEL_DM7000,test "$BOXMODEL" = "dm7000" -o "$BOXMODEL" = "dm7020" -o "$BOXMODEL" = "dm7025")
|
||||
|
||||
AM_CONDITIONAL(BOXMODEL_HD51,test "$BOXMODEL" = "hd51")
|
||||
AM_CONDITIONAL(BOXMODEL_VUSOLO4K,test "$BOXMODEL" = "vusolo4k")
|
||||
AM_CONDITIONAL(BOXMODEL_IP200,test "$BOXMODEL" = "ip200")
|
||||
AM_CONDITIONAL(BOXMODEL_IP250,test "$BOXMODEL" = "ip250")
|
||||
AM_CONDITIONAL(BOXMODEL_IP350,test "$BOXMODEL" = "ip350")
|
||||
AM_CONDITIONAL(BOXMODEL_IP400,test "$BOXMODEL" = "ip400")
|
||||
|
||||
AM_CONDITIONAL(BOXMODEL_RASPI,test "$BOXMODEL" = "raspi")
|
||||
|
||||
if test "$BOXTYPE" = "azbox"; then
|
||||
if test "$BOXTYPE" = "dbox2"; then
|
||||
AC_DEFINE(HAVE_DBOX_HARDWARE, 1, [building for a dbox2])
|
||||
elif test "$BOXTYPE" = "azbox"; then
|
||||
AC_DEFINE(HAVE_AZBOX_HARDWARE, 1, [building for an azbox])
|
||||
elif test "$BOXTYPE" = "tripledragon"; then
|
||||
AC_DEFINE(HAVE_TRIPLEDRAGON, 1, [building for a tripledragon])
|
||||
elif test "$BOXTYPE" = "spark"; then
|
||||
AC_DEFINE(HAVE_SPARK_HARDWARE, 1, [building for a goldenmedia 990 or edision pingulux])
|
||||
AC_DEFINE(HAVE_SPARK_HARDWARE, 1, [building for a spark st7111 box])
|
||||
elif test "$BOXTYPE" = "dreambox"; then
|
||||
AC_DEFINE(HAVE_DREAMBOX_HARDWARE, 1, [building for a dreambox])
|
||||
elif test "$BOXTYPE" = "ipbox"; then
|
||||
AC_DEFINE(HAVE_IPBOX_HARDWARE, 1, [building for an ipbox])
|
||||
elif test "$BOXTYPE" = "coolstream"; then
|
||||
AC_DEFINE(HAVE_COOL_HARDWARE, 1, [building for a coolstream])
|
||||
elif test "$BOXTYPE" = "generic"; then
|
||||
AC_DEFINE(HAVE_GENERIC_HARDWARE, 1, [building for a generic device like a standard PC])
|
||||
elif test "$BOXTYPE" = "duckbox"; then
|
||||
AC_DEFINE(HAVE_DUCKBOX_HARDWARE, 1, [building for a duckbox])
|
||||
elif test "$BOXTYPE" = "armbox"; then
|
||||
AC_DEFINE(HAVE_ARM_HARDWARE, 1, [building for an armbox])
|
||||
|
||||
fi
|
||||
|
||||
# TODO: do we need more defines?
|
||||
if test "$BOXMODEL" = "raspi"; then
|
||||
if test "$BOXMODEL" = "dm500"; then
|
||||
AC_DEFINE(BOXMODEL_DM500, 1, [dreambox 500])
|
||||
elif test "$BOXMODEL" = "ip200"; then
|
||||
AC_DEFINE(BOXMODEL_IP200, 1, [ipbox 200])
|
||||
elif test "$BOXMODEL" = "ip250"; then
|
||||
AC_DEFINE(BOXMODEL_IP250, 1, [ipbox 250])
|
||||
elif test "$BOXMODEL" = "ip350"; then
|
||||
AC_DEFINE(BOXMODEL_IP350, 1, [ipbox 350])
|
||||
elif test "$BOXMODEL" = "ip400"; then
|
||||
AC_DEFINE(BOXMODEL_IP400, 1, [ipbox 400])
|
||||
elif test "$BOXMODEL" = "raspi"; then
|
||||
AC_DEFINE(BOXMODEL_RASPI, 1, [Raspberry pi])
|
||||
elif test "$BOXMODEL" = "ufs910"; then
|
||||
AC_DEFINE(BOXMODEL_UFS910, 1, [ufs910])
|
||||
elif test "$BOXMODEL" = "ufs912"; then
|
||||
AC_DEFINE(BOXMODEL_UFS912, 1, [ufs912])
|
||||
elif test "$BOXMODEL" = "ufs913"; then
|
||||
AC_DEFINE(BOXMODEL_UFS913, 1, [ufs913])
|
||||
elif test "$BOXMODEL" = "ufs922"; then
|
||||
AC_DEFINE(BOXMODEL_UFS922, 1, [ufs922])
|
||||
elif test "$BOXMODEL" = "spark"; then
|
||||
AC_DEFINE(BOXMODEL_SPARK, 1, [spark])
|
||||
elif test "$BOXMODEL" = "spark7162"; then
|
||||
AC_DEFINE(BOXMODEL_SPARK7162, 1, [spark7162])
|
||||
elif test "$BOXMODEL" = "atevio7500"; then
|
||||
AC_DEFINE(BOXMODEL_ATEVIO7500, 1, [atevio7500])
|
||||
elif test "$BOXMODEL" = "fortis_hdbox"; then
|
||||
AC_DEFINE(BOXMODEL_FORTIS_HDBOX, 1, [fortis_hdbox])
|
||||
elif test "$BOXMODEL" = "octagon1008"; then
|
||||
AC_DEFINE(BOXMODEL_OCTAGON1008, 1, [octagon1008])
|
||||
elif test "$BOXMODEL" = "hs7110"; then
|
||||
AC_DEFINE(BOXMODEL_HS7110, 1, [hs7110])
|
||||
elif test "$BOXMODEL" = "hs7810a"; then
|
||||
AC_DEFINE(BOXMODEL_HS7810A, 1, [hs7810a])
|
||||
elif test "$BOXMODEL" = "hs7119"; then
|
||||
AC_DEFINE(BOXMODEL_HS7119, 1, [hs7119])
|
||||
elif test "$BOXMODEL" = "hs7819"; then
|
||||
AC_DEFINE(BOXMODEL_HS7819, 1, [hs7819])
|
||||
elif test "$BOXMODEL" = "dp7000"; then
|
||||
AC_DEFINE(BOXMODEL_DP7000, 1, [dp7000])
|
||||
elif test "$BOXMODEL" = "cuberevo"; then
|
||||
AC_DEFINE(BOXMODEL_CUBEREVO, 1, [cuberevo])
|
||||
elif test "$BOXMODEL" = "cuberevo_mini"; then
|
||||
AC_DEFINE(BOXMODEL_CUBEREVO_MINI, 1, [cuberevo_mini])
|
||||
elif test "$BOXMODEL" = "cuberevo_mini2"; then
|
||||
AC_DEFINE(BOXMODEL_CUBEREVO_MINI2, 1, [cuberevo_mini2])
|
||||
elif test "$BOXMODEL" = "cuberevo_250hd"; then
|
||||
AC_DEFINE(BOXMODEL_CUBEREVO_250HD, 1, [cuberevo_250hd])
|
||||
elif test "$BOXMODEL" = "cuberevo_2000hd"; then
|
||||
AC_DEFINE(BOXMODEL_CUBEREVO_2000HD, 1, [cuberevo_2000hd])
|
||||
elif test "$BOXMODEL" = "cuberevo_3000hd"; then
|
||||
AC_DEFINE(BOXMODEL_CUBEREVO_3000HD, 1, [cuberevo_3000hd])
|
||||
elif test "$BOXMODEL" = "ipbox9900"; then
|
||||
AC_DEFINE(BOXMODEL_IPBOX9900, 1, [ipbox9900])
|
||||
elif test "$BOXMODEL" = "ipbox99"; then
|
||||
AC_DEFINE(BOXMODEL_IPBOX99, 1, [ipbox99])
|
||||
elif test "$BOXMODEL" = "ipbox55"; then
|
||||
AC_DEFINE(BOXMODEL_IPBOX55, 1, [ipbox55])
|
||||
elif test "$BOXMODEL" = "arivalink200"; then
|
||||
AC_DEFINE(BOXMODEL_ARIVALINK200, 1, [arivalink200])
|
||||
elif test "$BOXMODEL" = "tf7700"; then
|
||||
AC_DEFINE(BOXMODEL_TF7700, 1, [tf7700])
|
||||
elif test "$BOXMODEL" = "hl101"; then
|
||||
AC_DEFINE(BOXMODEL_HL101, 1, [hl101])
|
||||
elif test "$BOXMODEL" = "hd51"; then
|
||||
AC_DEFINE(BOXMODEL_HD51, 1, [HD51 / AX51])
|
||||
elif test "$BOXMODEL" = "vusolo4k"; then
|
||||
AC_DEFINE(BOXMODEL_VUSOLO4K, 1, [vusolo4k])
|
||||
fi
|
||||
])
|
||||
|
||||
|
@@ -1,7 +1,8 @@
|
||||
noinst_LTLIBRARIES = libazbox.la
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/common
|
||||
-I$(top_srcdir)/common \
|
||||
-I$(top_srcdir)/include
|
||||
|
||||
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
|
||||
AM_LDFLAGS = -lpthread
|
||||
@@ -13,6 +14,5 @@ libazbox_la_SOURCES = \
|
||||
audio.cpp \
|
||||
init.cpp \
|
||||
playback.cpp \
|
||||
pwrmngr.cpp \
|
||||
record.cpp
|
||||
|
||||
|
161
azbox/audio.cpp
161
azbox/audio.cpp
@@ -9,7 +9,7 @@
|
||||
|
||||
#include <proc_tools.h>
|
||||
|
||||
#include "audio_lib.h"
|
||||
#include "audio_hal.h"
|
||||
#include "lt_debug.h"
|
||||
|
||||
#define AUDIO_DEVICE "/dev/dvb/adapter0/audio0"
|
||||
@@ -20,54 +20,55 @@
|
||||
|
||||
cAudio * audioDecoder = NULL;
|
||||
|
||||
typedef struct audio_pdata
|
||||
{
|
||||
int fd;
|
||||
int clipfd;
|
||||
int mixer_fd;
|
||||
int mixer_num;
|
||||
} audio_pdata;
|
||||
#define P ((audio_pdata *)pdata)
|
||||
|
||||
cAudio::cAudio(void *, void *, void *)
|
||||
{
|
||||
fd = -1;
|
||||
clipfd = -1;
|
||||
mixer_fd = -1;
|
||||
openDevice();
|
||||
Muted = false;
|
||||
pdata = calloc(1, sizeof(audio_pdata));
|
||||
P->clipfd = -1;
|
||||
P->mixer_fd = -1;
|
||||
P->fd = open(AUDIO_DEVICE, O_RDONLY|O_CLOEXEC);
|
||||
if (P->fd < 0)
|
||||
lt_info("%s: open failed (%m)\n", __func__);
|
||||
muted = false;
|
||||
}
|
||||
|
||||
cAudio::~cAudio(void)
|
||||
{
|
||||
closeDevice();
|
||||
}
|
||||
|
||||
void cAudio::openDevice(void)
|
||||
{
|
||||
lt_debug("%s\n", __func__);
|
||||
if (fd < 0)
|
||||
{
|
||||
if ((fd = open(AUDIO_DEVICE, O_RDONLY|O_CLOEXEC)) < 0)
|
||||
lt_info("openDevice: open failed (%m)\n");
|
||||
do_mute(true, false);
|
||||
if (P->fd >= 0) {
|
||||
ioctl(P->fd, AUDIO_CONTINUE); /* enigma2 also does CONTINUE before close... */
|
||||
close(P->fd);
|
||||
P->fd = -1;
|
||||
}
|
||||
else
|
||||
lt_info("openDevice: already open (fd = %d)\n", fd);
|
||||
if (P->clipfd >= 0)
|
||||
close(P->clipfd);
|
||||
if (P->mixer_fd >= 0)
|
||||
close(P->mixer_fd);
|
||||
free(pdata);
|
||||
}
|
||||
|
||||
void cAudio::closeDevice(void)
|
||||
int cAudio::mute(void)
|
||||
{
|
||||
lt_debug("%s\n", __func__);
|
||||
ioctl(fd, AUDIO_CONTINUE); /* enigma2 also does CONTINUE before close... */
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
fd = -1;
|
||||
if (clipfd >= 0)
|
||||
close(clipfd);
|
||||
clipfd = -1;
|
||||
if (mixer_fd >= 0)
|
||||
close(mixer_fd);
|
||||
mixer_fd = -1;
|
||||
return SetMute(true);
|
||||
}
|
||||
|
||||
int cAudio::do_mute(bool enable, bool remember)
|
||||
int cAudio::unmute(void)
|
||||
{
|
||||
lt_debug("%s(%d, %d)\n", __func__, enable, remember);
|
||||
return SetMute(false);
|
||||
}
|
||||
|
||||
if (remember)
|
||||
Muted = enable;
|
||||
int cAudio::SetMute(bool enable)
|
||||
{
|
||||
lt_debug("%s(%d)\n", __func__, enable);
|
||||
|
||||
muted = enable;
|
||||
#if 0
|
||||
/* does not work? */
|
||||
if (ioctl(fd, AUDIO_SET_MUTE, enable) < 0 )
|
||||
@@ -96,14 +97,14 @@ int cAudio::setVolume(unsigned int left, unsigned int right)
|
||||
lt_debug("%s(%d, %d)\n", __func__, left, right);
|
||||
|
||||
volume = (left + right) / 2;
|
||||
if (clipfd != -1 && mixer_fd != -1) {
|
||||
if (P->clipfd != -1 && P->mixer_fd != -1) {
|
||||
int tmp = 0;
|
||||
/* not sure if left / right is correct here, but it is always the same anyways ;-) */
|
||||
if (! Muted)
|
||||
if (! muted)
|
||||
tmp = left << 8 | right;
|
||||
int ret = ioctl(mixer_fd, MIXER_WRITE(mixer_num), &tmp);
|
||||
int ret = ioctl(P->mixer_fd, MIXER_WRITE(P->mixer_num), &tmp);
|
||||
if (ret == -1)
|
||||
lt_info("%s: MIXER_WRITE(%d),%04x: %m\n", __func__, mixer_num, tmp);
|
||||
lt_info("%s: MIXER_WRITE(%d),%04x: %m\n", __func__, P->mixer_num, tmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -111,7 +112,7 @@ int cAudio::setVolume(unsigned int left, unsigned int right)
|
||||
mixer.volume_left = map_volume(left);
|
||||
mixer.volume_right = map_volume(right);
|
||||
|
||||
if (ioctl(fd, AUDIO_SET_MIXER, &mixer) < 0)
|
||||
if (ioctl(P->fd, AUDIO_SET_MIXER, &mixer) < 0)
|
||||
lt_info("%s: AUDIO_SET_MIXER failed (%m)\n", __func__);
|
||||
|
||||
return 0;
|
||||
@@ -121,16 +122,16 @@ int cAudio::Start(void)
|
||||
{
|
||||
lt_debug("%s\n", __func__);
|
||||
int ret;
|
||||
ioctl(fd, AUDIO_CONTINUE);
|
||||
ret = ioctl(fd, AUDIO_PLAY);
|
||||
ioctl(P->fd, AUDIO_CONTINUE);
|
||||
ret = ioctl(P->fd, AUDIO_PLAY);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cAudio::Stop(void)
|
||||
{
|
||||
lt_debug("%s\n", __func__);
|
||||
ioctl(fd, AUDIO_STOP);
|
||||
ioctl(fd, AUDIO_CONTINUE); /* no idea why we have to stop and then continue => enigma2 does it, too */
|
||||
ioctl(P->fd, AUDIO_STOP);
|
||||
ioctl(P->fd, AUDIO_CONTINUE); /* no idea why we have to stop and then continue => enigma2 does it, too */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -142,7 +143,7 @@ bool cAudio::Pause(bool /*Pcm*/)
|
||||
void cAudio::SetSyncMode(AVSYNC_TYPE Mode)
|
||||
{
|
||||
lt_debug("%s %d\n", __func__, Mode);
|
||||
ioctl(fd, AUDIO_SET_AV_SYNC, Mode);
|
||||
ioctl(P->fd, AUDIO_SET_AV_SYNC, Mode);
|
||||
};
|
||||
|
||||
//AUDIO_ENCODING_AC3
|
||||
@@ -158,7 +159,6 @@ void cAudio::SetStreamType(AUDIO_FORMAT type)
|
||||
{
|
||||
int bypass = AUDIO_STREAMTYPE_MPEG;
|
||||
lt_debug("%s %d\n", __func__, type);
|
||||
StreamType = type;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
@@ -175,7 +175,7 @@ void cAudio::SetStreamType(AUDIO_FORMAT type)
|
||||
|
||||
// Normaly the encoding should be set using AUDIO_SET_ENCODING
|
||||
// But as we implemented the behavior to bypass (cause of e2) this is correct here
|
||||
if (ioctl(fd, AUDIO_SET_BYPASS_MODE, bypass) < 0)
|
||||
if (ioctl(P->fd, AUDIO_SET_BYPASS_MODE, bypass) < 0)
|
||||
lt_info("%s: AUDIO_SET_BYPASS_MODE failed (%m)\n", __func__);
|
||||
};
|
||||
|
||||
@@ -191,12 +191,12 @@ int cAudio::PrepareClipPlay(int ch, int srate, int bits, int little_endian)
|
||||
const char *dsp_dev = getenv("DSP_DEVICE");
|
||||
const char *mix_dev = getenv("MIX_DEVICE");
|
||||
lt_debug("%s ch %d srate %d bits %d le %d\n", __FUNCTION__, ch, srate, bits, little_endian);
|
||||
if (clipfd >= 0) {
|
||||
lt_info("%s: clipfd already opened (%d)\n", __FUNCTION__, clipfd);
|
||||
if (P->clipfd >= 0) {
|
||||
lt_info("%s: clipfd already opened (%d)\n", __func__, P->clipfd);
|
||||
return -1;
|
||||
}
|
||||
mixer_num = -1;
|
||||
mixer_fd = -1;
|
||||
P->mixer_num = -1;
|
||||
P->mixer_fd = -1;
|
||||
/* a different DSP device can be given with DSP_DEVICE and MIX_DEVICE
|
||||
* if this device cannot be opened, we fall back to the internal OSS device
|
||||
* Example:
|
||||
@@ -213,8 +213,8 @@ int cAudio::PrepareClipPlay(int ch, int srate, int bits, int little_endian)
|
||||
}
|
||||
lt_info("%s: dsp_dev %s mix_dev %s\n", __func__, dsp_dev, mix_dev); /* NULL mix_dev is ok */
|
||||
/* the tdoss dsp driver seems to work only on the second open(). really. */
|
||||
clipfd = open(dsp_dev, O_WRONLY|O_CLOEXEC);
|
||||
if (clipfd < 0) {
|
||||
P->clipfd = open(dsp_dev, O_WRONLY|O_CLOEXEC);
|
||||
if (P->clipfd < 0) {
|
||||
lt_info("%s open %s: %m\n", dsp_dev, __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
@@ -223,29 +223,29 @@ int cAudio::PrepareClipPlay(int ch, int srate, int bits, int little_endian)
|
||||
fmt = AFMT_S16_BE;
|
||||
else
|
||||
fmt = AFMT_S16_LE;
|
||||
if (ioctl(clipfd, SNDCTL_DSP_SETFMT, &fmt))
|
||||
if (ioctl(P->clipfd, SNDCTL_DSP_SETFMT, &fmt))
|
||||
perror("SNDCTL_DSP_SETFMT");
|
||||
if (ioctl(clipfd, SNDCTL_DSP_CHANNELS, &ch))
|
||||
if (ioctl(P->clipfd, SNDCTL_DSP_CHANNELS, &ch))
|
||||
perror("SNDCTL_DSP_CHANNELS");
|
||||
if (ioctl(clipfd, SNDCTL_DSP_SPEED, &srate))
|
||||
if (ioctl(P->clipfd, SNDCTL_DSP_SPEED, &srate))
|
||||
perror("SNDCTL_DSP_SPEED");
|
||||
if (ioctl(clipfd, SNDCTL_DSP_RESET))
|
||||
if (ioctl(P->clipfd, SNDCTL_DSP_RESET))
|
||||
perror("SNDCTL_DSP_RESET");
|
||||
|
||||
if (!mix_dev)
|
||||
return 0;
|
||||
|
||||
mixer_fd = open(mix_dev, O_RDWR|O_CLOEXEC);
|
||||
if (mixer_fd < 0) {
|
||||
P->mixer_fd = open(mix_dev, O_RDWR|O_CLOEXEC);
|
||||
if (P->mixer_fd < 0) {
|
||||
lt_info("%s: open mixer %s failed (%m)\n", __func__, mix_dev);
|
||||
/* not a real error */
|
||||
return 0;
|
||||
}
|
||||
if (ioctl(mixer_fd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) {
|
||||
if (ioctl(P->mixer_fd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) {
|
||||
lt_info("%s: SOUND_MIXER_READ_DEVMASK %m\n", __func__);
|
||||
devmask = 0;
|
||||
}
|
||||
if (ioctl(mixer_fd, SOUND_MIXER_READ_STEREODEVS, &stereo) == -1) {
|
||||
if (ioctl(P->mixer_fd, SOUND_MIXER_READ_STEREODEVS, &stereo) == -1) {
|
||||
lt_info("%s: SOUND_MIXER_READ_STEREODEVS %m\n", __func__);
|
||||
stereo = 0;
|
||||
}
|
||||
@@ -253,8 +253,8 @@ int cAudio::PrepareClipPlay(int ch, int srate, int bits, int little_endian)
|
||||
if (usable == 0) {
|
||||
lt_info("%s: devmask: %08x stereo: %08x, no usable dev :-(\n",
|
||||
__func__, devmask, stereo);
|
||||
close(mixer_fd);
|
||||
mixer_fd = -1;
|
||||
close(P->mixer_fd);
|
||||
P->mixer_fd = -1;
|
||||
return 0; /* TODO: should we treat this as error? */
|
||||
}
|
||||
/* __builtin_popcount needs GCC, it counts the set bits... */
|
||||
@@ -265,14 +265,14 @@ int cAudio::PrepareClipPlay(int ch, int srate, int bits, int little_endian)
|
||||
__func__, devmask, stereo, __func__);
|
||||
const char *tmp = getenv("MIX_NUMBER");
|
||||
if (tmp)
|
||||
mixer_num = atoi(tmp);
|
||||
P->mixer_num = atoi(tmp);
|
||||
lt_info("%s: mixer_num is %d -> device %08x\n",
|
||||
__func__, mixer_num, (mixer_num >= 0) ? (1 << mixer_num) : 0);
|
||||
__func__, P->mixer_num, (P->mixer_num >= 0) ? (1 << P->mixer_num) : 0);
|
||||
/* no error checking, you'd better know what you are doing... */
|
||||
} else {
|
||||
mixer_num = 0;
|
||||
P->mixer_num = 0;
|
||||
while (!(usable & 0x01)) {
|
||||
mixer_num++;
|
||||
P->mixer_num++;
|
||||
usable >>= 1;
|
||||
}
|
||||
}
|
||||
@@ -285,11 +285,11 @@ int cAudio::WriteClip(unsigned char *buffer, int size)
|
||||
{
|
||||
int ret;
|
||||
// lt_debug("cAudio::%s\n", __FUNCTION__);
|
||||
if (clipfd <= 0) {
|
||||
if (P->clipfd <= 0) {
|
||||
lt_info("%s: clipfd not yet opened\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
ret = write(clipfd, buffer, size);
|
||||
ret = write(P->clipfd, buffer, size);
|
||||
if (ret < 0)
|
||||
lt_info("%s: write error (%m)\n", __FUNCTION__);
|
||||
return ret;
|
||||
@@ -298,15 +298,15 @@ int cAudio::WriteClip(unsigned char *buffer, int size)
|
||||
int cAudio::StopClip()
|
||||
{
|
||||
lt_debug("%s\n", __FUNCTION__);
|
||||
if (clipfd <= 0) {
|
||||
if (P->clipfd <= 0) {
|
||||
lt_info("%s: clipfd not yet opened\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
close(clipfd);
|
||||
clipfd = -1;
|
||||
if (mixer_fd >= 0)
|
||||
close(mixer_fd);
|
||||
mixer_fd = -1;
|
||||
close(P->clipfd);
|
||||
P->clipfd = -1;
|
||||
if (P->mixer_fd >= 0)
|
||||
close(P->mixer_fd);
|
||||
P->mixer_fd = -1;
|
||||
setVolume(volume, volume);
|
||||
return 0;
|
||||
};
|
||||
@@ -370,10 +370,15 @@ void cAudio::SetHdmiDD(bool enable)
|
||||
lt_debug("%s %d\n", __func__, enable);
|
||||
};
|
||||
|
||||
#define AUDIO_BYPASS_ON 0
|
||||
#define AUDIO_BYPASS_OFF 1
|
||||
void cAudio::SetSpdifDD(bool enable)
|
||||
{
|
||||
lt_debug("%s %d\n", __func__, enable);
|
||||
setBypassMode(!enable);
|
||||
//setBypassMode(!enable);
|
||||
int mode = enable ? AUDIO_BYPASS_ON : AUDIO_BYPASS_OFF;
|
||||
if (ioctl(P->fd, AUDIO_SET_BYPASS_MODE, mode) < 0)
|
||||
lt_info("%s AUDIO_SET_BYPASS_MODE %d: %m\n", __func__, mode);
|
||||
};
|
||||
|
||||
void cAudio::ScheduleMute(bool On)
|
||||
@@ -386,8 +391,7 @@ void cAudio::EnableAnalogOut(bool enable)
|
||||
lt_debug("%s %d\n", __FUNCTION__, enable);
|
||||
};
|
||||
|
||||
#define AUDIO_BYPASS_ON 0
|
||||
#define AUDIO_BYPASS_OFF 1
|
||||
#if 0
|
||||
void cAudio::setBypassMode(bool disable)
|
||||
{
|
||||
lt_debug("%s %d\n", __func__, disable);
|
||||
@@ -396,3 +400,4 @@ void cAudio::setBypassMode(bool disable)
|
||||
lt_info("%s AUDIO_SET_BYPASS_MODE %d: %m\n", __func__, mode);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
@@ -1,98 +0,0 @@
|
||||
/* public header file */
|
||||
|
||||
#ifndef _AUDIO_LIB_H_
|
||||
#define _AUDIO_LIB_H_
|
||||
|
||||
#include "../common/cs_types.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_SYNC_WITH_PTS,
|
||||
AUDIO_NO_SYNC,
|
||||
AUDIO_SYNC_AUDIO_MASTER
|
||||
} AUDIO_SYNC_MODE;
|
||||
|
||||
typedef enum {
|
||||
HDMI_ENCODED_OFF,
|
||||
HDMI_ENCODED_AUTO,
|
||||
HDMI_ENCODED_FORCED
|
||||
} HDMI_ENCODED_MODE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_FMT_AUTO = 0,
|
||||
AUDIO_FMT_MPEG,
|
||||
AUDIO_FMT_MP3,
|
||||
AUDIO_FMT_DOLBY_DIGITAL,
|
||||
AUDIO_FMT_BASIC = AUDIO_FMT_DOLBY_DIGITAL,
|
||||
AUDIO_FMT_AAC,
|
||||
AUDIO_FMT_AAC_PLUS,
|
||||
AUDIO_FMT_DD_PLUS,
|
||||
AUDIO_FMT_DTS,
|
||||
AUDIO_FMT_AVS,
|
||||
AUDIO_FMT_MLP,
|
||||
AUDIO_FMT_WMA,
|
||||
AUDIO_FMT_MPG1, // TD only. For Movieplayer / cPlayback
|
||||
AUDIO_FMT_ADVANCED = AUDIO_FMT_MLP
|
||||
} AUDIO_FORMAT;
|
||||
|
||||
class cAudio
|
||||
{
|
||||
friend class cPlayback;
|
||||
private:
|
||||
int fd;
|
||||
bool Muted;
|
||||
|
||||
int clipfd; /* for pcm playback */
|
||||
int mixer_fd; /* if we are using the OSS mixer */
|
||||
int mixer_num; /* oss mixer to use, if any */
|
||||
|
||||
AUDIO_FORMAT StreamType;
|
||||
AUDIO_SYNC_MODE SyncMode;
|
||||
bool started;
|
||||
|
||||
int volume;
|
||||
|
||||
void openDevice(void);
|
||||
void closeDevice(void);
|
||||
|
||||
int do_mute(bool enable, bool remember);
|
||||
void setBypassMode(bool disable);
|
||||
public:
|
||||
/* construct & destruct */
|
||||
cAudio(void *, void *, void *);
|
||||
~cAudio(void);
|
||||
|
||||
void *GetHandle() { return NULL; };
|
||||
/* shut up */
|
||||
int mute(bool remember = true) { return do_mute(true, remember); };
|
||||
int unmute(bool remember = true) { return do_mute(false, remember); };
|
||||
|
||||
/* volume, min = 0, max = 255 */
|
||||
int setVolume(unsigned int left, unsigned int right);
|
||||
int getVolume(void) { return volume;}
|
||||
bool getMuteStatus(void) { return Muted; };
|
||||
|
||||
/* start and stop audio */
|
||||
int Start(void);
|
||||
int Stop(void);
|
||||
bool Pause(bool Pcm = true);
|
||||
void SetStreamType(AUDIO_FORMAT type);
|
||||
void SetSyncMode(AVSYNC_TYPE Mode);
|
||||
|
||||
/* select channels */
|
||||
int setChannel(int channel);
|
||||
int PrepareClipPlay(int uNoOfChannels, int uSampleRate, int uBitsPerSample, int bLittleEndian);
|
||||
int WriteClip(unsigned char * buffer, int size);
|
||||
int StopClip();
|
||||
void getAudioInfo(int &type, int &layer, int& freq, int &bitrate, int &mode);
|
||||
void SetSRS(int iq_enable, int nmgr_enable, int iq_mode, int iq_level);
|
||||
bool IsHdmiDDSupported();
|
||||
void SetHdmiDD(bool enable);
|
||||
void SetSpdifDD(bool enable);
|
||||
void ScheduleMute(bool On);
|
||||
void EnableAnalogOut(bool enable);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -1 +0,0 @@
|
||||
../libspark/cs_api.h
|
@@ -30,11 +30,13 @@
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include "dmx_lib.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include "dmx_hal.h"
|
||||
#include "lt_debug.h"
|
||||
|
||||
/* Ugh... see comment in destructor for details... */
|
||||
#include "video_lib.h"
|
||||
#include "video_hal.h"
|
||||
#include "video_priv.h"
|
||||
extern cVideo *videoDecoder;
|
||||
|
||||
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_DEMUX, this, args)
|
||||
@@ -42,14 +44,8 @@ extern cVideo *videoDecoder;
|
||||
#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_DEMUX, NULL, args)
|
||||
|
||||
#define dmx_err(_errfmt, _errstr, _revents) do { \
|
||||
uint16_t _pid = (uint16_t)-1; uint16_t _f = 0;\
|
||||
if (dmx_type == DMX_PSI_CHANNEL) { \
|
||||
_pid = s_flt.pid; _f = s_flt.filter.filter[0]; \
|
||||
} else { \
|
||||
_pid = p_flt.pid; \
|
||||
}; \
|
||||
lt_info("%s " _errfmt " fd:%d, ev:0x%x %s pid:0x%04hx flt:0x%02hx\n", \
|
||||
__func__, _errstr, fd, _revents, DMX_T[dmx_type], _pid, _f); \
|
||||
__func__, _errstr, fd, _revents, DMX_T[dmx_type], pid, flt); \
|
||||
} while(0);
|
||||
|
||||
cDemux *videoDemux = NULL;
|
||||
@@ -88,9 +84,6 @@ cDemux::cDemux(int n)
|
||||
else
|
||||
num = n;
|
||||
fd = -1;
|
||||
measure = false;
|
||||
last_measure = 0;
|
||||
last_data = 0;
|
||||
}
|
||||
|
||||
cDemux::~cDemux()
|
||||
@@ -165,8 +158,6 @@ void cDemux::Close(void)
|
||||
ioctl(fd, DMX_STOP);
|
||||
close(fd);
|
||||
fd = -1;
|
||||
if (measure)
|
||||
return;
|
||||
if (dmx_type == DMX_TP_CHANNEL)
|
||||
{
|
||||
dmx_tp_count--;
|
||||
@@ -273,11 +264,13 @@ int cDemux::Read(unsigned char *buff, int len, int timeout)
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool cDemux::sectionFilter(unsigned short pid, const unsigned char * const filter,
|
||||
bool cDemux::sectionFilter(unsigned short _pid, const unsigned char * const filter,
|
||||
const unsigned char * const mask, int len, int timeout,
|
||||
const unsigned char * const negmask)
|
||||
{
|
||||
struct dmx_sct_filter_params s_flt;
|
||||
memset(&s_flt, 0, sizeof(s_flt));
|
||||
pid = _pid;
|
||||
|
||||
if (len > DMX_FILTER_SIZE)
|
||||
{
|
||||
@@ -286,6 +279,7 @@ bool cDemux::sectionFilter(unsigned short pid, const unsigned char * const filte
|
||||
}
|
||||
s_flt.pid = pid;
|
||||
s_flt.timeout = timeout;
|
||||
flt = filter[0];
|
||||
memcpy(s_flt.filter.filter, filter, len);
|
||||
memcpy(s_flt.filter.mask, mask, len);
|
||||
if (negmask != NULL)
|
||||
@@ -389,8 +383,11 @@ bool cDemux::sectionFilter(unsigned short pid, const unsigned char * const filte
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cDemux::pesFilter(const unsigned short pid)
|
||||
bool cDemux::pesFilter(const unsigned short _pid)
|
||||
{
|
||||
struct dmx_pes_filter_params p_flt;
|
||||
pid = _pid;
|
||||
flt = 0;
|
||||
/* allow PID 0 for web streaming e.g.
|
||||
* this check originally is from tuxbox cvs but I'm not sure
|
||||
* what it is good for...
|
||||
@@ -497,7 +494,7 @@ void cDemux::getSTC(int64_t * STC)
|
||||
lt_debug("%s #%d\n", __func__, num);
|
||||
int64_t pts = 0;
|
||||
if (videoDecoder)
|
||||
pts = videoDecoder->GetPTS();
|
||||
pts = videoDecoder->vdec->GetPTS();
|
||||
*STC = pts;
|
||||
}
|
||||
|
||||
|
@@ -1 +0,0 @@
|
||||
#include "dmx_lib.h"
|
@@ -1,70 +0,0 @@
|
||||
#ifndef __DEMUX_TD_H
|
||||
#define __DEMUX_TD_H
|
||||
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
#include <inttypes.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/dvb/dmx.h>
|
||||
#include "../common/cs_types.h"
|
||||
|
||||
#define MAX_DMX_UNITS 4
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DMX_INVALID = 0,
|
||||
DMX_VIDEO_CHANNEL = 1,
|
||||
DMX_AUDIO_CHANNEL,
|
||||
DMX_PES_CHANNEL,
|
||||
DMX_PSI_CHANNEL,
|
||||
DMX_PIP_CHANNEL,
|
||||
DMX_TP_CHANNEL,
|
||||
DMX_PCR_ONLY_CHANNEL
|
||||
} DMX_CHANNEL_TYPE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int fd;
|
||||
unsigned short pid;
|
||||
} pes_pids;
|
||||
|
||||
class cDemux
|
||||
{
|
||||
private:
|
||||
int num;
|
||||
int fd;
|
||||
int buffersize;
|
||||
bool measure;
|
||||
uint64_t last_measure, last_data;
|
||||
DMX_CHANNEL_TYPE dmx_type;
|
||||
std::vector<pes_pids> pesfds;
|
||||
struct dmx_sct_filter_params s_flt;
|
||||
struct dmx_pes_filter_params p_flt;
|
||||
public:
|
||||
|
||||
bool Open(DMX_CHANNEL_TYPE pes_type, void * x = NULL, int y = 0);
|
||||
void Close(void);
|
||||
bool Start(bool record = false);
|
||||
bool Stop(void);
|
||||
int Read(unsigned char *buff, int len, int Timeout = 0);
|
||||
bool sectionFilter(unsigned short pid, const unsigned char * const filter, const unsigned char * const mask, int len, int Timeout = 0, const unsigned char * const negmask = NULL);
|
||||
bool pesFilter(const unsigned short pid);
|
||||
void SetSyncMode(AVSYNC_TYPE mode);
|
||||
void * getBuffer();
|
||||
void * getChannel();
|
||||
DMX_CHANNEL_TYPE getChannelType(void) { return dmx_type; };
|
||||
bool addPid(unsigned short pid);
|
||||
void getSTC(int64_t * STC);
|
||||
int getUnit(void);
|
||||
static bool SetSource(int unit, int source);
|
||||
static int GetSource(int unit);
|
||||
// TD only functions
|
||||
int getFD(void) { return fd; }; /* needed by cPlayback class */
|
||||
void removePid(unsigned short Pid); /* needed by cRecord class */
|
||||
std::vector<pes_pids> getPesPids(void) { return pesfds; };
|
||||
//
|
||||
cDemux(int num = 0);
|
||||
~cDemux();
|
||||
};
|
||||
|
||||
#endif //__DEMUX_H
|
@@ -2,7 +2,7 @@
|
||||
* determine the capabilities of the hardware.
|
||||
* part of libstb-hal
|
||||
*
|
||||
* (C) 2010-2012 Stefan Seyfried
|
||||
* (C) 2010-2012,2016 Stefan Seyfried
|
||||
*
|
||||
* License: GPL v2 or later
|
||||
*/
|
||||
@@ -30,7 +30,9 @@ hw_caps_t *get_hwcaps(void)
|
||||
caps.display_type = HW_DISPLAY_LINE_TEXT;
|
||||
caps.has_HDMI = 1;
|
||||
caps.display_xres = 8;
|
||||
caps.display_has_statusline = 0;
|
||||
caps.display_can_deepstandby = 0;
|
||||
caps.display_can_set_brightness = 0;
|
||||
strcpy(caps.boxvendor, "AZBox");
|
||||
const char *tmp;
|
||||
char buf[64];
|
||||
@@ -46,6 +48,7 @@ hw_caps_t *get_hwcaps(void)
|
||||
}
|
||||
else
|
||||
strcpy(caps.boxname, "(unknown model)");
|
||||
strcpy(caps.boxarch, "mipsel");
|
||||
|
||||
return ∩︀
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#include <unistd.h>
|
||||
#include "init_lib.h"
|
||||
#include "init_td.h"
|
||||
#include "lt_debug.h"
|
||||
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_INIT, NULL, args)
|
||||
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_INIT, NULL, args)
|
||||
|
@@ -1,5 +0,0 @@
|
||||
#ifndef __INIT_TD_H
|
||||
#define __INIT_TD_H
|
||||
void init_td_api();
|
||||
void shutdown_td_api();
|
||||
#endif
|
@@ -50,7 +50,7 @@
|
||||
#define IN_FILE "/tmp/rmfp.in2"
|
||||
#define OUT_FILE "/tmp/rmfp.out2"
|
||||
|
||||
#include "playback.h"
|
||||
#include "playback_hal.h"
|
||||
|
||||
extern "C"{
|
||||
#include "e2mruainclude.h"
|
||||
@@ -73,8 +73,38 @@ static time_t monotonic_ms(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
class PBPrivate
|
||||
{
|
||||
public:
|
||||
bool rmfp_command(int cmd, int param, bool has_param, char *buf, int buflen);
|
||||
void run_rmfp(void);
|
||||
PBPrivate(void) {
|
||||
playing = 0;
|
||||
thread_started = false;
|
||||
eof = false;
|
||||
open_success = false;
|
||||
pthread_mutex_init(&rmfp_cmd_mutex, NULL);
|
||||
};
|
||||
~PBPrivate(void) {
|
||||
pthread_mutex_destroy(&rmfp_cmd_mutex);
|
||||
};
|
||||
|
||||
int duration;
|
||||
int playing;
|
||||
int speed;
|
||||
playmode_t pmode;
|
||||
uint16_t apid;
|
||||
uint16_t subpid;
|
||||
bool eof;
|
||||
bool open_success;
|
||||
bool thread_started;
|
||||
pthread_t thread;
|
||||
pthread_mutex_t rmfp_cmd_mutex;
|
||||
char *fname;
|
||||
};
|
||||
|
||||
/* the mutex makes sure that commands are not interspersed */
|
||||
bool cPlayback::rmfp_command(int cmd, int param, bool has_param, char *buf, int buflen)
|
||||
bool PBPrivate::rmfp_command(int cmd, int param, bool has_param, char *buf, int buflen)
|
||||
{
|
||||
lt_info("%s: %d %d %d %d\n", __func__, cmd, param, has_param, buflen);
|
||||
bool ret = true;
|
||||
@@ -141,21 +171,21 @@ bool cPlayback::rmfp_command(int cmd, int param, bool has_param, char *buf, int
|
||||
* the output will be buffered after starting up and we will only
|
||||
* see "Playback has started..." after the player exits
|
||||
*/
|
||||
void cPlayback::run_rmfp()
|
||||
void PBPrivate::run_rmfp()
|
||||
{
|
||||
lt_debug("%s: starting\n", __func__);
|
||||
thread_started = true;
|
||||
//Watch for the space at the end
|
||||
std::string base = "rmfp_player -dram 1 -ve 1 -waitexit ";
|
||||
std::string filename(mfilename);
|
||||
std::string filename(fname);
|
||||
std::string file = '"' + filename + '"';
|
||||
std::string final = base + file;
|
||||
|
||||
if (playMode == PLAYMODE_TS && mduration != 0)
|
||||
if (pmode == PLAYMODE_TS && duration != 0)
|
||||
{
|
||||
std::stringstream duration;
|
||||
duration << (mduration /** 60000LL*/);
|
||||
final = base + "-duration " + duration.str() + " " + file;
|
||||
std::stringstream du;
|
||||
du << (duration /** 60000LL*/);
|
||||
final = base + "-duration " + du.str() + " " + file;
|
||||
}
|
||||
|
||||
pid_t pid = 0;
|
||||
@@ -190,7 +220,7 @@ void cPlayback::run_rmfp()
|
||||
else if (strstr(output, "End of file..."))
|
||||
{
|
||||
playing = 1; /* this can happen without "Playback has started..." */
|
||||
eof_reached = true;
|
||||
eof = true;
|
||||
lt_info("%s: ===================> eof_reached = true\n", __func__);
|
||||
}
|
||||
}
|
||||
@@ -206,14 +236,14 @@ void cPlayback::run_rmfp()
|
||||
playing = 2;
|
||||
else
|
||||
playing = 0;
|
||||
eof_reached = true;
|
||||
eof = true;
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
/* helper function to call the cpp thread loop */
|
||||
void *execute_rua_thread(void *c)
|
||||
{
|
||||
cPlayback *obj = (cPlayback *)c;
|
||||
PBPrivate *obj = (PBPrivate *)c;
|
||||
lt_info_c("%s\n", __func__);
|
||||
obj->run_rmfp();
|
||||
/* free(obj); // this is most likely wrong */
|
||||
@@ -228,11 +258,11 @@ bool cPlayback::Open(playmode_t PlayMode)
|
||||
"PLAYMODE_TS",
|
||||
"PLAYMODE_FILE"
|
||||
};
|
||||
playMode = PlayMode;
|
||||
if (playMode > 1)
|
||||
pd->pmode = PlayMode;
|
||||
if (pd->pmode > 1)
|
||||
{
|
||||
lt_info("%s: PlayMode %d out of range!\n", __func__, PlayMode);
|
||||
playMode = PLAYMODE_FILE;
|
||||
pd->pmode = PLAYMODE_FILE;
|
||||
}
|
||||
|
||||
lt_info("%s: mode %d (%s)\n", __func__, PlayMode, aPLAYMODE[PlayMode]);
|
||||
@@ -253,7 +283,7 @@ bool cPlayback::Open(playmode_t PlayMode)
|
||||
if (i > 10)
|
||||
{
|
||||
lt_info("%s: ERROR - player is not idle after 10 seconds!\n", __func__);
|
||||
open_success = false;
|
||||
pd->open_success = false;
|
||||
return false;
|
||||
}
|
||||
sleep(1);
|
||||
@@ -266,10 +296,15 @@ bool cPlayback::Open(playmode_t PlayMode)
|
||||
unlink(IN_FILE);
|
||||
unlink(OUT_FILE);
|
||||
|
||||
open_success = true;
|
||||
pd->open_success = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool cPlayback::Start(std::string /*filename*/, std::string /*headers*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//Used by Fileplay
|
||||
bool cPlayback::Start(char *filename, unsigned short vpid, int vtype, unsigned short _apid,
|
||||
int ac3, unsigned int duration)
|
||||
@@ -278,49 +313,49 @@ bool cPlayback::Start(char *filename, unsigned short vpid, int vtype, unsigned s
|
||||
|
||||
lt_info("%s: filename=%s\n", __func__, filename);
|
||||
lt_info("%s: vpid=%u vtype=%d apid=%u ac3=%d duration=%i open_success=%d\n",
|
||||
__func__, vpid, vtype, _apid, ac3, duration, open_success);
|
||||
__func__, vpid, vtype, _apid, ac3, duration, pd->open_success);
|
||||
|
||||
if (!open_success)
|
||||
if (!pd->open_success)
|
||||
return false;
|
||||
|
||||
eof_reached = false;
|
||||
pd->eof = false;
|
||||
//create playback path
|
||||
apid = 0;
|
||||
subpid = 0;
|
||||
mfilename = filename;
|
||||
mduration = duration;
|
||||
if (pthread_create(&thread, 0, execute_rua_thread, this) != 0)
|
||||
pd->apid = 0;
|
||||
pd->subpid = 0;
|
||||
pd->fname = filename;
|
||||
pd->duration = duration;
|
||||
if (pthread_create(&pd->thread, 0, execute_rua_thread, pd) != 0)
|
||||
{
|
||||
lt_info("%s: error creating rmfp_player thread! (out of memory?)\n", __func__);
|
||||
ret = false;
|
||||
}
|
||||
while (! playing)
|
||||
while (! pd->playing)
|
||||
sleep(1);
|
||||
if (playing == 2)
|
||||
playing = 0;
|
||||
if (pd->playing == 2)
|
||||
pd->playing = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cPlayback::Close(void)
|
||||
{
|
||||
lt_info("%s: playing %d thread_started %d\n", __func__, playing, thread_started);
|
||||
lt_info("%s: playing %d thread_started %d\n", __func__, pd->playing, pd->thread_started);
|
||||
|
||||
if (thread_started)
|
||||
if (pd->thread_started)
|
||||
{
|
||||
rmfp_command(KEY_COMMAND_QUIT_ALL, 0, false, NULL, 0);
|
||||
pd->rmfp_command(KEY_COMMAND_QUIT_ALL, 0, false, NULL, 0);
|
||||
|
||||
if (pthread_join(thread, NULL))
|
||||
if (pthread_join(pd->thread, NULL))
|
||||
lt_info("%s: error joining rmfp thread (%m)\n", __func__);
|
||||
playing = 0;
|
||||
thread_started = false;
|
||||
pd->playing = 0;
|
||||
pd->thread_started = false;
|
||||
}
|
||||
else
|
||||
lt_info("%s: Warning: thread_started == false!\n", __func__);
|
||||
|
||||
if (open_success)
|
||||
if (pd->open_success)
|
||||
{
|
||||
proc_put("/proc/player", "1", 2);
|
||||
open_success = false;
|
||||
pd->open_success = false;
|
||||
lt_info("%s: /proc/player switched to '1'\n", __func__);
|
||||
usleep(1000000);
|
||||
}
|
||||
@@ -329,39 +364,39 @@ void cPlayback::Close(void)
|
||||
bool cPlayback::SetAPid(unsigned short pid, int /*ac3*/)
|
||||
{
|
||||
lt_info("%s: pid %i\n", __func__, pid);
|
||||
if (pid != apid) {
|
||||
rmfp_command(KEY_COMMAND_SWITCH_AUDIO, pid, true, NULL, 0);
|
||||
apid = pid;
|
||||
if (pid != pd->apid) {
|
||||
pd->rmfp_command(KEY_COMMAND_SWITCH_AUDIO, pid, true, NULL, 0);
|
||||
pd->apid = pid;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cPlayback::SelectSubtitles(int pid)
|
||||
bool cPlayback::SelectSubtitles(int pid, std::string /*charset*/)
|
||||
{
|
||||
lt_info("%s: pid %i\n", __func__, pid);
|
||||
if (pid != subpid)
|
||||
if (pid != pd->subpid)
|
||||
{
|
||||
rmfp_command(KEY_COMMAND_SWITCH_SUBS, pid, true, NULL, 0);
|
||||
subpid = pid;
|
||||
pd->rmfp_command(KEY_COMMAND_SWITCH_SUBS, pid, true, NULL, 0);
|
||||
pd->subpid = pid;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cPlayback::SetSpeed(int speed)
|
||||
{
|
||||
lt_info("%s: playing %d speed %d\n", __func__, playing, speed);
|
||||
lt_info("%s: playing %d speed %d\n", __func__, pd->playing, speed);
|
||||
|
||||
if (!playing)
|
||||
if (!pd->playing)
|
||||
return false;
|
||||
|
||||
playback_speed = speed;
|
||||
pd->speed = speed;
|
||||
|
||||
if (speed > 1 || speed < 0)
|
||||
rmfp_command(CUSTOM_COMMAND_TRICK_SEEK, speed, true, NULL, 0);
|
||||
pd->rmfp_command(CUSTOM_COMMAND_TRICK_SEEK, speed, true, NULL, 0);
|
||||
else if (speed == 0)
|
||||
rmfp_command(KEY_COMMAND_PAUSE, 0, false, NULL, 0);
|
||||
pd->rmfp_command(KEY_COMMAND_PAUSE, 0, false, NULL, 0);
|
||||
else
|
||||
rmfp_command(KEY_COMMAND_PLAY, 0, false, NULL, 0);
|
||||
pd->rmfp_command(KEY_COMMAND_PLAY, 0, false, NULL, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -378,22 +413,22 @@ bool cPlayback::GetSpeed(int &/*speed*/) const
|
||||
// in milliseconds
|
||||
bool cPlayback::GetPosition(int &position, int &duration)
|
||||
{
|
||||
lt_debug("%s: playing %d\n", __func__, playing);
|
||||
lt_debug("%s: playing %d\n", __func__, pd->playing);
|
||||
|
||||
if (eof_reached)
|
||||
if (pd->eof)
|
||||
{
|
||||
position = mduration;
|
||||
duration = mduration;
|
||||
position = pd->duration;
|
||||
duration = pd->duration;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!playing)
|
||||
if (!pd->playing)
|
||||
return false;
|
||||
|
||||
char buf[32];
|
||||
/* custom command 222 returns "12345\n1234\n",
|
||||
* first line is duration, second line is position */
|
||||
if (! rmfp_command(222, 0, false, buf, 32))
|
||||
if (! pd->rmfp_command(222, 0, false, buf, 32))
|
||||
return false;
|
||||
duration = atoi(buf);
|
||||
char *p = strchr(buf, '\n');
|
||||
@@ -404,11 +439,11 @@ bool cPlayback::GetPosition(int &position, int &duration)
|
||||
if (duration == 0)
|
||||
duration = position + 1000;
|
||||
|
||||
if (playMode == PLAYMODE_TS)
|
||||
if (pd->pmode == PLAYMODE_TS)
|
||||
{
|
||||
if (position > mduration)
|
||||
mduration = position + 1000;
|
||||
duration = mduration;
|
||||
if (position > pd->duration)
|
||||
pd->duration = position + 1000;
|
||||
duration = pd->duration;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
@@ -416,23 +451,23 @@ bool cPlayback::GetPosition(int &position, int &duration)
|
||||
|
||||
bool cPlayback::SetPosition(int position, bool absolute)
|
||||
{
|
||||
lt_info("%s: pos %d abs %d playing %d\n", __func__, position, absolute, playing);
|
||||
lt_info("%s: pos %d abs %d playing %d\n", __func__, position, absolute, pd->playing);
|
||||
|
||||
if (!playing)
|
||||
if (!pd->playing)
|
||||
return false;
|
||||
|
||||
int seconds = position / 1000;;
|
||||
|
||||
if (absolute)
|
||||
{
|
||||
rmfp_command(KEY_COMMAND_SEEK_TO_TIME, seconds, true, NULL, 0);
|
||||
pd->rmfp_command(KEY_COMMAND_SEEK_TO_TIME, seconds, true, NULL, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (position > 0)
|
||||
rmfp_command(CUSTOM_COMMAND_SEEK_RELATIVE_FWD, seconds, true, NULL, 0);
|
||||
pd->rmfp_command(CUSTOM_COMMAND_SEEK_RELATIVE_FWD, seconds, true, NULL, 0);
|
||||
else if (position < 0)
|
||||
rmfp_command(CUSTOM_COMMAND_SEEK_RELATIVE_BWD, seconds, true, NULL, 0);
|
||||
pd->rmfp_command(CUSTOM_COMMAND_SEEK_RELATIVE_BWD, seconds, true, NULL, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -440,7 +475,7 @@ void cPlayback::FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t
|
||||
{
|
||||
lt_info("%s\n", __func__);
|
||||
char buf[32];
|
||||
rmfp_command(CUSTOM_COMMAND_AUDIO_COUNT, 0, false, buf, 3);
|
||||
pd->rmfp_command(CUSTOM_COMMAND_AUDIO_COUNT, 0, false, buf, 3);
|
||||
unsigned int audio_count = atoi(buf);
|
||||
|
||||
*numpida = audio_count;
|
||||
@@ -451,7 +486,7 @@ void cPlayback::FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t
|
||||
char streamidstring[11];
|
||||
char audio_lang[21];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
rmfp_command(CUSTOM_COMMAND_GET_AUDIO_BY_ID, aid, true, buf, 32);
|
||||
pd->rmfp_command(CUSTOM_COMMAND_GET_AUDIO_BY_ID, aid, true, buf, 32);
|
||||
memcpy(streamidstring, buf, 10);
|
||||
streamidstring[10] = '\0';
|
||||
memcpy(audio_lang, buf + 10, 20);
|
||||
@@ -469,7 +504,7 @@ void cPlayback::FindAllSubs(uint16_t *spids, unsigned short *supported, uint16_t
|
||||
lt_info("%s\n", __func__);
|
||||
char buf[32];
|
||||
|
||||
rmfp_command(CUSTOM_COMMAND_SUBS_COUNT, 0, false, buf, 3);
|
||||
pd->rmfp_command(CUSTOM_COMMAND_SUBS_COUNT, 0, false, buf, 3);
|
||||
unsigned int spu_count = atoi(buf);
|
||||
*numpids = spu_count;
|
||||
|
||||
@@ -480,7 +515,7 @@ void cPlayback::FindAllSubs(uint16_t *spids, unsigned short *supported, uint16_t
|
||||
char streamidstring[11];
|
||||
char spu_lang[21];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
rmfp_command(CUSTOM_COMMAND_GET_SUB_BY_ID, sid, true, buf, 32);
|
||||
pd->rmfp_command(CUSTOM_COMMAND_GET_SUB_BY_ID, sid, true, buf, 32);
|
||||
memcpy(streamidstring, buf, 10);
|
||||
streamidstring[10] = '\0';
|
||||
memcpy(spu_lang, buf + 10, 20);
|
||||
@@ -504,18 +539,36 @@ void cPlayback::GetChapters(std::vector<int> &positions, std::vector<std::string
|
||||
titles.clear();
|
||||
}
|
||||
|
||||
|
||||
void cPlayback::GetTitles(std::vector<int> &playlists, std::vector<std::string> &titles, int ¤t)
|
||||
{
|
||||
playlists.clear();
|
||||
titles.clear();
|
||||
current = 0;
|
||||
}
|
||||
|
||||
void cPlayback::SetTitle(int /*title*/)
|
||||
{
|
||||
}
|
||||
|
||||
void cPlayback::RequestAbort(void)
|
||||
{
|
||||
}
|
||||
|
||||
uint64_t cPlayback::GetReadCount(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
cPlayback::cPlayback(int /*num*/)
|
||||
{
|
||||
lt_info("%s: constructor\n", __func__);
|
||||
playing = 0;
|
||||
thread_started = false;
|
||||
eof_reached = false;
|
||||
open_success = false;
|
||||
pthread_mutex_init(&rmfp_cmd_mutex, NULL);
|
||||
pd = new PBPrivate();
|
||||
}
|
||||
|
||||
cPlayback::~cPlayback()
|
||||
{
|
||||
lt_info("%s\n", __func__);
|
||||
pthread_mutex_destroy(&rmfp_cmd_mutex);
|
||||
delete pd;
|
||||
pd = NULL;
|
||||
}
|
||||
|
@@ -1,62 +0,0 @@
|
||||
#ifndef __PLAYBACK_H
|
||||
#define __PLAYBACK_H
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
typedef enum {
|
||||
PLAYMODE_TS = 0,
|
||||
PLAYMODE_FILE,
|
||||
} playmode_t;
|
||||
|
||||
class cPlayback
|
||||
{
|
||||
private:
|
||||
pthread_mutex_t rmfp_cmd_mutex;
|
||||
int playing;
|
||||
bool eof_reached;
|
||||
int playback_speed;
|
||||
playmode_t playMode;
|
||||
bool open_success;
|
||||
uint16_t apid;
|
||||
uint16_t subpid;
|
||||
char *mfilename;
|
||||
int mduration;
|
||||
pthread_t thread;
|
||||
bool thread_started;
|
||||
/* private functions */
|
||||
bool rmfp_command(int cmd, int param, bool has_param, char *buf, int buflen);
|
||||
public:
|
||||
cPlayback(int num = 0);
|
||||
~cPlayback();
|
||||
|
||||
void run_rmfp();
|
||||
|
||||
bool Open(playmode_t PlayMode);
|
||||
void Close(void);
|
||||
bool Start(char *filename, unsigned short vpid, int vtype, unsigned short apid,
|
||||
int ac3, unsigned int duration);
|
||||
bool SetAPid(unsigned short pid, int ac3);
|
||||
bool SetSpeed(int speed);
|
||||
bool GetSpeed(int &speed) const;
|
||||
bool GetPosition(int &position, int &duration); /* pos: current time in ms, dur: file length in ms */
|
||||
bool SetPosition(int position, bool absolute = false); /* position: jump in ms */
|
||||
void FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t *numpida, std::string *language);
|
||||
void FindAllSubs(uint16_t *pids, unsigned short *supported, uint16_t *numpida, std::string *language);
|
||||
bool SelectSubtitles(int pid);
|
||||
void GetChapters(std::vector<int> &positions, std::vector<std::string> &titles);
|
||||
#if 0
|
||||
// Functions that are not used by movieplayer.cpp:
|
||||
bool Stop(void);
|
||||
bool GetOffset(off64_t &offset);
|
||||
bool IsPlaying(void) const { return playing; }
|
||||
bool IsEnabled(void) const { return enabled; }
|
||||
void * GetHandle(void);
|
||||
void * GetDmHandle(void);
|
||||
int GetCurrPlaybackSpeed(void) const { return nPlaybackSpeed; }
|
||||
void PlaybackNotify (int Event, void *pData, void *pTag);
|
||||
void DMNotify(int Event, void *pTsBuf, void *Tag);
|
||||
#endif
|
||||
};
|
||||
#endif
|
@@ -1 +0,0 @@
|
||||
../libspark/pwrmngr.cpp
|
@@ -1 +0,0 @@
|
||||
../libspark/pwrmngr.h
|
@@ -1 +0,0 @@
|
||||
../libspark/record_lib.h
|
110
azbox/video.cpp
110
azbox/video.cpp
@@ -37,7 +37,9 @@
|
||||
|
||||
#include <proc_tools.h>
|
||||
|
||||
#include "video_lib.h"
|
||||
#include "video_hal.h"
|
||||
#include "video_priv.h"
|
||||
|
||||
#define VIDEO_DEVICE "/dev/dvb/adapter0/video0"
|
||||
#include "lt_debug.h"
|
||||
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, this, args)
|
||||
@@ -75,12 +77,22 @@ static void show_iframe(int fd, unsigned char *iframe, size_t st_size);
|
||||
#define VIDEO_STREAMTYPE_MPEG1 6
|
||||
|
||||
cVideo::cVideo(int, void *, void *, unsigned int)
|
||||
{
|
||||
vdec = new VDec();
|
||||
}
|
||||
|
||||
cVideo::~cVideo(void)
|
||||
{
|
||||
delete vdec;
|
||||
vdec = NULL;
|
||||
}
|
||||
|
||||
VDec::VDec(void)
|
||||
{
|
||||
lt_debug("%s\n", __FUNCTION__);
|
||||
|
||||
//croppingMode = VID_DISPMODE_NORM;
|
||||
//outputformat = VID_OUTFMT_RGBC_SVIDEO;
|
||||
scartvoltage = -1;
|
||||
video_standby = 0;
|
||||
fd = -1;
|
||||
|
||||
@@ -111,17 +123,17 @@ cVideo::cVideo(int, void *, void *, unsigned int)
|
||||
close(blankfd);
|
||||
}
|
||||
openDevice();
|
||||
Pig(-1, -1, -1, -1);
|
||||
Pig(-1, -1, -1, -1, 1, 1);
|
||||
}
|
||||
|
||||
cVideo::~cVideo(void)
|
||||
VDec::~VDec(void)
|
||||
{
|
||||
closeDevice();
|
||||
if (blank_data)
|
||||
free(blank_data);
|
||||
}
|
||||
|
||||
void cVideo::openDevice(void)
|
||||
void VDec::openDevice(void)
|
||||
{
|
||||
int n = 0;
|
||||
lt_debug("%s\n", __func__);
|
||||
@@ -143,7 +155,7 @@ retry:
|
||||
playstate = VIDEO_STOPPED;
|
||||
}
|
||||
|
||||
void cVideo::closeDevice(void)
|
||||
void VDec::closeDevice(void)
|
||||
{
|
||||
lt_debug("%s\n", __func__);
|
||||
if (fd >= 0)
|
||||
@@ -181,6 +193,11 @@ int cVideo::setAspectRatio(int aspect, int mode)
|
||||
}
|
||||
|
||||
int cVideo::getAspectRatio(void)
|
||||
{
|
||||
return vdec->getAspectRatio();
|
||||
}
|
||||
|
||||
int VDec::getAspectRatio(void)
|
||||
{
|
||||
video_size_t s;
|
||||
if (fd == -1)
|
||||
@@ -198,7 +215,7 @@ int cVideo::getAspectRatio(void)
|
||||
return s.aspect_ratio * 2 + 1;
|
||||
}
|
||||
|
||||
int cVideo::setCroppingMode(int /*vidDispMode_t format*/)
|
||||
int cVideo::setCroppingMode(void)
|
||||
{
|
||||
return 0;
|
||||
#if 0
|
||||
@@ -215,6 +232,16 @@ int cVideo::setCroppingMode(int /*vidDispMode_t format*/)
|
||||
}
|
||||
|
||||
int cVideo::Start(void * /*PcrChannel*/, unsigned short /*PcrPid*/, unsigned short /*VideoPid*/, void * /*hChannel*/)
|
||||
{
|
||||
return vdec->Start();
|
||||
}
|
||||
|
||||
int cVideo::Stop(bool blank)
|
||||
{
|
||||
return vdec->Stop(blank);
|
||||
}
|
||||
|
||||
int VDec::Start(void)
|
||||
{
|
||||
lt_debug("%s playstate=%d\n", __FUNCTION__, playstate);
|
||||
#if 0
|
||||
@@ -227,7 +254,7 @@ int cVideo::Start(void * /*PcrChannel*/, unsigned short /*PcrPid*/, unsigned sho
|
||||
return fop(ioctl, VIDEO_PLAY);
|
||||
}
|
||||
|
||||
int cVideo::Stop(bool blank)
|
||||
int VDec::Stop(bool blank)
|
||||
{
|
||||
lt_debug("%s(%d)\n", __FUNCTION__, blank);
|
||||
if (stillpicture)
|
||||
@@ -242,7 +269,12 @@ int cVideo::Stop(bool blank)
|
||||
return fop(ioctl, VIDEO_STOP, blank ? 1 : 0);
|
||||
}
|
||||
|
||||
int cVideo::setBlank(int)
|
||||
int cVideo::setBlank(int b)
|
||||
{
|
||||
return vdec->setBlank(b);
|
||||
}
|
||||
|
||||
int VDec::setBlank(int)
|
||||
{
|
||||
pthread_mutex_lock(&stillp_mutex);
|
||||
if (blank_data)
|
||||
@@ -291,7 +323,7 @@ int cVideo::SetVideoSystem(int video_system, bool remember)
|
||||
|
||||
int cVideo::getPlayState(void)
|
||||
{
|
||||
return playstate;
|
||||
return vdec->playstate;
|
||||
}
|
||||
|
||||
void cVideo::SetVideoMode(analog_mode_t mode)
|
||||
@@ -319,8 +351,14 @@ void cVideo::SetVideoMode(analog_mode_t mode)
|
||||
proc_put("/proc/stb/avs/0/colorformat", m, strlen(m));
|
||||
}
|
||||
|
||||
void cVideo::ShowPicture(const char * fname)
|
||||
bool cVideo::ShowPicture(const char * fname)
|
||||
{
|
||||
return vdec->ShowPicture(fname);
|
||||
}
|
||||
|
||||
bool VDec::ShowPicture(const char * fname)
|
||||
{
|
||||
bool ret = false;
|
||||
lt_debug("%s(%s)\n", __func__, fname);
|
||||
char destname[512];
|
||||
char cmd[512];
|
||||
@@ -332,18 +370,18 @@ void cVideo::ShowPicture(const char * fname)
|
||||
{
|
||||
/* does not work and the driver does not seem to like it */
|
||||
lt_info("%s: video_standby == true\n", __func__);
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
if (fd < 0)
|
||||
{
|
||||
lt_info("%s: decoder not opened?\n", __func__);
|
||||
return;
|
||||
lt_info("%s: decoder not opened\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
strcpy(destname, "/var/cache");
|
||||
if (stat(fname, &st2))
|
||||
{
|
||||
lt_info("%s: could not stat %s (%m)\n", __func__, fname);
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
mkdir(destname, 0755);
|
||||
/* the cache filename is (example for /share/tuxbox/neutrino/icons/radiomode.jpg):
|
||||
@@ -393,19 +431,25 @@ void cVideo::ShowPicture(const char * fname)
|
||||
read(mfd, iframe, st.st_size);
|
||||
show_iframe(fd, iframe, st.st_size);
|
||||
free(iframe);
|
||||
ret = true;
|
||||
out:
|
||||
close(mfd);
|
||||
pthread_mutex_unlock(&stillp_mutex);
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cVideo::StopPicture()
|
||||
{
|
||||
lt_debug("%s\n", __func__);
|
||||
stillpicture = false;
|
||||
vdec->stillpicture = false;
|
||||
}
|
||||
|
||||
void cVideo::Standby(unsigned int bOn)
|
||||
{
|
||||
vdec->Standby(bOn);
|
||||
}
|
||||
|
||||
void VDec::Standby(unsigned int bOn)
|
||||
{
|
||||
lt_debug("%s(%d)\n", __func__, bOn);
|
||||
if (bOn)
|
||||
@@ -428,26 +472,12 @@ int cVideo::getBlank(void)
|
||||
return !ret;
|
||||
}
|
||||
|
||||
/* this function is regularly called, checks if video parameters
|
||||
changed and triggers appropriate actions */
|
||||
void cVideo::VideoParamWatchdog(void)
|
||||
void cVideo::Pig(int x, int y, int w, int h, int osd_w, int osd_h)
|
||||
{
|
||||
#if 0
|
||||
static unsigned int _v_info = (unsigned int) -1;
|
||||
unsigned int v_info;
|
||||
if (fd == -1)
|
||||
return;
|
||||
ioctl(fd, MPEG_VID_GET_V_INFO_RAW, &v_info);
|
||||
if (_v_info != v_info)
|
||||
{
|
||||
lt_debug("%s params changed. old: %08x new: %08x\n", __FUNCTION__, _v_info, v_info);
|
||||
setAspectRatio(-1, -1);
|
||||
}
|
||||
_v_info = v_info;
|
||||
#endif
|
||||
vdec->Pig(x, y, w, h, osd_w, osd_h);
|
||||
}
|
||||
|
||||
void cVideo::Pig(int x, int y, int w, int h, int osd_w, int osd_h)
|
||||
void VDec::Pig(int x, int y, int w, int h, int osd_w, int osd_h)
|
||||
{
|
||||
char buffer[64];
|
||||
int _x, _y, _w, _h;
|
||||
@@ -509,6 +539,11 @@ static inline int rate2csapi(int rate)
|
||||
}
|
||||
|
||||
void cVideo::getPictureInfo(int &width, int &height, int &rate)
|
||||
{
|
||||
vdec->getPictureInfo(width, height, rate);
|
||||
}
|
||||
|
||||
void VDec::getPictureInfo(int &width, int &height, int &rate)
|
||||
{
|
||||
video_size_t s;
|
||||
int r;
|
||||
@@ -554,6 +589,11 @@ void cVideo::SetSyncMode(AVSYNC_TYPE mode)
|
||||
};
|
||||
|
||||
int cVideo::SetStreamType(VIDEO_FORMAT type)
|
||||
{
|
||||
return vdec->SetStreamType(type);
|
||||
}
|
||||
|
||||
int VDec::SetStreamType(VIDEO_FORMAT type)
|
||||
{
|
||||
static const char *VF[] = {
|
||||
"VIDEO_FORMAT_MPEG2",
|
||||
@@ -585,7 +625,7 @@ int cVideo::SetStreamType(VIDEO_FORMAT type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t cVideo::GetPTS(void)
|
||||
int64_t VDec::GetPTS(void)
|
||||
{
|
||||
int64_t pts = 0;
|
||||
if (ioctl(fd, VIDEO_GET_PTS, &pts) < 0)
|
||||
|
@@ -1,196 +0,0 @@
|
||||
#ifndef _VIDEO_TD_H
|
||||
#define _VIDEO_TD_H
|
||||
|
||||
#include <linux/dvb/video.h>
|
||||
#include "../common/cs_types.h"
|
||||
#include "dmx_lib.h"
|
||||
|
||||
typedef enum {
|
||||
ANALOG_SD_RGB_CINCH = 0x00,
|
||||
ANALOG_SD_YPRPB_CINCH,
|
||||
ANALOG_HD_RGB_CINCH,
|
||||
ANALOG_HD_YPRPB_CINCH,
|
||||
ANALOG_SD_RGB_SCART = 0x10,
|
||||
ANALOG_SD_YPRPB_SCART,
|
||||
ANALOG_HD_RGB_SCART,
|
||||
ANALOG_HD_YPRPB_SCART,
|
||||
ANALOG_SCART_MASK = 0x10
|
||||
} analog_mode_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
VIDEO_FORMAT_MPEG2 = 0,
|
||||
VIDEO_FORMAT_MPEG4,
|
||||
VIDEO_FORMAT_VC1,
|
||||
VIDEO_FORMAT_JPEG,
|
||||
VIDEO_FORMAT_GIF,
|
||||
VIDEO_FORMAT_PNG
|
||||
} VIDEO_FORMAT;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_SD = 0,
|
||||
VIDEO_HD,
|
||||
VIDEO_120x60i,
|
||||
VIDEO_320x240i,
|
||||
VIDEO_1440x800i,
|
||||
VIDEO_360x288i
|
||||
} VIDEO_DEFINITION;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_FRAME_RATE_23_976 = 0,
|
||||
VIDEO_FRAME_RATE_24,
|
||||
VIDEO_FRAME_RATE_25,
|
||||
VIDEO_FRAME_RATE_29_97,
|
||||
VIDEO_FRAME_RATE_30,
|
||||
VIDEO_FRAME_RATE_50,
|
||||
VIDEO_FRAME_RATE_59_94,
|
||||
VIDEO_FRAME_RATE_60
|
||||
} VIDEO_FRAME_RATE;
|
||||
|
||||
typedef enum {
|
||||
DISPLAY_AR_1_1,
|
||||
DISPLAY_AR_4_3,
|
||||
DISPLAY_AR_14_9,
|
||||
DISPLAY_AR_16_9,
|
||||
DISPLAY_AR_20_9,
|
||||
DISPLAY_AR_RAW,
|
||||
} DISPLAY_AR;
|
||||
|
||||
typedef enum {
|
||||
DISPLAY_AR_MODE_PANSCAN = 0,
|
||||
DISPLAY_AR_MODE_LETTERBOX,
|
||||
DISPLAY_AR_MODE_NONE,
|
||||
DISPLAY_AR_MODE_PANSCAN2
|
||||
} DISPLAY_AR_MODE;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_DB_DR_NEITHER = 0,
|
||||
VIDEO_DB_ON,
|
||||
VIDEO_DB_DR_BOTH
|
||||
} VIDEO_DB_DR;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_PLAY_STILL = 0,
|
||||
VIDEO_PLAY_CLIP,
|
||||
VIDEO_PLAY_TRICK,
|
||||
VIDEO_PLAY_MOTION,
|
||||
VIDEO_PLAY_MOTION_NO_SYNC
|
||||
} VIDEO_PLAY_MODE;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_STD_NTSC,
|
||||
VIDEO_STD_SECAM,
|
||||
VIDEO_STD_PAL,
|
||||
VIDEO_STD_480P,
|
||||
VIDEO_STD_576P,
|
||||
VIDEO_STD_720P60,
|
||||
VIDEO_STD_1080I60,
|
||||
VIDEO_STD_720P50,
|
||||
VIDEO_STD_1080I50,
|
||||
VIDEO_STD_1080P30,
|
||||
VIDEO_STD_1080P24,
|
||||
VIDEO_STD_1080P25,
|
||||
VIDEO_STD_AUTO,
|
||||
VIDEO_STD_1080P50, /* SPARK only */
|
||||
VIDEO_STD_MAX
|
||||
} VIDEO_STD;
|
||||
|
||||
/* not used, for dummy functions */
|
||||
typedef enum {
|
||||
VIDEO_HDMI_CEC_MODE_OFF = 0,
|
||||
VIDEO_HDMI_CEC_MODE_TUNER,
|
||||
VIDEO_HDMI_CEC_MODE_RECORDER
|
||||
} VIDEO_HDMI_CEC_MODE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VIDEO_CONTROL_BRIGHTNESS = 0,
|
||||
VIDEO_CONTROL_CONTRAST,
|
||||
VIDEO_CONTROL_SATURATION,
|
||||
VIDEO_CONTROL_HUE,
|
||||
VIDEO_CONTROL_SHARPNESS,
|
||||
VIDEO_CONTROL_MAX = VIDEO_CONTROL_SHARPNESS
|
||||
} VIDEO_CONTROL;
|
||||
|
||||
|
||||
class cVideo
|
||||
{
|
||||
friend class cDemux;
|
||||
friend class cPlayback;
|
||||
private:
|
||||
/* video device */
|
||||
int fd;
|
||||
/* apparently we cannot query the driver's state
|
||||
=> remember it */
|
||||
video_play_state_t playstate;
|
||||
int /*vidDispMode_t*/ croppingMode;
|
||||
int /*vidOutFmt_t*/ outputformat;
|
||||
int scartvoltage;
|
||||
|
||||
VIDEO_FORMAT StreamType;
|
||||
VIDEO_DEFINITION VideoDefinition;
|
||||
DISPLAY_AR DisplayAR;
|
||||
VIDEO_PLAY_MODE SyncMode;
|
||||
DISPLAY_AR_MODE ARMode;
|
||||
VIDEO_DB_DR eDbDr;
|
||||
DISPLAY_AR PictureAR;
|
||||
VIDEO_FRAME_RATE FrameRate;
|
||||
int video_standby;
|
||||
int64_t GetPTS(void);
|
||||
|
||||
void openDevice(void);
|
||||
void closeDevice(void);
|
||||
public:
|
||||
/* constructor & destructor */
|
||||
cVideo(int mode, void *, void *, unsigned int unit = 0);
|
||||
~cVideo(void);
|
||||
|
||||
void * GetTVEnc() { return NULL; };
|
||||
void * GetTVEncSD() { return NULL; };
|
||||
|
||||
/* aspect ratio */
|
||||
int getAspectRatio(void);
|
||||
void getPictureInfo(int &width, int &height, int &rate);
|
||||
int setAspectRatio(int aspect, int mode);
|
||||
|
||||
/* cropping mode */
|
||||
int setCroppingMode(int x = 0 /*vidDispMode_t x = VID_DISPMODE_NORM*/);
|
||||
|
||||
/* get play state */
|
||||
int getPlayState(void);
|
||||
|
||||
/* blank on freeze */
|
||||
int getBlank(void);
|
||||
int setBlank(int enable);
|
||||
|
||||
/* change video play state. Parameters are all unused. */
|
||||
int Start(void *PcrChannel = NULL, unsigned short PcrPid = 0, unsigned short VideoPid = 0, void *x = NULL);
|
||||
int Stop(bool blank = true);
|
||||
bool Pause(void);
|
||||
|
||||
/* set video_system */
|
||||
int SetVideoSystem(int video_system, bool remember = true);
|
||||
int SetStreamType(VIDEO_FORMAT type);
|
||||
void SetSyncMode(AVSYNC_TYPE mode);
|
||||
bool SetCECMode(VIDEO_HDMI_CEC_MODE) { return true; };
|
||||
void SetCECAutoView(bool) { return; };
|
||||
void SetCECAutoStandby(bool) { return; };
|
||||
void ShowPicture(const char * fname);
|
||||
void StopPicture();
|
||||
void Standby(unsigned int bOn);
|
||||
void Pig(int x, int y, int w, int h, int osd_w = 1064, int osd_h = 600);
|
||||
void SetControl(int, int) { return; };
|
||||
void VideoParamWatchdog(void);
|
||||
void setContrast(int val);
|
||||
void SetVideoMode(analog_mode_t mode);
|
||||
void SetDBDR(int) { return; };
|
||||
void SetAudioHandle(void *) { return; };
|
||||
void SetAutoModes(int [VIDEO_STD_MAX]) { return; };
|
||||
int OpenVBI(int) { return 0; };
|
||||
int CloseVBI(void) { return 0; };
|
||||
int StartVBI(unsigned short) { return 0; };
|
||||
int StopVBI(void) { return 0; };
|
||||
void SetDemux(cDemux *dmx);
|
||||
};
|
||||
|
||||
#endif
|
60
azbox/video_priv.h
Normal file
60
azbox/video_priv.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* (C) 2010-2013 Stefan Seyfried
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* private video functions, to be used only inside libstb-hal
|
||||
*/
|
||||
|
||||
#ifndef __video_priv__
|
||||
#define __video_priv__
|
||||
|
||||
#include <video_hal.h>
|
||||
#include <linux/dvb/video.h>
|
||||
|
||||
class VDec
|
||||
{
|
||||
public:
|
||||
/* all public, used inside libstb-hal only anyways... */
|
||||
int fd; /* video device fd */
|
||||
/* apparently we cannot query the driver's state
|
||||
=> remember it */
|
||||
video_play_state_t playstate;
|
||||
int video_standby;
|
||||
bool stillpicture;
|
||||
|
||||
/* constructor & destructor */
|
||||
VDec(void);
|
||||
~VDec(void);
|
||||
|
||||
/* used directly by cVideo */
|
||||
int getAspectRatio(void);
|
||||
void getPictureInfo(int &width, int &height, int &rate);
|
||||
int Start(void);
|
||||
int Stop(bool blank = true);
|
||||
int setBlank(int blank);
|
||||
int SetStreamType(VIDEO_FORMAT type);
|
||||
void SetSyncMode(AVSYNC_TYPE mode);
|
||||
bool ShowPicture(const char * fname);
|
||||
void Standby(unsigned int bOn);
|
||||
void Pig(int x, int y, int w, int h, int osd_w, int osd_h);
|
||||
|
||||
/* used internally by dmx */
|
||||
int64_t GetPTS(void);
|
||||
/* used internally by playback */
|
||||
void openDevice(void);
|
||||
void closeDevice(void);
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,33 +1,13 @@
|
||||
noinst_LTLIBRARIES = libcommon.la
|
||||
|
||||
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
|
||||
AM_LDFLAGS = -lpthread
|
||||
|
||||
if BOXTYPE_DUCKBOX
|
||||
AM_CXXFLAGS += \
|
||||
-I $(top_srcdir)/include \
|
||||
-I $(top_srcdir)/libdvbci
|
||||
endif
|
||||
-I $(top_srcdir)/include
|
||||
|
||||
if BOXTYPE_ARMBOX
|
||||
AM_CXXFLAGS += \
|
||||
-I $(top_srcdir)/include \
|
||||
-I $(top_srcdir)/libdvbci
|
||||
endif
|
||||
|
||||
if BOXTYPE_DUCKBOX
|
||||
libcommon_la_SOURCES = \
|
||||
ca_ci.cpp
|
||||
else
|
||||
if BOXTYPE_ARMBOX
|
||||
libcommon_la_SOURCES = \
|
||||
ca_ci.cpp
|
||||
else
|
||||
libcommon_la_SOURCES = \
|
||||
ca.cpp
|
||||
endif
|
||||
endif
|
||||
|
||||
libcommon_la_SOURCES += \
|
||||
lt_debug.cpp \
|
||||
proc_tools.c
|
||||
ca.cpp \
|
||||
lt_debug.c \
|
||||
proc_tools.c \
|
||||
pwrmngr.cpp \
|
||||
version_hal.cpp
|
||||
|
1768
common/ca_ci.cpp
1768
common/ca_ci.cpp
File diff suppressed because it is too large
Load Diff
350
common/ca_ci.h
350
common/ca_ci.h
@@ -1,350 +0,0 @@
|
||||
#ifndef __CA_H_
|
||||
#define __CA_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <list>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#include "mmi.h"
|
||||
#include "cs_types.h"
|
||||
#include "cs_api.h"
|
||||
|
||||
/* constants taken from dvb-apps */
|
||||
#define T_SB 0x80 // sb primitive h<--m
|
||||
#define T_RCV 0x81 // receive primitive h-->m
|
||||
#define T_CREATE_T_C 0x82 // create transport connection primitive h-->m
|
||||
#define T_C_T_C_REPLY 0x83 // ctc reply primitive h<--m
|
||||
#define T_DELETE_T_C 0x84 // delete tc primitive h<->m
|
||||
#define T_D_T_C_REPLY 0x85 // dtc reply primitive h<->m
|
||||
#define T_REQUEST_T_C 0x86 // request transport connection primitive h<--m
|
||||
#define T_NEW_T_C 0x87 // new tc / reply to t_request primitive h-->m
|
||||
#define T_T_C_ERROR 0x77 // error creating tc primitive h-->m
|
||||
#define T_DATA_LAST 0xA0 // convey data from higher constructed h<->m
|
||||
#define T_DATA_MORE 0xA1 // convey data from higher constructed h<->m
|
||||
|
||||
/* max multi decrypt per ci-cam */
|
||||
#define CI_MAX_MULTI 5
|
||||
|
||||
enum CA_INIT_MASK {
|
||||
CA_INIT_SC = 1,
|
||||
CA_INIT_CI,
|
||||
CA_INIT_BOTH
|
||||
};
|
||||
|
||||
enum CA_SLOT_TYPE {
|
||||
CA_SLOT_TYPE_SMARTCARD,
|
||||
CA_SLOT_TYPE_CI,
|
||||
CA_SLOT_TYPE_ALL
|
||||
};
|
||||
|
||||
enum CA_MESSAGE_FLAGS {
|
||||
CA_MESSAGE_EMPTY = (1 << 0),
|
||||
CA_MESSAGE_HAS_PARAM1_DATA = (1 << 1), /// Free after use!
|
||||
CA_MESSAGE_HAS_PARAM1_INT = (1 << 2),
|
||||
CA_MESSAGE_HAS_PARAM1_PTR = (1 << 3),
|
||||
CA_MESSAGE_HAS_PARAM2_INT = (1 << 4),
|
||||
CA_MESSAGE_HAS_PARAM2_PTR = (1 << 5),
|
||||
CA_MESSAGE_HAS_PARAM2_DATA = (1 << 6),
|
||||
CA_MESSAGE_HAS_PARAM3_DATA = (1 << 7), /// Free after use!
|
||||
CA_MESSAGE_HAS_PARAM3_INT = (1 << 8),
|
||||
CA_MESSAGE_HAS_PARAM3_PTR = (1 << 9),
|
||||
CA_MESSAGE_HAS_PARAM4_INT = (1 << 10),
|
||||
CA_MESSAGE_HAS_PARAM4_PTR = (1 << 11),
|
||||
CA_MESSAGE_HAS_PARAM4_DATA = (1 << 12),
|
||||
CA_MESSAGE_HAS_PARAM5_INT = (1 << 13),
|
||||
CA_MESSAGE_HAS_PARAM5_PTR = (1 << 14),
|
||||
CA_MESSAGE_HAS_PARAM5_DATA = (1 << 15),
|
||||
CA_MESSAGE_HAS_PARAM6_INT = (1 << 16),
|
||||
CA_MESSAGE_HAS_PARAM6_PTR = (1 << 17),
|
||||
CA_MESSAGE_HAS_PARAM6_DATA = (1 << 18),
|
||||
CA_MESSAGE_HAS_PARAM1_LONG = (1 << 19),
|
||||
CA_MESSAGE_HAS_PARAM2_LONG = (1 << 20),
|
||||
CA_MESSAGE_HAS_PARAM3_LONG = (1 << 21),
|
||||
CA_MESSAGE_HAS_PARAM4_LONG = (1 << 22)
|
||||
};
|
||||
|
||||
enum CA_MESSAGE_MSGID {
|
||||
CA_MESSAGE_MSG_INSERTED,
|
||||
CA_MESSAGE_MSG_REMOVED,
|
||||
CA_MESSAGE_MSG_INIT_OK,
|
||||
CA_MESSAGE_MSG_INIT_FAILED,
|
||||
CA_MESSAGE_MSG_MMI_MENU,
|
||||
CA_MESSAGE_MSG_MMI_MENU_ENTER,
|
||||
CA_MESSAGE_MSG_MMI_MENU_ANSWER,
|
||||
CA_MESSAGE_MSG_MMI_LIST,
|
||||
CA_MESSAGE_MSG_MMI_TEXT,
|
||||
CA_MESSAGE_MSG_MMI_REQ_INPUT,
|
||||
CA_MESSAGE_MSG_MMI_CLOSE,
|
||||
CA_MESSAGE_MSG_INTERNAL,
|
||||
CA_MESSAGE_MSG_PMT_ARRIVED,
|
||||
CA_MESSAGE_MSG_CAPMT_ARRIVED,
|
||||
CA_MESSAGE_MSG_CAT_ARRIVED,
|
||||
CA_MESSAGE_MSG_ECM_ARRIVED,
|
||||
CA_MESSAGE_MSG_EMM_ARRIVED,
|
||||
CA_MESSAGE_MSG_CHANNEL_CHANGE,
|
||||
CA_MESSAGE_MSG_GUI_READY,
|
||||
CA_MESSAGE_MSG_EXIT
|
||||
};
|
||||
|
||||
typedef struct CA_MESSAGE {
|
||||
uint32_t MsgId;
|
||||
enum CA_SLOT_TYPE SlotType;
|
||||
int Slot;
|
||||
uint32_t Flags;
|
||||
union {
|
||||
uint8_t *Data[4];
|
||||
uint32_t Param[4];
|
||||
void *Ptr[4];
|
||||
uint64_t ParamLong[4];
|
||||
} Msg;
|
||||
} CA_MESSAGE;
|
||||
|
||||
typedef std::set<int> ca_map_t;
|
||||
typedef ca_map_t::iterator ca_map_iterator_t;
|
||||
|
||||
typedef std::vector<u16> bSIDVector;
|
||||
|
||||
typedef std::vector<u16> CaIdVector;
|
||||
typedef std::vector<u16>::iterator CaIdVectorIterator;
|
||||
typedef std::vector<u16>::const_iterator CaIdVectorConstIterator;
|
||||
|
||||
#define CA_MESSAGE_SIZE sizeof(CA_MESSAGE)
|
||||
#define CA_MESSAGE_ENTRIES 256
|
||||
#define CA_MESSAGE_ENTRIES_CI 128
|
||||
#define CA_MESSAGE_ENTRIES_SC 64
|
||||
|
||||
#ifndef CS_CA_PDATA
|
||||
#define CS_CA_PDATA void
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
TUNER_A,
|
||||
TUNER_B,
|
||||
TUNER_C,
|
||||
TUNER_D
|
||||
} source_t;
|
||||
|
||||
typedef enum {
|
||||
eDataTimeout,
|
||||
eDataError,
|
||||
eDataReady,
|
||||
eDataWrite,
|
||||
eDataStatusChanged
|
||||
} eData;
|
||||
|
||||
typedef enum {
|
||||
eStatusNone,
|
||||
eStatusWait,
|
||||
eStatusReset
|
||||
} eStatus;
|
||||
|
||||
struct queueData
|
||||
{
|
||||
__u8 prio;
|
||||
unsigned char *data;
|
||||
unsigned int len;
|
||||
queueData(unsigned char *_data, unsigned int _len, __u8 _prio = 0)
|
||||
:prio(_prio), data(_data), len(_len)
|
||||
{
|
||||
|
||||
}
|
||||
bool operator < ( const struct queueData &a ) const
|
||||
{
|
||||
return prio < a.prio;
|
||||
}
|
||||
};
|
||||
|
||||
class eDVBCIMMISession;
|
||||
class eDVBCIApplicationManagerSession;
|
||||
class eDVBCICAManagerSession;
|
||||
class eDVBCIContentControlManagerSession;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
pthread_t slot_thread;
|
||||
unsigned int slot;
|
||||
int fd;
|
||||
int connection_id;
|
||||
eStatus status;
|
||||
|
||||
int receivedLen;
|
||||
unsigned char* receivedData;
|
||||
|
||||
void* pClass;
|
||||
|
||||
bool pollConnection;
|
||||
bool camIsReady;
|
||||
|
||||
eDVBCIMMISession* mmiSession;
|
||||
eDVBCIApplicationManagerSession* appSession;
|
||||
eDVBCICAManagerSession* camgrSession;
|
||||
eDVBCIContentControlManagerSession* ccmgrSession;
|
||||
|
||||
bool hasAppManager;
|
||||
bool hasMMIManager;
|
||||
bool hasCAManager;
|
||||
bool hasCCManager;
|
||||
bool hasDateTime;
|
||||
bool mmiOpened;
|
||||
bool init;
|
||||
|
||||
bool ccmgr_ready;
|
||||
|
||||
char ci_dev[32];
|
||||
char name[512];
|
||||
|
||||
bool newPids;
|
||||
bool newCapmt;
|
||||
bool multi;
|
||||
bool recordUse[CI_MAX_MULTI];
|
||||
bool liveUse[CI_MAX_MULTI];
|
||||
u16 SID[CI_MAX_MULTI];
|
||||
u64 TP;
|
||||
int ci_use_count;
|
||||
u32 pmtlen;
|
||||
u8 source;
|
||||
u8 camask;
|
||||
unsigned char pmtdata[1024 * 4];
|
||||
|
||||
int counter;
|
||||
CaIdVector cam_caids;
|
||||
std::priority_queue<queueData> sendqueue;
|
||||
|
||||
std::vector<u16> pids;
|
||||
|
||||
bSIDVector bsids;
|
||||
unsigned char lastKey[32];
|
||||
unsigned char scrambled;
|
||||
u8 lastParity;
|
||||
bool DataLast;
|
||||
bool DataRCV;
|
||||
bool SidBlackListed;
|
||||
/* private data */
|
||||
void *private_data;
|
||||
|
||||
} eDVBCISlot;
|
||||
|
||||
eData sendData(eDVBCISlot *slot, unsigned char* data, int len);
|
||||
|
||||
typedef std::list<eDVBCISlot*>::iterator SlotIt;
|
||||
|
||||
/// CA module class
|
||||
class cCA {
|
||||
private:
|
||||
/// Static instance of the CA module
|
||||
// static cCA *inst;
|
||||
/// Private constructor (singleton method)
|
||||
cCA(void);
|
||||
/// Private data for the CA module
|
||||
CS_CA_PDATA *privateData;
|
||||
/// set inputs with tuner letter in tsmux
|
||||
void setInputs();
|
||||
/// write ci info file to /tmp
|
||||
void write_ci_info(int slot, CaIdVector caids);
|
||||
/// delete ci info file
|
||||
void del_ci_info(int slot);
|
||||
/// extract audio / video pids from capmt
|
||||
void extractPids(eDVBCISlot* slot);
|
||||
/// ci module is detected
|
||||
void ci_inserted(eDVBCISlot* slot);
|
||||
/// ci module is removed
|
||||
void ci_removed(eDVBCISlot* slot);
|
||||
/// decode the tpdu tag
|
||||
void process_tpdu(eDVBCISlot* slot, unsigned char tpdu_tag, __u8* data, int asn_data_length, int con_id);
|
||||
/// set flag of running ci record to false
|
||||
bool StopRecordCI( u64 TP, u16 SID, u8 source, u32 calen);
|
||||
/// set flag of running ci live-tv to false
|
||||
bool StopLiveCI( u64 TP, u16 SID, u8 source, u32 calen);
|
||||
/// find an unused ci slot for use with service
|
||||
SlotIt FindFreeSlot(u64 tpid, u8 source, u16 sid, ca_map_t camap, u8 scrambled);
|
||||
/// get slot iterator by slot number
|
||||
SlotIt GetSlot(unsigned int slot);
|
||||
/// send buffered capmt to ci modul
|
||||
bool SendCaPMT(eDVBCISlot* slot);
|
||||
/// send a dummy capmt to ci for deactivating
|
||||
bool SendNullPMT(eDVBCISlot* slot);
|
||||
/// set ci source
|
||||
void setSource(eDVBCISlot* slot);
|
||||
/// set demux source
|
||||
void setInputSource(eDVBCISlot* slot, bool ci);
|
||||
/// check if data in queue
|
||||
bool checkQueueSize(eDVBCISlot* slot);
|
||||
enum CA_INIT_MASK initMask;
|
||||
int num_slots;
|
||||
bool init;
|
||||
void SendPMT();
|
||||
pthread_mutex_t ciMutex;
|
||||
std::list<eDVBCISlot*> slot_data;
|
||||
pthread_t slot_thread;
|
||||
|
||||
public:
|
||||
/// sh4 unused
|
||||
bool Init(void);
|
||||
/// init ci and start the loop
|
||||
cCA(int Slots);
|
||||
/// Returns the number of CI slots
|
||||
uint32_t GetNumberCISlots(void);
|
||||
/// Returns the number of Smartcard slots
|
||||
uint32_t GetNumberSmartCardSlots(void);
|
||||
/// Singleton
|
||||
static cCA *GetInstance(void);
|
||||
/// Send PMT to a individual or to all available modules (DEPRECATED)
|
||||
bool SendPMT(int Unit, unsigned char *Data, int Len, enum CA_SLOT_TYPE SlotType = CA_SLOT_TYPE_ALL);
|
||||
/// Sends a message to the CA thread
|
||||
bool SendMessage(const CA_MESSAGE *Msg);
|
||||
/// Sets which modules to initialize. It is only
|
||||
/// possible to change this once!
|
||||
/// sh4 unused
|
||||
void SetInitMask(enum CA_INIT_MASK InitMask);
|
||||
/// Sets the frequency (in Hz) of the TS stream input (only valid for CI)
|
||||
/// sh4 unused
|
||||
void SetTSClock(u32 Speed);
|
||||
/// Start the CA module
|
||||
/// sh4 unused
|
||||
bool Start(void);
|
||||
/// Stops the CA module
|
||||
/// sh4 unused
|
||||
void Stop(void);
|
||||
/// Notify that the GUI is ready to receive messages
|
||||
/// (CA messages coming from a module)
|
||||
/// sh4 unused
|
||||
void Ready(bool Set);
|
||||
/// Resets a module (if possible)
|
||||
/// sh4 unused
|
||||
void ModuleReset(enum CA_SLOT_TYPE, uint32_t Slot);
|
||||
/// Checks if a module is present
|
||||
bool ModulePresent(enum CA_SLOT_TYPE, uint32_t Slot);
|
||||
/// Returns the module name in array Name
|
||||
void ModuleName(enum CA_SLOT_TYPE, uint32_t Slot, char *Name);
|
||||
/// Notify the module we want to enter menu
|
||||
void MenuEnter(enum CA_SLOT_TYPE, uint32_t Slot);
|
||||
/// Notify the module with our answer (choice nr)
|
||||
void MenuAnswer(enum CA_SLOT_TYPE, uint32_t Slot, uint32_t choice);
|
||||
/// Notify the module with our answer (binary)
|
||||
void InputAnswer(enum CA_SLOT_TYPE, uint32_t Slot, uint8_t * Data, int Len);
|
||||
/// Notify the module we closed the menu
|
||||
void MenuClose(enum CA_SLOT_TYPE, uint32_t Slot);
|
||||
/// Get the supported CAIDs
|
||||
int GetCAIDS(CaIdVector &Caids);
|
||||
/// Send a CA-PMT object and Raw unparsed PMT to the CA layer
|
||||
bool SendCAPMT(u64 /*Source*/, u8 /*DemuxSource*/, u8 /*DemuxMask*/, const unsigned char * /*CAPMT*/, u32 /*CAPMTLen*/, const unsigned char * /*RawPMT*/, u32 /*RawPMTLen*/, enum CA_SLOT_TYPE SlotType = CA_SLOT_TYPE_ALL,
|
||||
unsigned char scrambled = 0, ca_map_t camap = std::set<int>(), int mode = 0, bool enabled = false);
|
||||
/// sh4 unused
|
||||
bool SendDateTime(void);
|
||||
/// the main loop
|
||||
void slot_pollthread(void *c);
|
||||
/// check if current channel uses any ci module
|
||||
bool checkChannelID(u64 chanID);
|
||||
/// set checking for live-tv use ci to true
|
||||
void setCheckLiveSlot(int check);
|
||||
/// as the name says
|
||||
bool CheckCerts(void);
|
||||
/// Virtual destructor
|
||||
virtual ~cCA();
|
||||
};
|
||||
|
||||
#endif ///__CA_H_
|
@@ -1 +0,0 @@
|
||||
../include/hardware_caps.h
|
@@ -21,10 +21,16 @@
|
||||
#define HAL_DEBUG_RECORD 7
|
||||
#define HAL_DEBUG_ALL ((1<<8)-1)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern int debuglevel;
|
||||
|
||||
void hal_set_threadname(const char *name);
|
||||
void _lt_debug(int facility, const void *, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
|
||||
void _lt_info(int facility, const void *, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
|
||||
void lt_debug_init(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@@ -1,8 +1,28 @@
|
||||
#include <stdio.h>
|
||||
#include <cstdlib>
|
||||
/*
|
||||
* (C) 2010-2013 Stefan Seyfried
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <config.h>
|
||||
|
||||
#include "pwrmngr.h"
|
||||
#include "lt_debug.h"
|
||||
|
||||
#if HAVE_TRIPLEDRAGON
|
||||
#include <stdio.h>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
@@ -11,32 +31,50 @@
|
||||
|
||||
#include <avs/avs_inf.h>
|
||||
#include <tdpanel/lcdstuff.h>
|
||||
#endif
|
||||
|
||||
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_PWRMNGR, this, args)
|
||||
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_PWRMNGR, this, args)
|
||||
void cCpuFreqManager::Up(void) { lt_debug("%s\n", __FUNCTION__); }
|
||||
void cCpuFreqManager::Down(void) { lt_debug("%s\n", __FUNCTION__); }
|
||||
void cCpuFreqManager::Reset(void) { lt_debug("%s\n", __FUNCTION__); }
|
||||
/* those function dummies return true or "harmless" values */
|
||||
bool cCpuFreqManager::SetDelta(unsigned long) { lt_debug("%s\n", __FUNCTION__); return true; }
|
||||
unsigned long cCpuFreqManager::GetCpuFreq(void) { lt_debug("%s\n", __FUNCTION__); return 0; }
|
||||
unsigned long cCpuFreqManager::GetDelta(void) { lt_debug("%s\n", __FUNCTION__); return 0; }
|
||||
//
|
||||
cCpuFreqManager::cCpuFreqManager(void) { lt_debug("%s\n", __FUNCTION__); }
|
||||
|
||||
bool cPowerManager::SetState(PWR_STATE) { lt_debug("%s\n", __FUNCTION__); return true; }
|
||||
|
||||
bool cPowerManager::Open(void) { lt_debug("%s\n", __FUNCTION__); return true; }
|
||||
void cPowerManager::Close(void) { lt_debug("%s\n", __FUNCTION__); }
|
||||
//
|
||||
bool cPowerManager::SetStandby(bool Active, bool Passive)
|
||||
/* cpufreqmanager */
|
||||
void cCpuFreqManager::Up(void)
|
||||
{
|
||||
lt_debug("%s(%d, %d)\n", __FUNCTION__, Active, Passive);
|
||||
lt_debug("%s\n", __func__);
|
||||
}
|
||||
|
||||
void cCpuFreqManager::Down(void)
|
||||
{
|
||||
lt_debug("%s\n", __func__);
|
||||
}
|
||||
|
||||
void cCpuFreqManager::Reset(void)
|
||||
{
|
||||
lt_debug("%s\n", __func__);
|
||||
}
|
||||
|
||||
/* those function dummies return true or "harmless" values */
|
||||
bool cCpuFreqManager::SetDelta(unsigned long)
|
||||
{
|
||||
lt_debug("%s\n", __func__);
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned long cCpuFreqManager::GetDelta(void)
|
||||
{
|
||||
lt_debug("%s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long cCpuFreqManager::GetCpuFreq(void)
|
||||
{
|
||||
lt_debug("%s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool cCpuFreqManager::SetCpuFreq(unsigned long f)
|
||||
{
|
||||
lt_info("%s(%lu) => set standby = %s\n", __func__, f, f?"true":"false");
|
||||
#if HAVE_TRIPLEDRAGON
|
||||
/* actually SetCpuFreq is used to determine if the system is in standby
|
||||
this is an "elegant" hack, because:
|
||||
* during a recording, cpu freq is kept "high", even if the box is sent to standby
|
||||
@@ -47,7 +85,6 @@ bool cCpuFreqManager::SetCpuFreq(unsigned long f)
|
||||
* f == 0 => max => not standby
|
||||
* f == 50000000 => min => standby
|
||||
*/
|
||||
lt_debug("%s(%lu) => set standby = %s\n", __FUNCTION__, f, f?"true":"false");
|
||||
int fd = open("/dev/stb/tdsystem", O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
@@ -78,10 +115,38 @@ bool cCpuFreqManager::SetCpuFreq(unsigned long f)
|
||||
}
|
||||
|
||||
close(fd);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
cPowerManager::cPowerManager(void) { lt_debug("%s\n", __FUNCTION__); }
|
||||
cPowerManager::~cPowerManager() { lt_debug("%s\n", __FUNCTION__); }
|
||||
cCpuFreqManager::cCpuFreqManager(void)
|
||||
{
|
||||
lt_debug("%s\n", __func__);
|
||||
}
|
||||
|
||||
/* powermanager */
|
||||
bool cPowerManager::Open(void)
|
||||
{
|
||||
lt_debug("%s\n", __func__);
|
||||
return true;
|
||||
}
|
||||
|
||||
void cPowerManager::Close(void)
|
||||
{
|
||||
lt_debug("%s\n", __func__);
|
||||
}
|
||||
bool cPowerManager::SetStandby(bool Active, bool Passive)
|
||||
{
|
||||
lt_debug("%s(%d, %d)\n", __func__, Active, Passive);
|
||||
return true;
|
||||
}
|
||||
|
||||
cPowerManager::cPowerManager(void)
|
||||
{
|
||||
lt_debug("%s\n", __func__);
|
||||
}
|
||||
|
||||
cPowerManager::~cPowerManager()
|
||||
{
|
||||
lt_debug("%s\n", __func__);
|
||||
}
|
51
common/version_hal.cpp
Normal file
51
common/version_hal.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* (C) 2018 Thilo Graf
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <libstb-hal-config.h>
|
||||
|
||||
#include <version_hal.h>
|
||||
|
||||
|
||||
void hal_get_lib_version(hal_libversion_t *ver)
|
||||
{
|
||||
if (!ver)
|
||||
return;
|
||||
|
||||
//init struct
|
||||
*ver = {"",0,0,0,"","",""};
|
||||
|
||||
#ifdef VERSION
|
||||
ver->vVersion = VERSION;
|
||||
#endif
|
||||
#ifdef PACKAGE_VERSION_MAJOR
|
||||
ver->vMajor = PACKAGE_VERSION_MAJOR;
|
||||
#endif
|
||||
#ifdef PACKAGE_VERSION_MAJOR
|
||||
ver->vMinor = PACKAGE_VERSION_MINOR;
|
||||
#endif
|
||||
#ifdef PACKAGE_VERSION_MINOR
|
||||
ver->vPatch = PACKAGE_VERSION_MICRO;
|
||||
#endif
|
||||
#ifdef PACKAGE_NAME
|
||||
ver->vName = PACKAGE_NAME;
|
||||
#endif
|
||||
#ifdef PACKAGE_STRING
|
||||
ver->vStr = PACKAGE_STRING;
|
||||
#endif
|
||||
#ifdef PACKAGE_VERSION_GIT
|
||||
ver->vGitDescribe = PACKAGE_VERSION_GIT;
|
||||
#endif
|
||||
}
|
101
configure.ac
101
configure.ac
@@ -1,9 +1,28 @@
|
||||
AC_INIT([libstb-hal], [1.0.1])
|
||||
# explicit defines for separate revision handling
|
||||
define(ver_major, 0)
|
||||
define(ver_minor, 2)
|
||||
define(ver_micro, 1)
|
||||
|
||||
# sync with current git
|
||||
define(ver_git, m4_esyscmd([
|
||||
GITBRANCH=$(git rev-parse --abbrev-ref HEAD);
|
||||
GITDESCRIBE=$(git describe --always --tags --dirty);
|
||||
printf "$GITDESCRIBE $GITBRANCH"
|
||||
]))
|
||||
|
||||
AC_PACKAGE_NAME, PACKAGE_NAME_LIBSTB_HAL
|
||||
AC_INIT([Tuxbox-libstb-hal], [ver_major.ver_minor.ver_micro])
|
||||
AM_INIT_AUTOMAKE
|
||||
AC_CONFIG_HEADERS([libstb-hal-config.h:config.h.in])
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_GNU_SOURCE
|
||||
|
||||
AC_DEFINE(PACKAGE_VERSION_MAJOR, ver_major, [Major version number])
|
||||
AC_DEFINE(PACKAGE_VERSION_MINOR, ver_minor, [Minor version number])
|
||||
AC_DEFINE(PACKAGE_VERSION_MICRO, ver_micro, [Micro version number])
|
||||
AC_DEFINE(PACKAGE_VERSION_GIT, "ver_git", [internal vcs version info])
|
||||
|
||||
TUXBOX_APPS
|
||||
TUXBOX_APPS_DIRECTORY
|
||||
TUXBOX_BOXTYPE
|
||||
@@ -20,60 +39,66 @@ AC_DISABLE_STATIC
|
||||
AC_SYS_LARGEFILE
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
AC_ARG_ENABLE(clutter,
|
||||
AS_HELP_STRING(--enable-clutter, use clutter instead of OpenGL),
|
||||
,[enable_clutter=no])
|
||||
|
||||
AM_CONDITIONAL(USE_CLUTTER,test "$enable_clutter" = "yes")
|
||||
AM_CONDITIONAL(USE_OPENGL,test "$enable_clutter" = "no")
|
||||
if test "$enable_clutter" = "yes"; then
|
||||
AC_DEFINE(USE_CLUTTER,1,[use clutter instead of opengl])
|
||||
else
|
||||
AC_DEFINE(USE_OPENGL,1,[use opengl instead of clutter])
|
||||
fi
|
||||
|
||||
if test x"$BOXTYPE" = x"tripledragon"; then
|
||||
PKG_CHECK_MODULES([DIRECTFB], [directfb])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(gstreamer_01,
|
||||
AS_HELP_STRING(--enable-gstreamer_01,use gstreamer 0.10 playback),
|
||||
,[enable_gstreamer_01=no])
|
||||
|
||||
AM_CONDITIONAL(ENABLE_GSTREAMER_01,test "$enable_gstreamer_01" = "yes")
|
||||
if test "$enable_gstreamer_01" = "yes"; then
|
||||
AC_DEFINE(ENABLE_GSTREAMER_01,1,[use gstreamer 0.10 playback])
|
||||
PKG_CHECK_MODULES([GSTREAMER], [gstreamer-0.10])
|
||||
PKG_CHECK_MODULES([GSTREAMER_INTERFACES], [gstinterfaces-0.10])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(gstreamer_10,
|
||||
AS_HELP_STRING(--enable-gstreamer_10,use gstreamer 1.0 playback),
|
||||
,[enable_gstreamer_10=no])
|
||||
|
||||
AM_CONDITIONAL(ENABLE_GSTREAMER_10,test "$enable_gstreamer_10" = "yes")
|
||||
if test "$enable_gstreamer_10" = "yes"; then
|
||||
AC_DEFINE(ENABLE_GSTREAMER_10,1,[use gstreamer 1.0 playback])
|
||||
PKG_CHECK_MODULES([GSTREAMER], [gstreamer-1.0])
|
||||
PKG_CHECK_MODULES([GSTREAMER_AUDIO], [gstreamer-audio-1.0])
|
||||
PKG_CHECK_MODULES([GSTREAMER_VIDEO], [gstreamer-video-1.0])
|
||||
fi
|
||||
|
||||
if test x$BOXTYPE = xarmbox ; then
|
||||
PKG_CHECK_MODULES([GSTREAMER], [gstreamer-1.0])
|
||||
PKG_CHECK_MODULES([GSTREAMER_AUDIO], [gstreamer-audio-1.0])
|
||||
PKG_CHECK_MODULES([GSTREAMER_VIDEO], [gstreamer-video-1.0])
|
||||
fi
|
||||
|
||||
if test x$BOXTYPE = xgeneric -a x$BOXMODEL != xraspi; then
|
||||
PKG_CHECK_MODULES([AVFORMAT], [libavformat >= 53.21.1])
|
||||
PKG_CHECK_MODULES([AVCODEC], [libavcodec >= 54.28.0])
|
||||
if test x$BOXTYPE = xgeneric; then
|
||||
if test x"$enable_clutter" = xyes; then
|
||||
PKG_CHECK_MODULES([CLUTTER], [clutter-1.0])
|
||||
fi
|
||||
if test x$BOXMODEL != xraspi; then
|
||||
PKG_CHECK_MODULES([AVFORMAT], [libavformat >= 53.21.1])
|
||||
PKG_CHECK_MODULES([AVCODEC], [libavcodec >= 54.28.0])
|
||||
# don't know which version is exactly needed here...
|
||||
PKG_CHECK_MODULES([SWSCALE], [libswscale])
|
||||
else
|
||||
# openmaxil are the broadcom userspace libs
|
||||
# my yocto (openembedded) layer has an openmaxil package built from userland git.
|
||||
# Use that if available. If not, just fall back to /opt/vc/...
|
||||
# can be overridden with OMX_CFLAGS= OMX_LIBS= variables...
|
||||
#
|
||||
PKG_CHECK_MODULES([OMX], [openmaxil], echo "OpenMAX/IL userspace package found. Good.",
|
||||
[ echo "OpenMAX/IL package not found, assuming /opt/vc/..."
|
||||
OMX_CFLAGS="-I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads/ -I/opt/vc/include/interface/vmcs_host/linux"
|
||||
OMX_LIBS="-L/opt/vc/lib/ -lopenmaxil -lbcm_host -lvcos -lvchiq_arm -pthread"
|
||||
])
|
||||
# raspbian has no current versions and only libav instead of ffmpeg... :-(
|
||||
PKG_CHECK_MODULES([AVFORMAT], [libavformat])
|
||||
PKG_CHECK_MODULES([AVCODEC], [libavcodec])
|
||||
fi
|
||||
PKG_CHECK_MODULES([SWRESAMPLE], [libswresample])
|
||||
# don't know which version is exactly needed here...
|
||||
PKG_CHECK_MODULES([AVUTIL], [libavutil])
|
||||
PKG_CHECK_MODULES([SWSCALE], [libswscale])
|
||||
fi
|
||||
if test x$BOXTYPE = xspark; then
|
||||
# versions are probably not correct :-(
|
||||
PKG_CHECK_MODULES([AVFORMAT], [libavformat >= 53.21.1])
|
||||
PKG_CHECK_MODULES([AVCODEC], [libavcodec >= 54.28.0])
|
||||
PKG_CHECK_MODULES([SWRESAMPLE], [libswresample])
|
||||
PKG_CHECK_MODULES([AVUTIL], [libavutil])
|
||||
fi
|
||||
|
||||
AC_OUTPUT([
|
||||
Makefile
|
||||
common/Makefile
|
||||
libeplayer3/Makefile
|
||||
libthread/Makefile
|
||||
azbox/Makefile
|
||||
generic-pc/Makefile
|
||||
libduckbox/Makefile
|
||||
libdvbci/Makefile
|
||||
libtriple/Makefile
|
||||
libspark/Makefile
|
||||
libarmbox/Makefile
|
||||
raspi/Makefile
|
||||
tools/Makefile
|
||||
])
|
||||
|
@@ -1,47 +1,41 @@
|
||||
noinst_LTLIBRARIES = libgeneric.la
|
||||
|
||||
AM_CPPFLAGS = -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
|
||||
AM_CPPFLAGS += -Wfatal-errors
|
||||
AM_CPPFLAGS += \
|
||||
-I$(top_srcdir)/common \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/common
|
||||
@AVUTIL_CFLAGS@ \
|
||||
@CLUTTER_CFLAGS@
|
||||
|
||||
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
|
||||
|
||||
AM_LDFLAGS = \
|
||||
-lglut -lGL -lGLU -lGLEW -lao \
|
||||
-lao \
|
||||
-lOpenThreads \
|
||||
@AVFORMAT_LIBS@ \
|
||||
@AVUTIL_LIBS@ \
|
||||
@AVCODEC_LIBS@ \
|
||||
@SWRESAMPLE_LIBS@ \
|
||||
@SWSCALE_LIBS@
|
||||
@SWSCALE_LIBS@ \
|
||||
@CLUTTER_LIBS@
|
||||
|
||||
if USE_OPENGL
|
||||
AM_LDFLAGS += -lglut -lGL -lGLU -lGLEW -lao
|
||||
endif
|
||||
|
||||
libgeneric_la_SOURCES = \
|
||||
hardware_caps.c \
|
||||
dmx.cpp \
|
||||
video.cpp \
|
||||
audio.cpp \
|
||||
glfb.cpp \
|
||||
init.cpp \
|
||||
pwrmngr.cpp \
|
||||
playback.cpp \
|
||||
record.cpp
|
||||
|
||||
if ENABLE_GSTREAMER_01
|
||||
libgeneric_la_SOURCES += \
|
||||
playback_gst_01.cpp
|
||||
AM_LDFLAGS += \
|
||||
-lgstreamer-0.10 \
|
||||
-lgstinterfaces-0.10
|
||||
else
|
||||
if ENABLE_GSTREAMER_10
|
||||
libgeneric_la_SOURCES += \
|
||||
playback_gst_10.cpp
|
||||
AM_LDFLAGS += \
|
||||
-lgstreamer-1.0 \
|
||||
-lgsttag-1.0 \
|
||||
-lgstmpegts-1.0
|
||||
else
|
||||
libgeneric_la_SOURCES += \
|
||||
playback.cpp
|
||||
if USE_CLUTTER
|
||||
libgeneric_la_SOURCES += clutterfb.cpp
|
||||
endif
|
||||
if USE_OPENGL
|
||||
libgeneric_la_SOURCES += glfb.cpp
|
||||
endif
|
||||
|
||||
|
@@ -22,54 +22,51 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "audio_lib.h"
|
||||
#include "dmx_lib.h"
|
||||
#include "audio_hal.h"
|
||||
#include "audio_priv.h"
|
||||
#include "dmx_hal.h"
|
||||
#include "lt_debug.h"
|
||||
|
||||
#define lt_debug(args...) _lt_debug(HAL_DEBUG_AUDIO, this, args)
|
||||
#define lt_info(args...) _lt_info(HAL_DEBUG_AUDIO, this, args)
|
||||
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/opt.h>
|
||||
#include <libavutil/samplefmt.h>
|
||||
#include <libswresample/swresample.h>
|
||||
#include <ao/ao.h>
|
||||
}
|
||||
/* ffmpeg buf 2k */
|
||||
#define INBUF_SIZE 0x0800
|
||||
/* my own buf 16k */
|
||||
#define DMX_BUF_SZ 0x4000
|
||||
|
||||
cAudio * audioDecoder = NULL;
|
||||
ADec *adec = NULL;
|
||||
|
||||
extern cDemux *audioDemux;
|
||||
static uint8_t *dmxbuf = NULL;
|
||||
static int bufpos;
|
||||
|
||||
extern bool HAL_nodec;
|
||||
|
||||
static cAudio *gThiz = NULL;
|
||||
|
||||
static ao_device *adevice = NULL;
|
||||
static ao_sample_format sformat;
|
||||
|
||||
static AVCodecContext *c= NULL;
|
||||
|
||||
cAudio::cAudio(void *, void *, void *)
|
||||
{
|
||||
adec = new ADec();
|
||||
}
|
||||
cAudio::~cAudio(void)
|
||||
{
|
||||
delete adec;
|
||||
}
|
||||
|
||||
ADec::ADec(void)
|
||||
{
|
||||
adevice = NULL;
|
||||
dmxbuf = NULL;
|
||||
bufpos = 0;
|
||||
c = NULL;
|
||||
thread_started = false;
|
||||
if (!HAL_nodec)
|
||||
dmxbuf = (uint8_t *)malloc(DMX_BUF_SZ);
|
||||
bufpos = 0;
|
||||
curr_pts = 0;
|
||||
gThiz = this;
|
||||
ao_initialize();
|
||||
}
|
||||
|
||||
cAudio::~cAudio(void)
|
||||
ADec::~ADec(void)
|
||||
{
|
||||
closeDevice();
|
||||
free(dmxbuf);
|
||||
if (adevice)
|
||||
ao_close(adevice);
|
||||
@@ -77,19 +74,19 @@ cAudio::~cAudio(void)
|
||||
ao_shutdown();
|
||||
}
|
||||
|
||||
void cAudio::openDevice(void)
|
||||
int cAudio::mute(void)
|
||||
{
|
||||
lt_debug("%s\n", __func__);
|
||||
return SetMute(true);
|
||||
}
|
||||
|
||||
void cAudio::closeDevice(void)
|
||||
int cAudio::unmute(void)
|
||||
{
|
||||
lt_debug("%s\n", __func__);
|
||||
return SetMute(false);
|
||||
}
|
||||
|
||||
int cAudio::do_mute(bool enable, bool remember)
|
||||
int cAudio::SetMute(bool enable)
|
||||
{
|
||||
lt_debug("%s(%d, %d)\n", __func__, enable, remember);
|
||||
lt_debug("%s(%d)\n", __func__, enable);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -100,21 +97,31 @@ int cAudio::setVolume(unsigned int left, unsigned int right)
|
||||
}
|
||||
|
||||
int cAudio::Start(void)
|
||||
{
|
||||
return adec->Start();
|
||||
}
|
||||
|
||||
int cAudio::Stop(void)
|
||||
{
|
||||
return adec->Stop();
|
||||
}
|
||||
|
||||
int ADec::Start(void)
|
||||
{
|
||||
lt_debug("%s >\n", __func__);
|
||||
if (! HAL_nodec)
|
||||
Thread::startThread();
|
||||
start();
|
||||
lt_debug("%s <\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cAudio::Stop(void)
|
||||
int ADec::Stop(void)
|
||||
{
|
||||
lt_debug("%s >\n", __func__);
|
||||
if (thread_started)
|
||||
{
|
||||
thread_started = false;
|
||||
Thread::joinThread();
|
||||
join();
|
||||
}
|
||||
lt_debug("%s <\n", __func__);
|
||||
return 0;
|
||||
@@ -141,6 +148,11 @@ int cAudio::setChannel(int /*channel*/)
|
||||
};
|
||||
|
||||
int cAudio::PrepareClipPlay(int ch, int srate, int bits, int le)
|
||||
{
|
||||
return adec->PrepareClipPlay(ch, srate, bits, le);
|
||||
}
|
||||
|
||||
int ADec::PrepareClipPlay(int ch, int srate, int bits, int le)
|
||||
{
|
||||
lt_debug("%s ch %d srate %d bits %d le %d adevice %p\n", __func__, ch, srate, bits, le, adevice);;
|
||||
int driver;
|
||||
@@ -167,6 +179,11 @@ int cAudio::PrepareClipPlay(int ch, int srate, int bits, int le)
|
||||
};
|
||||
|
||||
int cAudio::WriteClip(unsigned char *buffer, int size)
|
||||
{
|
||||
return adec->WriteClip(buffer, size);
|
||||
}
|
||||
|
||||
int ADec::WriteClip(unsigned char *buffer, int size)
|
||||
{
|
||||
lt_debug("cAudio::%s buf 0x%p size %d\n", __func__, buffer, size);
|
||||
if (!adevice) {
|
||||
@@ -194,14 +211,45 @@ int cAudio::StopClip()
|
||||
};
|
||||
|
||||
void cAudio::getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &mode)
|
||||
{
|
||||
adec->getAudioInfo(type, layer, freq, bitrate, mode);
|
||||
}
|
||||
|
||||
void ADec::getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &mode)
|
||||
{
|
||||
type = 0;
|
||||
layer = 0; /* not used */
|
||||
freq = 0;
|
||||
bitrate = 0; /* not used, but easy to get :-) */
|
||||
mode = 0; /* default: stereo */
|
||||
printf("cAudio::getAudioInfo c %p\n", c);
|
||||
if (c) {
|
||||
type = (c->codec_id != AV_CODEC_ID_MP2); /* only mpeg / not mpeg is indicated */
|
||||
switch (c->codec_id) {
|
||||
case AV_CODEC_ID_MP2:
|
||||
type = AUDIO_FMT_MPEG;
|
||||
break;
|
||||
case AV_CODEC_ID_MP3:
|
||||
type = AUDIO_FMT_MP3;
|
||||
break;
|
||||
case AV_CODEC_ID_AC3:
|
||||
case AV_CODEC_ID_TRUEHD:
|
||||
type = AUDIO_FMT_DOLBY_DIGITAL;
|
||||
break;
|
||||
case AV_CODEC_ID_EAC3:
|
||||
type = AUDIO_FMT_DD_PLUS;
|
||||
break;
|
||||
case AV_CODEC_ID_AAC:
|
||||
type = AUDIO_FMT_AAC;
|
||||
break;
|
||||
case AV_CODEC_ID_DTS:
|
||||
type = AUDIO_FMT_DTS;
|
||||
break;
|
||||
case AV_CODEC_ID_MLP:
|
||||
type = AUDIO_FMT_MLP;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
freq = c->sample_rate;
|
||||
bitrate = c->bit_rate;
|
||||
if (c->channels == 1)
|
||||
@@ -239,7 +287,7 @@ void cAudio::getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &m
|
||||
}
|
||||
}
|
||||
lt_debug("%s t: %d l: %d f: %d b: %d m: %d codec_id: %x\n",
|
||||
__func__, type, layer, freq, bitrate, mode, c->codec_id);
|
||||
__func__, type, layer, freq, bitrate, mode, c?c->codec_id:-1);
|
||||
};
|
||||
|
||||
void cAudio::SetSRS(int /*iq_enable*/, int /*nmgr_enable*/, int /*iq_mode*/, int /*iq_level*/)
|
||||
@@ -267,17 +315,12 @@ void cAudio::EnableAnalogOut(bool enable)
|
||||
lt_debug("%s %d\n", __func__, enable);
|
||||
};
|
||||
|
||||
void cAudio::setBypassMode(bool disable)
|
||||
{
|
||||
lt_debug("%s %d\n", __func__, disable);
|
||||
}
|
||||
|
||||
static int _my_read(void *, uint8_t *buf, int buf_size)
|
||||
{
|
||||
return gThiz->my_read(buf, buf_size);
|
||||
return adec->my_read(buf, buf_size);
|
||||
}
|
||||
|
||||
int cAudio::my_read(uint8_t *buf, int buf_size)
|
||||
int ADec::my_read(uint8_t *buf, int buf_size)
|
||||
{
|
||||
int tmp = 0;
|
||||
if (audioDecoder && bufpos < DMX_BUF_SZ - 4096) {
|
||||
@@ -304,7 +347,7 @@ int cAudio::my_read(uint8_t *buf, int buf_size)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void cAudio::run()
|
||||
void ADec::run()
|
||||
{
|
||||
lt_info("====================== start decoder thread ================================\n");
|
||||
/* libavcodec & friends */
|
||||
@@ -356,28 +399,31 @@ void cAudio::run()
|
||||
lt_info("%s: nb_streams: %d, should be 1!\n", __func__, avfc->nb_streams);
|
||||
goto out;
|
||||
}
|
||||
if (avfc->streams[0]->codec->codec_type != AVMEDIA_TYPE_AUDIO)
|
||||
lt_info("%s: stream 0 no audio codec? 0x%x\n", __func__, avfc->streams[0]->codec->codec_type);
|
||||
p = avfc->streams[0]->codecpar;
|
||||
if (p->codec_type != AVMEDIA_TYPE_AUDIO)
|
||||
lt_info("%s: stream 0 no audio codec? 0x%x\n", __func__, p->codec_type);
|
||||
|
||||
c = avfc->streams[0]->codec;
|
||||
codec = avcodec_find_decoder(c->codec_id);
|
||||
codec = avcodec_find_decoder(p->codec_id);
|
||||
if (!codec) {
|
||||
lt_info("%s: Codec for %s not found\n", __func__, avcodec_get_name(c->codec_id));
|
||||
lt_info("%s: Codec for %s not found\n", __func__, avcodec_get_name(p->codec_id));
|
||||
goto out;
|
||||
}
|
||||
if (c)
|
||||
av_free(c);
|
||||
c = avcodec_alloc_context3(codec);
|
||||
if (avcodec_open2(c, codec, NULL) < 0) {
|
||||
lt_info("%s: avcodec_open2() failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
frame = av_frame_alloc();
|
||||
if (!frame) {
|
||||
lt_info("%s: avcodec_alloc_frame failed\n", __func__);
|
||||
lt_info("%s: av_frame_alloc failed\n", __func__);
|
||||
goto out2;
|
||||
}
|
||||
/* output sample rate, channels, layout could be set here if necessary */
|
||||
o_ch = c->channels; /* 2 */
|
||||
o_sr = c->sample_rate; /* 48000 */
|
||||
o_layout = c->channel_layout; /* AV_CH_LAYOUT_STEREO */
|
||||
o_ch = p->channels; /* 2 */
|
||||
o_sr = p->sample_rate; /* 48000 */
|
||||
o_layout = p->channel_layout; /* AV_CH_LAYOUT_STEREO */
|
||||
if (sformat.channels != o_ch || sformat.rate != o_sr ||
|
||||
sformat.byte_format != AO_FMT_NATIVE || sformat.bits != 16 || adevice == NULL)
|
||||
{
|
||||
@@ -392,8 +438,9 @@ void cAudio::run()
|
||||
adevice = ao_open_live(driver, &sformat, NULL);
|
||||
ai = ao_driver_info(driver);
|
||||
lt_info("%s: changed params ch %d srate %d bits %d adevice %p\n",
|
||||
__func__, o_ch, o_sr, 16, adevice);;
|
||||
lt_info("libao driver: %d name '%s' short '%s' author '%s'\n",
|
||||
__func__, o_ch, o_sr, 16, adevice);
|
||||
if(ai)
|
||||
lt_info("libao driver: %d name '%s' short '%s' author '%s'\n",
|
||||
driver, ai->name, ai->short_name, ai->author);
|
||||
}
|
||||
#if 0
|
||||
@@ -404,10 +451,10 @@ void cAudio::run()
|
||||
#endif
|
||||
av_get_sample_fmt_string(tmp, sizeof(tmp), c->sample_fmt);
|
||||
lt_info("decoding %s, sample_fmt %d (%s) sample_rate %d channels %d\n",
|
||||
avcodec_get_name(c->codec_id), c->sample_fmt, tmp, c->sample_rate, c->channels);
|
||||
avcodec_get_name(p->codec_id), c->sample_fmt, tmp, p->sample_rate, p->channels);
|
||||
swr = swr_alloc_set_opts(swr,
|
||||
o_layout, AV_SAMPLE_FMT_S16, o_sr, /* output */
|
||||
c->channel_layout, c->sample_fmt, c->sample_rate, /* input */
|
||||
p->channel_layout, c->sample_fmt, p->sample_rate, /* input */
|
||||
0, NULL);
|
||||
if (! swr) {
|
||||
lt_info("could not alloc resample context\n");
|
||||
@@ -421,15 +468,15 @@ void cAudio::run()
|
||||
avcodec_decode_audio4(c, frame, &gotframe, &avpkt);
|
||||
if (gotframe && thread_started) {
|
||||
int out_linesize;
|
||||
obuf_sz = av_rescale_rnd(swr_get_delay(swr, c->sample_rate) +
|
||||
frame->nb_samples, o_sr, c->sample_rate, AV_ROUND_UP);
|
||||
obuf_sz = av_rescale_rnd(swr_get_delay(swr, p->sample_rate) +
|
||||
frame->nb_samples, o_sr, p->sample_rate, AV_ROUND_UP);
|
||||
if (obuf_sz > obuf_sz_max) {
|
||||
lt_info("obuf_sz: %d old: %d\n", obuf_sz, obuf_sz_max);
|
||||
av_free(obuf);
|
||||
if (av_samples_alloc(&obuf, &out_linesize, o_ch,
|
||||
frame->nb_samples, AV_SAMPLE_FMT_S16, 1) < 0) {
|
||||
lt_info("av_samples_alloc failed\n");
|
||||
av_free_packet(&avpkt);
|
||||
av_packet_unref(&avpkt);
|
||||
break; /* while (thread_started) */
|
||||
}
|
||||
obuf_sz_max = obuf_sz;
|
||||
@@ -442,7 +489,7 @@ void cAudio::run()
|
||||
obuf_sz, AV_SAMPLE_FMT_S16, 1);
|
||||
ao_play(adevice, (char *)obuf, o_buf_sz);
|
||||
}
|
||||
av_free_packet(&avpkt);
|
||||
av_packet_unref(&avpkt);
|
||||
}
|
||||
// ao_close(adevice); /* can take long :-( */
|
||||
av_free(obuf);
|
||||
@@ -451,6 +498,7 @@ void cAudio::run()
|
||||
av_frame_free(&frame);
|
||||
out2:
|
||||
avcodec_close(c);
|
||||
av_free(c);
|
||||
c = NULL;
|
||||
out:
|
||||
avformat_close_input(&avfc);
|
||||
|
@@ -1,105 +0,0 @@
|
||||
/* public header file */
|
||||
|
||||
#ifndef _AUDIO_LIB_H_
|
||||
#define _AUDIO_LIB_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <thread_abstraction.h>
|
||||
#include "../common/cs_types.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_SYNC_WITH_PTS,
|
||||
AUDIO_NO_SYNC,
|
||||
AUDIO_SYNC_AUDIO_MASTER
|
||||
} AUDIO_SYNC_MODE;
|
||||
|
||||
typedef enum {
|
||||
HDMI_ENCODED_OFF,
|
||||
HDMI_ENCODED_AUTO,
|
||||
HDMI_ENCODED_FORCED
|
||||
} HDMI_ENCODED_MODE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_FMT_AUTO = 0,
|
||||
AUDIO_FMT_MPEG,
|
||||
AUDIO_FMT_MP3,
|
||||
AUDIO_FMT_DOLBY_DIGITAL,
|
||||
AUDIO_FMT_BASIC = AUDIO_FMT_DOLBY_DIGITAL,
|
||||
AUDIO_FMT_AAC,
|
||||
AUDIO_FMT_AAC_PLUS,
|
||||
AUDIO_FMT_DD_PLUS,
|
||||
AUDIO_FMT_DTS,
|
||||
AUDIO_FMT_AVS,
|
||||
AUDIO_FMT_MLP,
|
||||
AUDIO_FMT_WMA,
|
||||
AUDIO_FMT_MPG1, // TD only. For Movieplayer / cPlayback
|
||||
AUDIO_FMT_ADVANCED = AUDIO_FMT_MLP
|
||||
} AUDIO_FORMAT;
|
||||
|
||||
class cAudio : public Thread
|
||||
{
|
||||
friend class cPlayback;
|
||||
private:
|
||||
int fd;
|
||||
bool Muted;
|
||||
|
||||
int clipfd; /* for pcm playback */
|
||||
int mixer_fd; /* if we are using the OSS mixer */
|
||||
int mixer_num; /* oss mixer to use, if any */
|
||||
|
||||
AUDIO_FORMAT StreamType;
|
||||
AUDIO_SYNC_MODE SyncMode;
|
||||
bool started;
|
||||
bool thread_started;
|
||||
|
||||
int volume;
|
||||
int64_t curr_pts;
|
||||
|
||||
void openDevice(void);
|
||||
void closeDevice(void);
|
||||
|
||||
int do_mute(bool enable, bool remember);
|
||||
void setBypassMode(bool disable);
|
||||
void run();
|
||||
public:
|
||||
/* construct & destruct */
|
||||
cAudio(void *, void *, void *);
|
||||
~cAudio(void);
|
||||
int64_t getPts() { return curr_pts; }
|
||||
|
||||
void *GetHandle() { return NULL; };
|
||||
/* shut up */
|
||||
int mute(bool remember = true) { return do_mute(true, remember); };
|
||||
int unmute(bool remember = true) { return do_mute(false, remember); };
|
||||
|
||||
/* volume, min = 0, max = 255 */
|
||||
int setVolume(unsigned int left, unsigned int right);
|
||||
int getVolume(void) { return volume;}
|
||||
bool getMuteStatus(void) { return Muted; };
|
||||
|
||||
/* start and stop audio */
|
||||
int Start(void);
|
||||
int Stop(void);
|
||||
bool Pause(bool Pcm = true);
|
||||
void SetStreamType(AUDIO_FORMAT type);
|
||||
void SetSyncMode(AVSYNC_TYPE Mode);
|
||||
|
||||
/* select channels */
|
||||
int setChannel(int channel);
|
||||
int PrepareClipPlay(int uNoOfChannels, int uSampleRate, int uBitsPerSample, int bLittleEndian);
|
||||
int WriteClip(unsigned char * buffer, int size);
|
||||
int StopClip();
|
||||
void getAudioInfo(int &type, int &layer, int& freq, int &bitrate, int &mode);
|
||||
void SetSRS(int iq_enable, int nmgr_enable, int iq_mode, int iq_level);
|
||||
bool IsHdmiDDSupported();
|
||||
void SetHdmiDD(bool enable);
|
||||
void SetSpdifDD(bool enable);
|
||||
void ScheduleMute(bool On);
|
||||
void EnableAnalogOut(bool enable);
|
||||
int my_read(uint8_t *buf, int buf_size);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
54
generic-pc/audio_priv.h
Normal file
54
generic-pc/audio_priv.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* (C) 2010-2013 Stefan Seyfried
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* private stuff for the audio decoder, only used inside libstb-hal
|
||||
*/
|
||||
|
||||
#include <OpenThreads/Thread>
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/opt.h>
|
||||
#include <libavutil/samplefmt.h>
|
||||
#include <libswresample/swresample.h>
|
||||
#include <ao/ao.h>
|
||||
}
|
||||
|
||||
class ADec : public OpenThreads::Thread
|
||||
{
|
||||
public:
|
||||
ADec();
|
||||
~ADec();
|
||||
int Start();
|
||||
int Stop();
|
||||
int PrepareClipPlay(int ch, int srate, int bits, int le);
|
||||
int WriteClip(unsigned char *buffer, int size);
|
||||
void getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &mode);
|
||||
int my_read(uint8_t *buf, int buf_size);
|
||||
int64_t getPts() { return curr_pts; };
|
||||
private:
|
||||
bool thread_started;
|
||||
int64_t curr_pts;
|
||||
void run();
|
||||
|
||||
ao_device *adevice;
|
||||
ao_sample_format sformat;
|
||||
uint8_t *dmxbuf;
|
||||
int bufpos;
|
||||
AVCodecContext *c;
|
||||
AVCodecParameters *p;
|
||||
};
|
||||
|
523
generic-pc/clutterfb.cpp
Normal file
523
generic-pc/clutterfb.cpp
Normal file
@@ -0,0 +1,523 @@
|
||||
/*
|
||||
Framebuffer implementation using clutter https://developer.gnome.org/clutter/
|
||||
Copyright (C) 2016 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
|
||||
|
||||
based on the openGL framebuffer implementation
|
||||
Copyright 2010 Carsten Juttner <carjay@gmx.net>
|
||||
Copyright 2012,2013 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
TODO: AV-Sync code is "experimental" at best
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <vector>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/input.h>
|
||||
#include "glfb_priv.h"
|
||||
#include "video_priv.h"
|
||||
#include "audio_priv.h"
|
||||
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
|
||||
#include "lt_debug.h"
|
||||
|
||||
#define lt_debug_c(args...) _lt_debug(HAL_DEBUG_INIT, NULL, args)
|
||||
#define lt_info_c(args...) _lt_info(HAL_DEBUG_INIT, NULL, args)
|
||||
#define lt_debug(args...) _lt_debug(HAL_DEBUG_INIT, this, args)
|
||||
#define lt_info(args...) _lt_info(HAL_DEBUG_INIT, this, args)
|
||||
|
||||
|
||||
extern VDec *vdec;
|
||||
extern ADec *adec;
|
||||
|
||||
/* the private class that does stuff only needed inside libstb-hal.
|
||||
* is used e.g. by cVideo... */
|
||||
GLFbPC *glfb_priv = NULL;
|
||||
|
||||
GLFramebuffer::GLFramebuffer(int x, int y)
|
||||
{
|
||||
Init();
|
||||
glfb_priv = new GLFbPC(x, y, osd_buf);
|
||||
si = glfb_priv->getScreenInfo();
|
||||
start();
|
||||
while (!glfb_priv->mInitDone)
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
GLFramebuffer::~GLFramebuffer()
|
||||
{
|
||||
glfb_priv->mShutDown = true;
|
||||
join();
|
||||
delete glfb_priv;
|
||||
glfb_priv = NULL;
|
||||
}
|
||||
|
||||
void GLFramebuffer::blit()
|
||||
{
|
||||
glfb_priv->blit();
|
||||
}
|
||||
|
||||
GLFbPC::GLFbPC(int x, int y, std::vector<unsigned char> &buf): mReInit(true), mShutDown(false), mInitDone(false)
|
||||
{
|
||||
osd_buf = &buf;
|
||||
mState.width = x;
|
||||
mState.height = y;
|
||||
mX = &_mX[0];
|
||||
mY = &_mY[0];
|
||||
*mX = x;
|
||||
*mY = y;
|
||||
av_reduce(&mOA.num, &mOA.den, x, y, INT_MAX);
|
||||
mVA = mOA; /* initial aspect ratios are from the FB resolution, those */
|
||||
_mVA = mVA; /* will be updated by the videoDecoder functions anyway */
|
||||
mVAchanged = true;
|
||||
mCrop = DISPLAY_AR_MODE_PANSCAN;
|
||||
zoom = 1.0;
|
||||
xscale = 1.0;
|
||||
const char *tmp = getenv("GLFB_FULLSCREEN");
|
||||
mFullscreen = !!(tmp);
|
||||
|
||||
mState.blit = true;
|
||||
last_apts = 0;
|
||||
|
||||
/* linux framebuffer compat mode */
|
||||
si.bits_per_pixel = 32;
|
||||
si.xres = mState.width;
|
||||
si.xres_virtual = si.xres;
|
||||
si.yres = mState.height;
|
||||
si.yres_virtual = si.yres;
|
||||
si.blue.length = 8;
|
||||
si.blue.offset = 0;
|
||||
si.green.length = 8;
|
||||
si.green.offset = 8;
|
||||
si.red.length = 8;
|
||||
si.red.offset = 16;
|
||||
si.transp.length = 8;
|
||||
si.transp.offset = 24;
|
||||
|
||||
unlink("/tmp/neutrino.input");
|
||||
mkfifo("/tmp/neutrino.input", 0600);
|
||||
input_fd = open("/tmp/neutrino.input", O_RDWR|O_CLOEXEC|O_NONBLOCK);
|
||||
if (input_fd < 0)
|
||||
lt_info("%s: could not open /tmp/neutrino.input FIFO: %m\n", __func__);
|
||||
initKeys();
|
||||
}
|
||||
|
||||
GLFbPC::~GLFbPC()
|
||||
{
|
||||
mShutDown = true;
|
||||
if (input_fd >= 0)
|
||||
close(input_fd);
|
||||
osd_buf->clear();
|
||||
}
|
||||
|
||||
void GLFbPC::initKeys()
|
||||
{
|
||||
/*
|
||||
Keep in sync with initKeys() in glfb.cpp
|
||||
*/
|
||||
|
||||
mKeyMap[CLUTTER_KEY_Up] = KEY_UP;
|
||||
mKeyMap[CLUTTER_KEY_Down] = KEY_DOWN;
|
||||
mKeyMap[CLUTTER_KEY_Left] = KEY_LEFT;
|
||||
mKeyMap[CLUTTER_KEY_Right] = KEY_RIGHT;
|
||||
|
||||
mKeyMap[CLUTTER_KEY_F1] = KEY_RED;
|
||||
mKeyMap[CLUTTER_KEY_F2] = KEY_GREEN;
|
||||
mKeyMap[CLUTTER_KEY_F3] = KEY_YELLOW;
|
||||
mKeyMap[CLUTTER_KEY_F4] = KEY_BLUE;
|
||||
|
||||
mKeyMap[CLUTTER_KEY_F5] = KEY_RECORD;
|
||||
mKeyMap[CLUTTER_KEY_F6] = KEY_PLAY;
|
||||
mKeyMap[CLUTTER_KEY_F7] = KEY_PAUSE;
|
||||
mKeyMap[CLUTTER_KEY_F8] = KEY_STOP;
|
||||
|
||||
mKeyMap[CLUTTER_KEY_F9] = KEY_FORWARD;
|
||||
mKeyMap[CLUTTER_KEY_F10] = KEY_REWIND;
|
||||
mKeyMap[CLUTTER_KEY_F11] = KEY_NEXT;
|
||||
mKeyMap[CLUTTER_KEY_F12] = KEY_PREVIOUS;
|
||||
|
||||
mKeyMap[CLUTTER_KEY_Page_Up] = KEY_PAGEUP;
|
||||
mKeyMap[CLUTTER_KEY_Page_Down] = KEY_PAGEDOWN;
|
||||
|
||||
mKeyMap[CLUTTER_KEY_Return] = KEY_OK;
|
||||
mKeyMap[CLUTTER_KEY_Escape] = KEY_EXIT;
|
||||
|
||||
mKeyMap['0'] = KEY_0;
|
||||
mKeyMap['1'] = KEY_1;
|
||||
mKeyMap['2'] = KEY_2;
|
||||
mKeyMap['3'] = KEY_3;
|
||||
mKeyMap['4'] = KEY_4;
|
||||
mKeyMap['5'] = KEY_5;
|
||||
mKeyMap['6'] = KEY_6;
|
||||
mKeyMap['7'] = KEY_7;
|
||||
mKeyMap['8'] = KEY_8;
|
||||
mKeyMap['9'] = KEY_9;
|
||||
|
||||
mKeyMap['+'] = KEY_VOLUMEUP;
|
||||
mKeyMap['-'] = KEY_VOLUMEDOWN;
|
||||
mKeyMap['.'] = KEY_MUTE;
|
||||
mKeyMap['a'] = KEY_AUDIO;
|
||||
mKeyMap['e'] = KEY_EPG;
|
||||
// ['f'] is reserved to toggle fullscreen;
|
||||
mKeyMap['g'] = KEY_GAMES;
|
||||
mKeyMap['h'] = KEY_HELP;
|
||||
mKeyMap['i'] = KEY_INFO;
|
||||
mKeyMap['m'] = KEY_MENU;
|
||||
mKeyMap['p'] = KEY_POWER;
|
||||
mKeyMap['r'] = KEY_RADIO;
|
||||
mKeyMap['s'] = KEY_SUBTITLE;
|
||||
mKeyMap['t'] = KEY_TV;
|
||||
mKeyMap['v'] = KEY_VIDEO;
|
||||
mKeyMap['z'] = KEY_SLEEP;
|
||||
|
||||
/* shift keys */
|
||||
mKeyMap['F'] = KEY_FAVORITES;
|
||||
mKeyMap['M'] = KEY_MODE;
|
||||
mKeyMap['S'] = KEY_SAT;
|
||||
mKeyMap['T'] = KEY_TEXT;
|
||||
mKeyMap['W'] = KEY_WWW;
|
||||
}
|
||||
|
||||
static ClutterActor *stage = NULL;
|
||||
static ClutterActor *fb_actor = NULL;
|
||||
static ClutterActor *vid_actor = NULL;
|
||||
static ClutterTimeline *tl = NULL;
|
||||
void GLFramebuffer::run()
|
||||
{
|
||||
int argc = 1;
|
||||
int x = glfb_priv->mState.width;
|
||||
int y = glfb_priv->mState.height;
|
||||
/* some dummy commandline for GLUT to be happy */
|
||||
char *a = (char *)"neutrino";
|
||||
char **argv = (char **)malloc(sizeof(char *) * 2);
|
||||
argv[0] = a;
|
||||
argv[1] = NULL;
|
||||
lt_info("GLFB: GL thread starting x %d y %d\n", x, y);
|
||||
if (clutter_init(&argc, &argv) != CLUTTER_INIT_SUCCESS) {
|
||||
lt_info("GLFB: error initializing clutter\n");
|
||||
return;
|
||||
}
|
||||
lt_info("GLFB: %s:%d\n", __func__, __LINE__);
|
||||
ClutterColor stage_color = { 0, 0, 0, 255 };
|
||||
stage = clutter_stage_new();
|
||||
clutter_actor_set_size(stage, x, y);
|
||||
clutter_actor_set_background_color(stage, &stage_color);
|
||||
clutter_actor_set_content_gravity(stage, CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT);
|
||||
//g_signal_connect(stage, "destroy", G_CALLBACK(clutter_main_quit), NULL);
|
||||
g_signal_connect(stage, "key-press-event", G_CALLBACK(GLFbPC::keyboardcb), (void *)1);
|
||||
g_signal_connect(stage, "key-release-event", G_CALLBACK(GLFbPC::keyboardcb), NULL);
|
||||
clutter_stage_set_user_resizable(CLUTTER_STAGE (stage), TRUE);
|
||||
clutter_actor_grab_key_focus(stage);
|
||||
clutter_actor_show(stage);
|
||||
|
||||
/* 32bit FB depth, *2 because tuxtxt uses a shadow buffer */
|
||||
int fbmem = x * y * 4 * 2;
|
||||
osd_buf.resize(fbmem);
|
||||
lt_info("GLFB: OSD buffer set to %d bytes at 0x%p\n", fbmem, osd_buf.data());
|
||||
|
||||
/* video plane is below FB plane, so it comes first */
|
||||
vid_actor = clutter_actor_new();
|
||||
ClutterContent *fb = clutter_image_new();
|
||||
/* osd_buf, because it starts up black */
|
||||
if (!clutter_image_set_data(CLUTTER_IMAGE(fb), osd_buf.data(), COGL_PIXEL_FORMAT_BGR_888, x, y, x*3, NULL)) {
|
||||
lt_info("GLFB::%s clutter_image_set_data failed? (vid)\n", __func__);
|
||||
_exit(1); /* life is hard */
|
||||
}
|
||||
clutter_actor_set_content(vid_actor, fb);
|
||||
g_object_unref(fb);
|
||||
clutter_actor_set_size(vid_actor, x, y);
|
||||
clutter_actor_set_position(vid_actor, 0, 0);
|
||||
clutter_actor_add_constraint(vid_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_WIDTH, 0));
|
||||
clutter_actor_add_constraint(vid_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_HEIGHT, 0));
|
||||
clutter_actor_add_constraint(vid_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_X, 0));
|
||||
clutter_actor_add_constraint(vid_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_Y, 0));
|
||||
clutter_actor_set_content_gravity(vid_actor, CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT);
|
||||
clutter_actor_set_pivot_point(vid_actor, 0.5, 0.5);
|
||||
clutter_actor_add_child(stage, vid_actor);
|
||||
clutter_actor_show(vid_actor);
|
||||
|
||||
fb_actor = clutter_actor_new();
|
||||
fb = clutter_image_new();
|
||||
if (!clutter_image_set_data(CLUTTER_IMAGE(fb), osd_buf.data(), COGL_PIXEL_FORMAT_BGRA_8888, x, y, x*4, NULL)) {
|
||||
lt_info("GLFB::%s clutter_image_set_data failed? (osd)\n", __func__);
|
||||
_exit(1); /* life is hard */
|
||||
}
|
||||
clutter_actor_set_content(fb_actor, fb);
|
||||
g_object_unref(fb);
|
||||
clutter_actor_set_size(fb_actor, x, y);
|
||||
clutter_actor_set_position(fb_actor, 0, 0);
|
||||
clutter_actor_add_constraint(fb_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_WIDTH, 0));
|
||||
clutter_actor_add_constraint(fb_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_HEIGHT, 0));
|
||||
clutter_actor_add_constraint(fb_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_X, 0));
|
||||
clutter_actor_add_constraint(fb_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_Y, 0));
|
||||
clutter_actor_set_content_gravity(fb_actor, CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT);
|
||||
clutter_actor_add_child(stage, fb_actor);
|
||||
clutter_actor_show(fb_actor);
|
||||
|
||||
glfb_priv->mInitDone = true; /* signal that setup is finished */
|
||||
tl = clutter_timeline_new(100);
|
||||
g_signal_connect(tl, "new-frame", G_CALLBACK(GLFbPC::rendercb), NULL);
|
||||
clutter_timeline_set_repeat_count(tl, -1);
|
||||
clutter_timeline_start(tl);
|
||||
clutter_main();
|
||||
g_object_unref(tl);
|
||||
free(argv);
|
||||
lt_info("GLFB: GL thread stopping\n");
|
||||
}
|
||||
|
||||
/* static */ void GLFbPC::rendercb()
|
||||
{
|
||||
glfb_priv->render();
|
||||
}
|
||||
|
||||
/* static */ bool GLFbPC::keyboardcb(ClutterActor * /*actor*/, ClutterEvent *event, gpointer user_data)
|
||||
{
|
||||
guint key = clutter_event_get_key_symbol (event);
|
||||
int keystate = user_data ? 1 : 0;
|
||||
lt_debug_c("GLFB::%s: 0x%x, %d\n", __func__, key, keystate);
|
||||
|
||||
struct input_event ev;
|
||||
if (key == 'f' && keystate)
|
||||
{
|
||||
lt_info_c("GLFB::%s: toggle fullscreen %s\n", __func__, glfb_priv->mFullscreen?"off":"on");
|
||||
glfb_priv->mFullscreen = !(glfb_priv->mFullscreen);
|
||||
glfb_priv->mReInit = true;
|
||||
return true;
|
||||
}
|
||||
std::map<int, int>::const_iterator i = glfb_priv->mKeyMap.find(key);
|
||||
if (i == glfb_priv->mKeyMap.end())
|
||||
return true;
|
||||
ev.code = i->second;
|
||||
ev.value = keystate; /* key own */
|
||||
ev.type = EV_KEY;
|
||||
gettimeofday(&ev.time, NULL);
|
||||
lt_debug_c("GLFB::%s: pushing 0x%x\n", __func__, ev.code);
|
||||
write(glfb_priv->input_fd, &ev, sizeof(ev));
|
||||
return true;
|
||||
}
|
||||
|
||||
int sleep_us = 30000;
|
||||
|
||||
void GLFbPC::render()
|
||||
{
|
||||
if(mShutDown)
|
||||
clutter_main_quit();
|
||||
|
||||
mReInitLock.lock();
|
||||
if (vdec && vdec->pig_changed)
|
||||
{
|
||||
mReInit = true;
|
||||
vdec->pig_changed = false;
|
||||
}
|
||||
if (mReInit)
|
||||
{
|
||||
int xoff = 0;
|
||||
int yoff = 0;
|
||||
mVAchanged = true;
|
||||
mReInit = false;
|
||||
#if 0
|
||||
mX = &_mX[mFullscreen];
|
||||
mY = &_mY[mFullscreen];
|
||||
#endif
|
||||
*mX = *mY * mOA.num / mOA.den;
|
||||
if (mFullscreen) {
|
||||
clutter_stage_set_fullscreen(CLUTTER_STAGE(stage), TRUE);
|
||||
clutter_actor_show(stage);
|
||||
clutter_stage_ensure_redraw(CLUTTER_STAGE(stage));
|
||||
} else {
|
||||
clutter_stage_set_fullscreen(CLUTTER_STAGE(stage), FALSE);
|
||||
// *mX = *mY * mOA.num / mOA.den;
|
||||
clutter_actor_set_size(stage, *mX, *mY);
|
||||
}
|
||||
lt_info("%s: reinit mX:%d mY:%d xoff:%d yoff:%d fs %d\n",
|
||||
__func__, *mX, *mY, xoff, yoff, mFullscreen);
|
||||
}
|
||||
mReInitLock.unlock();
|
||||
bltDisplayBuffer(); /* decoded video stream */
|
||||
if (mState.blit) {
|
||||
/* only blit manually after fb->blit(), this helps to find missed blit() calls */
|
||||
mState.blit = false;
|
||||
lt_debug("GLFB::%s blit!\n", __func__);
|
||||
bltOSDBuffer(); /* OSD */
|
||||
}
|
||||
|
||||
if (mVAchanged)
|
||||
{
|
||||
mVAchanged = false;
|
||||
zoom = 1.0;
|
||||
float xzoom = 1.0;
|
||||
//xscale = 1.0;
|
||||
int cmp = av_cmp_q(mVA, mOA);
|
||||
const AVRational a149 = { 14, 9 };
|
||||
switch (cmp) {
|
||||
default:
|
||||
case INT_MIN: /* invalid */
|
||||
case 0: /* identical */
|
||||
lt_debug("%s: mVA == mOA (or fullscreen mode :-)\n", __func__);
|
||||
break;
|
||||
case 1: /* mVA > mOA -- video is wider than display */
|
||||
lt_debug("%s: mVA > mOA\n", __func__);
|
||||
switch (mCrop) {
|
||||
case DISPLAY_AR_MODE_PANSCAN:
|
||||
zoom = av_q2d(mVA) / av_q2d(mOA);
|
||||
break;
|
||||
case DISPLAY_AR_MODE_LETTERBOX:
|
||||
break;
|
||||
case DISPLAY_AR_MODE_PANSCAN2:
|
||||
zoom = av_q2d(a149) / av_q2d(mOA);
|
||||
break;
|
||||
case DISPLAY_AR_MODE_NONE:
|
||||
xzoom = av_q2d(mOA) / av_q2d(mVA);
|
||||
zoom = av_q2d(mVA) / av_q2d(mOA);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case -1: /* mVA < mOA -- video is taller than display */
|
||||
lt_debug("%s: mVA < mOA\n", __func__);
|
||||
switch (mCrop) {
|
||||
case DISPLAY_AR_MODE_LETTERBOX:
|
||||
break;
|
||||
case DISPLAY_AR_MODE_PANSCAN2:
|
||||
if (av_cmp_q(a149, mOA) < 0) {
|
||||
zoom = av_q2d(mVA) * av_q2d(a149) / av_q2d(mOA);
|
||||
break;
|
||||
}
|
||||
/* fallthrough for output format 14:9 */
|
||||
case DISPLAY_AR_MODE_PANSCAN:
|
||||
zoom = av_q2d(mOA) / av_q2d(mVA);
|
||||
break;
|
||||
case DISPLAY_AR_MODE_NONE:
|
||||
xzoom = av_q2d(mOA) / av_q2d(mVA);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (vdec &&
|
||||
vdec->pig_x >= 0 && vdec->pig_y >= 0 &&
|
||||
vdec->pig_w > 0 && vdec->pig_h > 0) {
|
||||
int ox = mState.width - vdec->pig_w;
|
||||
int oy = mState.height - vdec->pig_h;
|
||||
float ppx = vdec->pig_x / (float) ox;
|
||||
float ppy = vdec->pig_y / (float) oy;
|
||||
zoom = zoom * (float)vdec->pig_w / mState.width;
|
||||
clutter_actor_set_pivot_point(vid_actor, ppx, ppy);
|
||||
} else {
|
||||
clutter_actor_set_pivot_point(vid_actor, 0.5, 0.5);
|
||||
}
|
||||
lt_debug("zoom: %f xscale: %f xzoom: %f\n", zoom, xscale,xzoom);
|
||||
clutter_actor_set_scale(vid_actor, xscale*zoom*xzoom, zoom);
|
||||
}
|
||||
clutter_timeline_stop(tl);
|
||||
clutter_timeline_set_delay(tl, sleep_us/1000);
|
||||
clutter_timeline_start(tl);
|
||||
}
|
||||
|
||||
void GLFbPC::bltOSDBuffer()
|
||||
{
|
||||
// lt_info("%s\n", __func__);
|
||||
int x = glfb_priv->mState.width;
|
||||
int y = glfb_priv->mState.height;
|
||||
ClutterContent *fb = clutter_image_new();
|
||||
if (!clutter_image_set_data(CLUTTER_IMAGE(fb), osd_buf->data(), COGL_PIXEL_FORMAT_BGRA_8888, x, y, x*4, NULL)) {
|
||||
lt_info("GLFB::%s clutter_image_set_data failed?\n", __func__);
|
||||
_exit(1); /* life is hard */
|
||||
}
|
||||
clutter_actor_set_content(fb_actor, fb);
|
||||
g_object_unref(fb);
|
||||
clutter_actor_show(fb_actor);
|
||||
}
|
||||
|
||||
void GLFbPC::bltDisplayBuffer()
|
||||
{
|
||||
// lt_info("GLFB::%s vdec: %p\n", __func__, vdec);
|
||||
if (!vdec) /* cannot start yet */
|
||||
return;
|
||||
static bool warn = true;
|
||||
VDec::SWFramebuffer *buf = vdec->getDecBuf();
|
||||
if (!buf) {
|
||||
if (warn)
|
||||
lt_info("GLFB::%s did not get a buffer...\n", __func__);
|
||||
warn = false;
|
||||
return;
|
||||
}
|
||||
warn = true;
|
||||
int w = buf->width(), h = buf->height();
|
||||
if (w == 0 || h == 0)
|
||||
return;
|
||||
|
||||
AVRational a = buf->AR();
|
||||
if (a.den != 0 && a.num != 0 && av_cmp_q(a, _mVA)) {
|
||||
_mVA = a;
|
||||
/* _mVA is the raw buffer's aspect, mVA is the real scaled output aspect */
|
||||
av_reduce(&mVA.num, &mVA.den, w * a.num, h * a.den, INT_MAX);
|
||||
// mVA.num: 16 mVA.den: 9 w: 720 h: 576
|
||||
// 16*576/720/9 = 1.42222
|
||||
xscale = (double)mVA.num*h/(double)mVA.den/w;
|
||||
mVAchanged = true;
|
||||
}
|
||||
|
||||
ClutterContent *fb = clutter_image_new();
|
||||
if (!clutter_image_set_data(CLUTTER_IMAGE(fb), &(*buf)[0], COGL_PIXEL_FORMAT_BGR_888, w, h, w*3, NULL)) {
|
||||
lt_info("GLFB::%s clutter_image_set_data failed?\n", __func__);
|
||||
_exit(1); /* life is hard */
|
||||
}
|
||||
clutter_actor_set_content(vid_actor, fb);
|
||||
g_object_unref(fb);
|
||||
clutter_actor_show(vid_actor);
|
||||
|
||||
/* "rate control" mechanism starts here...
|
||||
* this implementation is pretty naive and not working too well, but
|
||||
* better this than nothing... :-) */
|
||||
int64_t apts = 0;
|
||||
int64_t vpts = buf->pts();
|
||||
if (adec)
|
||||
apts = adec->getPts();
|
||||
if (apts != last_apts) {
|
||||
int rate, dummy1, dummy2;
|
||||
if (apts < vpts)
|
||||
sleep_us = (sleep_us * 2 + (vpts - apts)*10/9) / 3;
|
||||
else if (sleep_us > 1000)
|
||||
sleep_us -= 1000;
|
||||
last_apts = apts;
|
||||
vdec->getPictureInfo(dummy1, dummy2, rate);
|
||||
if (rate > 0)
|
||||
rate = 2000000 / rate; /* limit to half the frame rate */
|
||||
else
|
||||
rate = 50000; /* minimum 20 fps */
|
||||
if (sleep_us > rate)
|
||||
sleep_us = rate;
|
||||
else if (sleep_us < 1)
|
||||
sleep_us = 1;
|
||||
}
|
||||
lt_debug("vpts: 0x%" PRIx64 " apts: 0x%" PRIx64 " diff: %6.3f sleep_us %d buf %d\n",
|
||||
buf->pts(), apts, (buf->pts() - apts)/90000.0, sleep_us, vdec->buf_num);
|
||||
}
|
@@ -1 +0,0 @@
|
||||
../libspark/cs_api.h
|
@@ -32,26 +32,21 @@
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include "dmx_lib.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include "dmx_hal.h"
|
||||
#include "lt_debug.h"
|
||||
|
||||
/* needed for getSTC :-( */
|
||||
#include "video_lib.h"
|
||||
extern cVideo *videoDecoder;
|
||||
#include "video_priv.h"
|
||||
extern VDec *vdec;
|
||||
|
||||
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_DEMUX, this, args)
|
||||
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_DEMUX, this, args)
|
||||
#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_DEMUX, NULL, args)
|
||||
|
||||
#define dmx_err(_errfmt, _errstr, _revents) do { \
|
||||
uint16_t _pid = (uint16_t)-1; uint16_t _f = 0;\
|
||||
if (dmx_type == DMX_PSI_CHANNEL) { \
|
||||
_pid = s_flt.pid; _f = s_flt.filter.filter[0]; \
|
||||
} else { \
|
||||
_pid = p_flt.pid; \
|
||||
}; \
|
||||
lt_info("%s " _errfmt " fd:%d, ev:0x%x %s pid:0x%04hx flt:0x%02hx\n", \
|
||||
__func__, _errstr, fd, _revents, DMX_T[dmx_type], _pid, _f); \
|
||||
__func__, _errstr, fd, _revents, DMX_T[dmx_type], pid, flt); \
|
||||
} while(0);
|
||||
|
||||
cDemux *videoDemux = NULL;
|
||||
@@ -70,15 +65,12 @@ static const char *DMX_T[] = {
|
||||
};
|
||||
|
||||
/* map the device numbers. for now only demux0 is used */
|
||||
#define NUM_DEMUXDEV 1
|
||||
static const char *devname[NUM_DEMUXDEV] = {
|
||||
static const char *devname[] = {
|
||||
"/dev/dvb/adapter0/demux0",
|
||||
"/dev/dvb/adapter0/demux0",
|
||||
"/dev/dvb/adapter0/demux0"
|
||||
};
|
||||
|
||||
#define NUM_DEMUX 1
|
||||
static int dmx_source[NUM_DEMUX] = { 0 };
|
||||
static bool init[NUM_DEMUXDEV] = { false };
|
||||
|
||||
/* uuuugly */
|
||||
static int dmx_tp_count = 0;
|
||||
#define MAX_TS_COUNT 8
|
||||
@@ -95,9 +87,6 @@ cDemux::cDemux(int n)
|
||||
else
|
||||
num = n;
|
||||
fd = -1;
|
||||
measure = false;
|
||||
last_measure = 0;
|
||||
last_data = 0;
|
||||
}
|
||||
|
||||
cDemux::~cDemux()
|
||||
@@ -163,8 +152,6 @@ void cDemux::Close(void)
|
||||
ioctl(fd, DMX_STOP);
|
||||
close(fd);
|
||||
fd = -1;
|
||||
if (measure)
|
||||
return;
|
||||
if (dmx_type == DMX_TP_CHANNEL)
|
||||
{
|
||||
dmx_tp_count--;
|
||||
@@ -256,11 +243,13 @@ int cDemux::Read(unsigned char *buff, int len, int timeout)
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool cDemux::sectionFilter(unsigned short pid, const unsigned char * const filter,
|
||||
bool cDemux::sectionFilter(unsigned short _pid, const unsigned char * const filter,
|
||||
const unsigned char * const mask, int len, int timeout,
|
||||
const unsigned char * const negmask)
|
||||
{
|
||||
struct dmx_sct_filter_params s_flt;
|
||||
memset(&s_flt, 0, sizeof(s_flt));
|
||||
pid = _pid;
|
||||
|
||||
if (len > DMX_FILTER_SIZE)
|
||||
{
|
||||
@@ -269,6 +258,7 @@ bool cDemux::sectionFilter(unsigned short pid, const unsigned char * const filte
|
||||
}
|
||||
s_flt.pid = pid;
|
||||
s_flt.timeout = timeout;
|
||||
flt = filter[0];
|
||||
memcpy(s_flt.filter.filter, filter, len);
|
||||
memcpy(s_flt.filter.mask, mask, len);
|
||||
if (negmask != NULL)
|
||||
@@ -369,8 +359,11 @@ bool cDemux::sectionFilter(unsigned short pid, const unsigned char * const filte
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cDemux::pesFilter(const unsigned short pid)
|
||||
bool cDemux::pesFilter(const unsigned short _pid)
|
||||
{
|
||||
struct dmx_pes_filter_params p_flt;
|
||||
pid = _pid;
|
||||
flt = 0;
|
||||
/* allow PID 0 for web streaming e.g.
|
||||
* this check originally is from tuxbox cvs but I'm not sure
|
||||
* what it is good for...
|
||||
@@ -481,8 +474,8 @@ void cDemux::removePid(unsigned short Pid)
|
||||
void cDemux::getSTC(int64_t * STC)
|
||||
{
|
||||
int64_t pts = 0;
|
||||
if (videoDecoder)
|
||||
pts = videoDecoder->GetPTS();
|
||||
if (vdec)
|
||||
pts = vdec->GetPTS();
|
||||
*STC = pts;
|
||||
}
|
||||
|
||||
@@ -497,28 +490,12 @@ int cDemux::getUnit(void)
|
||||
|
||||
bool cDemux::SetSource(int unit, int source)
|
||||
{
|
||||
//lt_info_c("%s(%d, %d): not implemented yet\n", __func__, unit, source);
|
||||
//return true;
|
||||
if (unit >= NUM_DEMUX || unit < 0) {
|
||||
lt_info_c("%s: unit (%d) out of range, NUM_DEMUX %d\n", __func__, unit, NUM_DEMUX);
|
||||
return false;
|
||||
}
|
||||
lt_info_c("%s(%d, %d) => %d to %d\n", __func__, unit, source, dmx_source[unit], source);
|
||||
if (source < 0 || source >= NUM_DEMUXDEV)
|
||||
lt_info_c("%s(%d, %d) ERROR: source %d out of range!\n", __func__, unit, source, source);
|
||||
else
|
||||
dmx_source[unit] = source;
|
||||
lt_info_c("%s(%d, %d): not implemented yet\n", __func__, unit, source);
|
||||
return true;
|
||||
}
|
||||
|
||||
int cDemux::GetSource(int unit)
|
||||
{
|
||||
//lt_info_c("%s(%d): not implemented yet\n", __func__, unit);
|
||||
//return 0;
|
||||
if (unit >= NUM_DEMUX || unit < 0) {
|
||||
lt_info_c("%s: unit (%d) out of range, NUM_DEMUX %d\n", __func__, unit, NUM_DEMUX);
|
||||
return -1;
|
||||
}
|
||||
lt_info_c("%s(%d) => %d\n", __func__, unit, dmx_source[unit]);
|
||||
return dmx_source[unit];
|
||||
lt_info_c("%s(%d): not implemented yet\n", __func__, unit);
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1 +0,0 @@
|
||||
#include "dmx_lib.h"
|
@@ -1,70 +0,0 @@
|
||||
#ifndef __DEMUX_TD_H
|
||||
#define __DEMUX_TD_H
|
||||
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
#include <inttypes.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/dvb/dmx.h>
|
||||
#include "../common/cs_types.h"
|
||||
|
||||
#define MAX_DMX_UNITS 4
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DMX_INVALID = 0,
|
||||
DMX_VIDEO_CHANNEL = 1,
|
||||
DMX_AUDIO_CHANNEL,
|
||||
DMX_PES_CHANNEL,
|
||||
DMX_PSI_CHANNEL,
|
||||
DMX_PIP_CHANNEL,
|
||||
DMX_TP_CHANNEL,
|
||||
DMX_PCR_ONLY_CHANNEL
|
||||
} DMX_CHANNEL_TYPE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int fd;
|
||||
unsigned short pid;
|
||||
} pes_pids;
|
||||
|
||||
class cDemux
|
||||
{
|
||||
private:
|
||||
int num;
|
||||
int fd;
|
||||
int buffersize;
|
||||
bool measure;
|
||||
uint64_t last_measure, last_data;
|
||||
DMX_CHANNEL_TYPE dmx_type;
|
||||
std::vector<pes_pids> pesfds;
|
||||
struct dmx_sct_filter_params s_flt;
|
||||
struct dmx_pes_filter_params p_flt;
|
||||
public:
|
||||
|
||||
bool Open(DMX_CHANNEL_TYPE pes_type, void * x = NULL, int y = 0);
|
||||
void Close(void);
|
||||
bool Start(bool record = false);
|
||||
bool Stop(void);
|
||||
int Read(unsigned char *buff, int len, int Timeout = 0);
|
||||
bool sectionFilter(unsigned short pid, const unsigned char * const filter, const unsigned char * const mask, int len, int Timeout = 0, const unsigned char * const negmask = NULL);
|
||||
bool pesFilter(const unsigned short pid);
|
||||
void SetSyncMode(AVSYNC_TYPE mode);
|
||||
void * getBuffer();
|
||||
void * getChannel();
|
||||
DMX_CHANNEL_TYPE getChannelType(void) { return dmx_type; };
|
||||
bool addPid(unsigned short pid);
|
||||
void getSTC(int64_t * STC);
|
||||
int getUnit(void);
|
||||
static bool SetSource(int unit, int source);
|
||||
static int GetSource(int unit);
|
||||
// TD only functions
|
||||
int getFD(void) { return fd; }; /* needed by cPlayback class */
|
||||
void removePid(unsigned short Pid); /* needed by cRecord class */
|
||||
std::vector<pes_pids> getPesPids(void) { return pesfds; };
|
||||
//
|
||||
cDemux(int num = 0);
|
||||
~cDemux();
|
||||
};
|
||||
|
||||
#endif //__DEMUX_H
|
@@ -22,6 +22,7 @@
|
||||
TODO: AV-Sync code is "experimental" at best
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <vector>
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -37,10 +38,9 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/input.h>
|
||||
#include "glfb.h"
|
||||
#include <GL/glx.h>
|
||||
#include "video_lib.h"
|
||||
#include "audio_lib.h"
|
||||
#include "glfb_priv.h"
|
||||
#include "video_priv.h"
|
||||
#include "audio_priv.h"
|
||||
|
||||
#include "lt_debug.h"
|
||||
|
||||
@@ -50,13 +50,39 @@
|
||||
#define lt_info(args...) _lt_info(HAL_DEBUG_INIT, this, args)
|
||||
|
||||
|
||||
extern cVideo *videoDecoder;
|
||||
extern cAudio *audioDecoder;
|
||||
extern VDec *vdec;
|
||||
extern ADec *adec;
|
||||
|
||||
static GLFramebuffer *gThiz = 0; /* GLUT does not allow for an arbitrary argument to the render func */
|
||||
/* the private class that does stuff only needed inside libstb-hal.
|
||||
* is used e.g. by cVideo... */
|
||||
GLFbPC *glfb_priv = NULL;
|
||||
|
||||
GLFramebuffer::GLFramebuffer(int x, int y): mReInit(true), mShutDown(false), mInitDone(false)
|
||||
GLFramebuffer::GLFramebuffer(int x, int y)
|
||||
{
|
||||
Init();
|
||||
glfb_priv = new GLFbPC(x, y, osd_buf);
|
||||
si = glfb_priv->getScreenInfo();
|
||||
start();
|
||||
while (!glfb_priv->mInitDone)
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
GLFramebuffer::~GLFramebuffer()
|
||||
{
|
||||
glfb_priv->mShutDown = true;
|
||||
join();
|
||||
delete glfb_priv;
|
||||
glfb_priv = NULL;
|
||||
}
|
||||
|
||||
void GLFramebuffer::blit()
|
||||
{
|
||||
glfb_priv->blit();
|
||||
}
|
||||
|
||||
GLFbPC::GLFbPC(int x, int y, std::vector<unsigned char> &buf): mReInit(true), mShutDown(false), mInitDone(false)
|
||||
{
|
||||
osd_buf = &buf;
|
||||
mState.width = x;
|
||||
mState.height = y;
|
||||
mX = &_mX[0];
|
||||
@@ -77,19 +103,19 @@ GLFramebuffer::GLFramebuffer(int x, int y): mReInit(true), mShutDown(false), mIn
|
||||
last_apts = 0;
|
||||
|
||||
/* linux framebuffer compat mode */
|
||||
screeninfo.bits_per_pixel = 32;
|
||||
screeninfo.xres = mState.width;
|
||||
screeninfo.xres_virtual = screeninfo.xres;
|
||||
screeninfo.yres = mState.height;
|
||||
screeninfo.yres_virtual = screeninfo.yres;
|
||||
screeninfo.blue.length = 8;
|
||||
screeninfo.blue.offset = 0;
|
||||
screeninfo.green.length = 8;
|
||||
screeninfo.green.offset = 8;
|
||||
screeninfo.red.length = 8;
|
||||
screeninfo.red.offset = 16;
|
||||
screeninfo.transp.length = 8;
|
||||
screeninfo.transp.offset = 24;
|
||||
si.bits_per_pixel = 32;
|
||||
si.xres = mState.width;
|
||||
si.xres_virtual = si.xres;
|
||||
si.yres = mState.height;
|
||||
si.yres_virtual = si.yres;
|
||||
si.blue.length = 8;
|
||||
si.blue.offset = 0;
|
||||
si.green.length = 8;
|
||||
si.green.offset = 8;
|
||||
si.red.length = 8;
|
||||
si.red.offset = 16;
|
||||
si.transp.length = 8;
|
||||
si.transp.offset = 24;
|
||||
|
||||
unlink("/tmp/neutrino.input");
|
||||
mkfifo("/tmp/neutrino.input", 0600);
|
||||
@@ -97,39 +123,39 @@ GLFramebuffer::GLFramebuffer(int x, int y): mReInit(true), mShutDown(false), mIn
|
||||
if (input_fd < 0)
|
||||
lt_info("%s: could not open /tmp/neutrino.input FIFO: %m\n", __func__);
|
||||
initKeys();
|
||||
Thread::startThread();
|
||||
while (!mInitDone)
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
GLFramebuffer::~GLFramebuffer()
|
||||
GLFbPC::~GLFbPC()
|
||||
{
|
||||
mShutDown = true;
|
||||
Thread::joinThread();
|
||||
if (input_fd >= 0)
|
||||
close(input_fd);
|
||||
osd_buf->clear();
|
||||
}
|
||||
|
||||
void GLFramebuffer::initKeys()
|
||||
void GLFbPC::initKeys()
|
||||
{
|
||||
/*
|
||||
Keep in sync with initKeys() in clutterfb.cpp
|
||||
*/
|
||||
|
||||
mSpecialMap[GLUT_KEY_UP] = KEY_UP;
|
||||
mSpecialMap[GLUT_KEY_DOWN] = KEY_DOWN;
|
||||
mSpecialMap[GLUT_KEY_LEFT] = KEY_LEFT;
|
||||
mSpecialMap[GLUT_KEY_RIGHT] = KEY_RIGHT;
|
||||
|
||||
mSpecialMap[GLUT_KEY_F1] = KEY_RED;
|
||||
mSpecialMap[GLUT_KEY_F2] = KEY_GREEN;
|
||||
mSpecialMap[GLUT_KEY_F3] = KEY_YELLOW;
|
||||
mSpecialMap[GLUT_KEY_F4] = KEY_BLUE;
|
||||
mSpecialMap[GLUT_KEY_F1] = KEY_RED;
|
||||
mSpecialMap[GLUT_KEY_F2] = KEY_GREEN;
|
||||
mSpecialMap[GLUT_KEY_F3] = KEY_YELLOW;
|
||||
mSpecialMap[GLUT_KEY_F4] = KEY_BLUE;
|
||||
|
||||
mSpecialMap[GLUT_KEY_F5] = KEY_PLAY;
|
||||
mSpecialMap[GLUT_KEY_F6] = KEY_STOP;
|
||||
mSpecialMap[GLUT_KEY_F7] = KEY_FORWARD;
|
||||
mSpecialMap[GLUT_KEY_F8] = KEY_REWIND;
|
||||
|
||||
mSpecialMap[GLUT_KEY_F9] = KEY_RECORD;
|
||||
mSpecialMap[GLUT_KEY_F10] = KEY_PAUSE;
|
||||
mSpecialMap[GLUT_KEY_F5] = KEY_RECORD;
|
||||
mSpecialMap[GLUT_KEY_F6] = KEY_PLAY;
|
||||
mSpecialMap[GLUT_KEY_F7] = KEY_PAUSE;
|
||||
mSpecialMap[GLUT_KEY_F8] = KEY_STOP;
|
||||
|
||||
mSpecialMap[GLUT_KEY_F9] = KEY_FORWARD;
|
||||
mSpecialMap[GLUT_KEY_F10] = KEY_REWIND;
|
||||
mSpecialMap[GLUT_KEY_F11] = KEY_NEXT;
|
||||
mSpecialMap[GLUT_KEY_F12] = KEY_PREVIOUS;
|
||||
|
||||
@@ -138,15 +164,6 @@ void GLFramebuffer::initKeys()
|
||||
|
||||
mKeyMap[0x0d] = KEY_OK;
|
||||
mKeyMap[0x1b] = KEY_EXIT;
|
||||
mKeyMap['e'] = KEY_EPG;
|
||||
mKeyMap['i'] = KEY_INFO;
|
||||
mKeyMap['m'] = KEY_MENU;
|
||||
|
||||
mKeyMap['+'] = KEY_VOLUMEUP;
|
||||
mKeyMap['-'] = KEY_VOLUMEDOWN;
|
||||
mKeyMap['.'] = KEY_MUTE;
|
||||
mKeyMap['h'] = KEY_HELP;
|
||||
mKeyMap['p'] = KEY_POWER;
|
||||
|
||||
mKeyMap['0'] = KEY_0;
|
||||
mKeyMap['1'] = KEY_1;
|
||||
@@ -159,17 +176,48 @@ void GLFramebuffer::initKeys()
|
||||
mKeyMap['8'] = KEY_8;
|
||||
mKeyMap['9'] = KEY_9;
|
||||
|
||||
mKeyMap['r'] = KEY_RED;
|
||||
mKeyMap['g'] = KEY_GREEN;
|
||||
mKeyMap['y'] = KEY_YELLOW;
|
||||
mKeyMap['b'] = KEY_BLUE;
|
||||
mKeyMap['+'] = KEY_VOLUMEUP;
|
||||
mKeyMap['-'] = KEY_VOLUMEDOWN;
|
||||
mKeyMap['.'] = KEY_MUTE;
|
||||
mKeyMap['a'] = KEY_AUDIO;
|
||||
mKeyMap['e'] = KEY_EPG;
|
||||
// ['f'] is reserved to toggle fullscreen;
|
||||
mKeyMap['g'] = KEY_GAMES;
|
||||
mKeyMap['h'] = KEY_HELP;
|
||||
mKeyMap['i'] = KEY_INFO;
|
||||
mKeyMap['m'] = KEY_MENU;
|
||||
mKeyMap['p'] = KEY_POWER;
|
||||
mKeyMap['r'] = KEY_RADIO;
|
||||
mKeyMap['s'] = KEY_SUBTITLE;
|
||||
mKeyMap['t'] = KEY_TV;
|
||||
mKeyMap['v'] = KEY_VIDEO;
|
||||
mKeyMap['z'] = KEY_SLEEP;
|
||||
|
||||
/* shift keys */
|
||||
mKeyMap['F'] = KEY_FAVORITES;
|
||||
mKeyMap['M'] = KEY_MODE;
|
||||
mKeyMap['S'] = KEY_SAT;
|
||||
mKeyMap['T'] = KEY_TEXT;
|
||||
mKeyMap['W'] = KEY_WWW;
|
||||
}
|
||||
|
||||
void GLFramebuffer::run()
|
||||
{
|
||||
setupCtx();
|
||||
setupOSDBuffer();
|
||||
mInitDone = true; /* signal that setup is finished */
|
||||
int argc = 1;
|
||||
int x = glfb_priv->mState.width;
|
||||
int y = glfb_priv->mState.height;
|
||||
/* some dummy commandline for GLUT to be happy */
|
||||
char const *argv[2] = { "neutrino", 0 };
|
||||
lt_info("GLFB: GL thread starting x %d y %d\n", x, y);
|
||||
glutInit(&argc, const_cast<char **>(argv));
|
||||
glutInitWindowSize(x, y);
|
||||
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
|
||||
glutCreateWindow("Neutrino");
|
||||
/* 32bit FB depth, *2 because tuxtxt uses a shadow buffer */
|
||||
int fbmem = x * y * 4 * 2;
|
||||
osd_buf.resize(fbmem);
|
||||
lt_info("GLFB: OSD buffer set to %d bytes at 0x%p\n", fbmem, osd_buf.data());
|
||||
glfb_priv->mInitDone = true; /* signal that setup is finished */
|
||||
|
||||
/* init the good stuff */
|
||||
GLenum err = glewInit();
|
||||
@@ -184,16 +232,15 @@ void GLFramebuffer::run()
|
||||
}
|
||||
else
|
||||
{
|
||||
gThiz = this;
|
||||
glutSetCursor(GLUT_CURSOR_NONE);
|
||||
glutDisplayFunc(GLFramebuffer::rendercb);
|
||||
glutKeyboardFunc(GLFramebuffer::keyboardcb);
|
||||
glutSpecialFunc(GLFramebuffer::specialcb);
|
||||
glutReshapeFunc(GLFramebuffer::resizecb);
|
||||
setupGLObjects(); /* needs GLEW prototypes */
|
||||
glutDisplayFunc(GLFbPC::rendercb);
|
||||
glutKeyboardFunc(GLFbPC::keyboardcb);
|
||||
glutSpecialFunc(GLFbPC::specialcb);
|
||||
glutReshapeFunc(GLFbPC::resizecb);
|
||||
glfb_priv->setupGLObjects(); /* needs GLEW prototypes */
|
||||
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
|
||||
glutMainLoop();
|
||||
releaseGLObjects();
|
||||
glfb_priv->releaseGLObjects();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -201,21 +248,20 @@ void GLFramebuffer::run()
|
||||
lt_info("GLFB: GL thread stopping\n");
|
||||
}
|
||||
|
||||
|
||||
void GLFramebuffer::setupCtx()
|
||||
#if 0
|
||||
void GLFbPC::setupCtx()
|
||||
{
|
||||
int argc = 1;
|
||||
/* some dummy commandline for GLUT to be happy */
|
||||
char const *argv[2] = { "neutrino", 0 };
|
||||
lt_info("GLFB: GL thread starting\n");
|
||||
lt_info("GLFB: GL thread starting x %d y %d\n", mX[0], mY[0]);
|
||||
glutInit(&argc, const_cast<char **>(argv));
|
||||
glutInitWindowSize(mX[0], mY[0]);
|
||||
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
|
||||
glutCreateWindow("Neutrino");
|
||||
GLWinID = glXGetCurrentDrawable(); // this was the holy grail to get the right window handle for gstreamer :D
|
||||
}
|
||||
|
||||
void GLFramebuffer::setupOSDBuffer()
|
||||
void GLFbPC::setupOSDBuffer()
|
||||
{ /* the OSD buffer size can be decoupled from the actual
|
||||
window size since the GL can blit-stretch with no
|
||||
trouble at all, ah, the luxury of ignorance... */
|
||||
@@ -224,12 +270,13 @@ void GLFramebuffer::setupOSDBuffer()
|
||||
{
|
||||
/* 32bit FB depth, *2 because tuxtxt uses a shadow buffer */
|
||||
int fbmem = mState.width * mState.height * 4 * 2;
|
||||
mOSDBuffer.resize(fbmem);
|
||||
lt_info("GLFB: OSD buffer set to %d bytes\n", fbmem);
|
||||
osd_buf->resize(fbmem);
|
||||
lt_info("GLFB: OSD buffer set to %d bytes at 0x%p\n", fbmem, osd_buf->data());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void GLFramebuffer::setupGLObjects()
|
||||
void GLFbPC::setupGLObjects()
|
||||
{
|
||||
unsigned char buf[4] = { 0, 0, 0, 0 }; /* 1 black pixel */
|
||||
glGenTextures(1, &mState.osdtex);
|
||||
@@ -257,7 +304,7 @@ void GLFramebuffer::setupGLObjects()
|
||||
}
|
||||
|
||||
|
||||
void GLFramebuffer::releaseGLObjects()
|
||||
void GLFbPC::releaseGLObjects()
|
||||
{
|
||||
glDeleteBuffers(1, &mState.pbo);
|
||||
glDeleteBuffers(1, &mState.displaypbo);
|
||||
@@ -266,56 +313,56 @@ void GLFramebuffer::releaseGLObjects()
|
||||
}
|
||||
|
||||
|
||||
/* static */ void GLFramebuffer::rendercb()
|
||||
/* static */ void GLFbPC::rendercb()
|
||||
{
|
||||
gThiz->render();
|
||||
glfb_priv->render();
|
||||
}
|
||||
|
||||
|
||||
/* static */ void GLFramebuffer::keyboardcb(unsigned char key, int /*x*/, int /*y*/)
|
||||
/* static */ void GLFbPC::keyboardcb(unsigned char key, int /*x*/, int /*y*/)
|
||||
{
|
||||
lt_debug_c("GLFB::%s: 0x%x\n", __func__, key);
|
||||
struct input_event ev;
|
||||
if (key == 'f')
|
||||
{
|
||||
lt_info_c("GLFB::%s: toggle fullscreen %s\n", __func__, gThiz->mFullscreen?"off":"on");
|
||||
gThiz->mFullscreen = !(gThiz->mFullscreen);
|
||||
gThiz->mReInit = true;
|
||||
lt_info_c("GLFB::%s: toggle fullscreen %s\n", __func__, glfb_priv->mFullscreen?"off":"on");
|
||||
glfb_priv->mFullscreen = !(glfb_priv->mFullscreen);
|
||||
glfb_priv->mReInit = true;
|
||||
return;
|
||||
}
|
||||
std::map<unsigned char, int>::const_iterator i = gThiz->mKeyMap.find(key);
|
||||
if (i == gThiz->mKeyMap.end())
|
||||
std::map<unsigned char, int>::const_iterator i = glfb_priv->mKeyMap.find(key);
|
||||
if (i == glfb_priv->mKeyMap.end())
|
||||
return;
|
||||
ev.code = i->second;
|
||||
ev.value = 1; /* key own */
|
||||
ev.type = EV_KEY;
|
||||
gettimeofday(&ev.time, NULL);
|
||||
lt_debug_c("GLFB::%s: pushing 0x%x\n", __func__, ev.code);
|
||||
write(gThiz->input_fd, &ev, sizeof(ev));
|
||||
write(glfb_priv->input_fd, &ev, sizeof(ev));
|
||||
ev.value = 0; /* neutrino is stupid, so push key up directly after key down */
|
||||
write(gThiz->input_fd, &ev, sizeof(ev));
|
||||
write(glfb_priv->input_fd, &ev, sizeof(ev));
|
||||
}
|
||||
|
||||
/* static */ void GLFramebuffer::specialcb(int key, int /*x*/, int /*y*/)
|
||||
/* static */ void GLFbPC::specialcb(int key, int /*x*/, int /*y*/)
|
||||
{
|
||||
lt_debug_c("GLFB::%s: 0x%x\n", __func__, key);
|
||||
struct input_event ev;
|
||||
std::map<int, int>::const_iterator i = gThiz->mSpecialMap.find(key);
|
||||
if (i == gThiz->mSpecialMap.end())
|
||||
std::map<int, int>::const_iterator i = glfb_priv->mSpecialMap.find(key);
|
||||
if (i == glfb_priv->mSpecialMap.end())
|
||||
return;
|
||||
ev.code = i->second;
|
||||
ev.value = 1;
|
||||
ev.type = EV_KEY;
|
||||
gettimeofday(&ev.time, NULL);
|
||||
lt_debug_c("GLFB::%s: pushing 0x%x\n", __func__, ev.code);
|
||||
write(gThiz->input_fd, &ev, sizeof(ev));
|
||||
write(glfb_priv->input_fd, &ev, sizeof(ev));
|
||||
ev.value = 0;
|
||||
write(gThiz->input_fd, &ev, sizeof(ev));
|
||||
write(glfb_priv->input_fd, &ev, sizeof(ev));
|
||||
}
|
||||
|
||||
int sleep_us = 30000;
|
||||
|
||||
void GLFramebuffer::render()
|
||||
void GLFbPC::render()
|
||||
{
|
||||
if(mShutDown)
|
||||
glutLeaveMainLoop();
|
||||
@@ -443,12 +490,12 @@ void GLFramebuffer::render()
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
/* static */ void GLFramebuffer::resizecb(int w, int h)
|
||||
/* static */ void GLFbPC::resizecb(int w, int h)
|
||||
{
|
||||
gThiz->checkReinit(w, h);
|
||||
glfb_priv->checkReinit(w, h);
|
||||
}
|
||||
|
||||
void GLFramebuffer::checkReinit(int x, int y)
|
||||
void GLFbPC::checkReinit(int x, int y)
|
||||
{
|
||||
static int last_x = 0, last_y = 0;
|
||||
|
||||
@@ -468,7 +515,7 @@ void GLFramebuffer::checkReinit(int x, int y)
|
||||
last_y = y;
|
||||
}
|
||||
|
||||
void GLFramebuffer::drawSquare(float size, float x_factor)
|
||||
void GLFbPC::drawSquare(float size, float x_factor)
|
||||
{
|
||||
GLfloat vertices[] = {
|
||||
1.0f, 1.0f,
|
||||
@@ -486,17 +533,17 @@ void GLFramebuffer::drawSquare(float size, float x_factor)
|
||||
1.0, 1.0,
|
||||
};
|
||||
if (x_factor > -99.0) { /* x_factor == -100 => OSD */
|
||||
if (videoDecoder &&
|
||||
videoDecoder->pig_x > 0 && videoDecoder->pig_y > 0 &&
|
||||
videoDecoder->pig_w > 0 && videoDecoder->pig_h > 0) {
|
||||
if (vdec &&
|
||||
vdec->pig_x > 0 && vdec->pig_y > 0 &&
|
||||
vdec->pig_w > 0 && vdec->pig_h > 0) {
|
||||
/* these calculations even consider cropping and panscan mode
|
||||
* maybe this could be done with some clever opengl tricks? */
|
||||
double w2 = (double)mState.width * 0.5l;
|
||||
double h2 = (double)mState.height * 0.5l;
|
||||
double x = (double)(videoDecoder->pig_x - w2) / w2 / x_factor / size;
|
||||
double y = (double)(h2 - videoDecoder->pig_y) / h2 / size;
|
||||
double w = (double)videoDecoder->pig_w / w2;
|
||||
double h = (double)videoDecoder->pig_h / h2;
|
||||
double x = (double)(vdec->pig_x - w2) / w2 / x_factor / size;
|
||||
double y = (double)(h2 - vdec->pig_y) / h2 / size;
|
||||
double w = (double)vdec->pig_w / w2;
|
||||
double h = (double)vdec->pig_h / h2;
|
||||
x += ((1.0l - x_factor * size) / 2.0l) * w / x_factor / size;
|
||||
y += ((size - 1.0l) / 2.0l) * h / size;
|
||||
vertices[0] = x + w; /* top right x */
|
||||
@@ -524,11 +571,11 @@ void GLFramebuffer::drawSquare(float size, float x_factor)
|
||||
}
|
||||
|
||||
|
||||
void GLFramebuffer::bltOSDBuffer()
|
||||
void GLFbPC::bltOSDBuffer()
|
||||
{
|
||||
/* FIXME: copy each time */
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mState.pbo);
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, mOSDBuffer.size(), &mOSDBuffer[0], GL_STREAM_DRAW_ARB);
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, osd_buf->size(), osd_buf->data(), GL_STREAM_DRAW_ARB);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, mState.osdtex);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mState.width, mState.height, GL_BGRA, GL_UNSIGNED_BYTE, 0);
|
||||
@@ -536,15 +583,15 @@ void GLFramebuffer::bltOSDBuffer()
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
|
||||
void GLFramebuffer::bltDisplayBuffer()
|
||||
void GLFbPC::bltDisplayBuffer()
|
||||
{
|
||||
if (!videoDecoder) /* cannot start yet */
|
||||
if (!vdec) /* cannot start yet */
|
||||
return;
|
||||
static bool warn = true;
|
||||
cVideo::SWFramebuffer *buf = videoDecoder->getDecBuf();
|
||||
VDec::SWFramebuffer *buf = vdec->getDecBuf();
|
||||
if (!buf) {
|
||||
if (warn)
|
||||
lt_debug("GLFB::%s did not get a buffer...\n", __func__);
|
||||
lt_info("GLFB::%s did not get a buffer...\n", __func__);
|
||||
warn = false;
|
||||
return;
|
||||
}
|
||||
@@ -573,10 +620,9 @@ void GLFramebuffer::bltDisplayBuffer()
|
||||
* this implementation is pretty naive and not working too well, but
|
||||
* better this than nothing... :-) */
|
||||
int64_t apts = 0;
|
||||
/* 18000 is the magic value for A/V sync in my libao->pulseaudio->intel_hda setup */
|
||||
int64_t vpts = buf->pts() + 18000;
|
||||
if (audioDecoder)
|
||||
apts = audioDecoder->getPts();
|
||||
int64_t vpts = buf->pts();
|
||||
if (adec)
|
||||
apts = adec->getPts();
|
||||
if (apts != last_apts) {
|
||||
int rate, dummy1, dummy2;
|
||||
if (apts < vpts)
|
||||
@@ -584,7 +630,7 @@ void GLFramebuffer::bltDisplayBuffer()
|
||||
else if (sleep_us > 1000)
|
||||
sleep_us -= 1000;
|
||||
last_apts = apts;
|
||||
videoDecoder->getPictureInfo(dummy1, dummy2, rate);
|
||||
vdec->getPictureInfo(dummy1, dummy2, rate);
|
||||
if (rate > 0)
|
||||
rate = 2000000 / rate; /* limit to half the frame rate */
|
||||
else
|
||||
@@ -595,11 +641,5 @@ void GLFramebuffer::bltDisplayBuffer()
|
||||
sleep_us = 1;
|
||||
}
|
||||
lt_debug("vpts: 0x%" PRIx64 " apts: 0x%" PRIx64 " diff: %6.3f sleep_us %d buf %d\n",
|
||||
buf->pts(), apts, (buf->pts() - apts)/90000.0, sleep_us, videoDecoder->buf_num);
|
||||
}
|
||||
|
||||
void GLFramebuffer::clear()
|
||||
{
|
||||
/* clears front and back buffer */
|
||||
memset(&mOSDBuffer[0], 0, mOSDBuffer.size());
|
||||
buf->pts(), apts, (buf->pts() - apts)/90000.0, sleep_us, vdec->buf_num);
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Copyright 2010 Carsten Juttner <carjay@gmx.net>
|
||||
Copyright 2012,2013 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
|
||||
Copyright 2012,2013,2016 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -14,44 +14,46 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
********************************************************************
|
||||
private stuff of the GLFB thread that is only used inside libstb-hal
|
||||
and not exposed to the application.
|
||||
*/
|
||||
|
||||
#ifndef __glthread__
|
||||
#define __glthread__
|
||||
#include <thread_abstraction.h>
|
||||
#include <mutex_abstraction.h>
|
||||
|
||||
#ifndef __glfb_priv__
|
||||
#define __glfb_priv__
|
||||
#include <OpenThreads/Mutex>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#if USE_OPENGL
|
||||
#include <GL/glew.h>
|
||||
#include <GL/freeglut.h>
|
||||
#include <GL/gl.h>
|
||||
#include <linux/fb.h> /* for screeninfo etc. */
|
||||
#endif
|
||||
#if USE_CLUTTER
|
||||
#include <clutter/clutter.h>
|
||||
#endif
|
||||
#include "glfb.h"
|
||||
extern "C" {
|
||||
#include <libavutil/rational.h>
|
||||
}
|
||||
|
||||
class GLFramebuffer : public Thread
|
||||
class GLFbPC
|
||||
{
|
||||
public:
|
||||
GLFramebuffer(int x, int y);
|
||||
~GLFramebuffer();
|
||||
|
||||
void run();
|
||||
std::vector<unsigned char> *getOSDBuffer() { return &mOSDBuffer; } /* pointer to OSD bounce buffer */
|
||||
|
||||
GLFbPC(int x, int y, std::vector<unsigned char> &buf);
|
||||
~GLFbPC();
|
||||
std::vector<unsigned char> *getOSDBuffer() { return osd_buf; } /* pointer to OSD bounce buffer */
|
||||
int getOSDWidth() { return mState.width; }
|
||||
int getOSDHeight() { return mState.height; }
|
||||
void blit() { mState.blit = true; }
|
||||
|
||||
void blit() { mState.blit = true; };
|
||||
fb_var_screeninfo getScreenInfo() { return si; }
|
||||
void setOutputFormat(AVRational a, int h, int c) { mOA = a; *mY = h; mCrop = c; mReInit = true; }
|
||||
|
||||
void clear();
|
||||
fb_var_screeninfo getScreenInfo() { return screeninfo; }
|
||||
int getWindowID() { return GLWinID; }
|
||||
|
||||
/* just make everything public for simplicity - this is only used inside libstb-hal anyway
|
||||
private:
|
||||
fb_var_screeninfo screeninfo;
|
||||
*/
|
||||
fb_var_screeninfo si;
|
||||
int *mX;
|
||||
int *mY;
|
||||
int _mX[2]; /* output window size */
|
||||
@@ -63,45 +65,59 @@ private:
|
||||
float zoom; /* for cropping */
|
||||
float xscale; /* and aspect ratio */
|
||||
int mCrop; /* DISPLAY_AR_MODE */
|
||||
int GLWinID;
|
||||
|
||||
bool mFullscreen; /* fullscreen? */
|
||||
bool mReInit; /* setup things for GL */
|
||||
Mutex mReInitLock;
|
||||
OpenThreads::Mutex mReInitLock;
|
||||
bool mShutDown; /* if set main loop is left */
|
||||
bool mInitDone; /* condition predicate */
|
||||
// OpenThreads::Condition mInitCond; /* condition variable for init */
|
||||
// mutable OpenThreads::Mutex mMutex; /* lock our data */
|
||||
|
||||
std::vector<unsigned char> mOSDBuffer; /* silly bounce buffer */
|
||||
std::vector<unsigned char> *osd_buf; /* silly bounce buffer */
|
||||
|
||||
#if USE_OPENGL
|
||||
std::map<unsigned char, int> mKeyMap;
|
||||
std::map<int, int> mSpecialMap;
|
||||
#endif
|
||||
#if USE_CLUTTER
|
||||
std::map<int, int> mKeyMap;
|
||||
#endif
|
||||
int input_fd;
|
||||
int64_t last_apts;
|
||||
void run();
|
||||
|
||||
static void rendercb(); /* callback for GLUT */
|
||||
void render(); /* actual render function */
|
||||
#if USE_OPENGL
|
||||
static void keyboardcb(unsigned char key, int x, int y);
|
||||
static void specialcb(int key, int x, int y);
|
||||
static void resizecb(int w, int h);
|
||||
void checkReinit(int w, int h); /* e.g. in case window was resized */
|
||||
|
||||
void initKeys(); /* setup key bindings for window */
|
||||
void setupCtx(); /* create the window and make the context current */
|
||||
void setupOSDBuffer(); /* create the OSD buffer */
|
||||
void setupGLObjects(); /* PBOs, textures and stuff */
|
||||
void releaseGLObjects();
|
||||
void drawSquare(float size, float x_factor = 1); /* do not be square */
|
||||
#endif
|
||||
#if USE_CLUTTER
|
||||
static bool keyboardcb(ClutterActor *actor, ClutterEvent *event, gpointer user_data);
|
||||
#endif
|
||||
|
||||
void initKeys(); /* setup key bindings for window */
|
||||
#if 0
|
||||
void setupCtx(); /* create the window and make the context current */
|
||||
void setupOSDBuffer(); /* create the OSD buffer */
|
||||
#endif
|
||||
|
||||
struct {
|
||||
int width; /* width and height, fixed for a framebuffer instance */
|
||||
int height;
|
||||
bool blit;
|
||||
#if USE_OPENGL
|
||||
GLuint osdtex; /* holds the OSD texture */
|
||||
GLuint pbo; /* PBO we use for transfer to texture */
|
||||
GLuint displaytex; /* holds the display texture */
|
||||
GLuint displaypbo;
|
||||
bool blit;
|
||||
#endif
|
||||
} mState;
|
||||
|
||||
void bltOSDBuffer();
|
@@ -7,12 +7,8 @@
|
||||
* License: GPL v2 or later
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <hardware_caps.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
@@ -33,6 +29,9 @@ hw_caps_t *get_hwcaps(void)
|
||||
caps.has_HDMI = 1;
|
||||
caps.display_xres = 8;
|
||||
caps.display_can_deepstandby = 0;
|
||||
caps.display_can_set_brightness = 0;
|
||||
caps.display_has_statusline = 0;
|
||||
caps.has_button_vformat = 0;
|
||||
strcpy(caps.boxvendor, "Generic");
|
||||
strcpy(caps.boxname, "PC");
|
||||
if (! uname(&u))
|
||||
|
@@ -1,7 +1,8 @@
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "init_lib.h"
|
||||
#include "init_td.h"
|
||||
#include "lt_debug.h"
|
||||
#include "glfb.h"
|
||||
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_INIT, NULL, args)
|
||||
|
@@ -1,5 +0,0 @@
|
||||
#ifndef __INIT_TD_H
|
||||
#define __INIT_TD_H
|
||||
void init_td_api();
|
||||
void shutdown_td_api();
|
||||
#endif
|
@@ -1,6 +1,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "playback.h"
|
||||
#include "playback_hal.h"
|
||||
|
||||
static const char * FILENAME = "playback-dummy";
|
||||
|
||||
@@ -13,25 +13,25 @@ void cPlayback::Close(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool cPlayback::Start(std::string filename, std::string headers)
|
||||
bool cPlayback::Start(std::string /*filename*/, std::string /*headers*/)
|
||||
{
|
||||
return Start((char*) filename.c_str(),0,0,0,0,0, headers);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, int duration, std::string headers)
|
||||
bool cPlayback::Start(char * filename, unsigned short vpid, int vtype, unsigned short apid, int ac3, unsigned int duration)
|
||||
{
|
||||
printf("%s:%s - filename=%s vpid=%u vtype=%d apid=%u ac3=%d duration=%i\n",
|
||||
FILENAME, __func__, filename, vpid, vtype, apid, ac3, duration);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cPlayback::SetAPid(int pid, bool /*ac3*/)
|
||||
bool cPlayback::SetAPid(unsigned short pid, int /*ac3*/)
|
||||
{
|
||||
printf("%s:%s pid %i\n", FILENAME, __func__, pid);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cPlayback::SelectSubtitles(int pid)
|
||||
bool cPlayback::SelectSubtitles(int pid, std::string /*charset*/)
|
||||
{
|
||||
printf("%s:%s pid %i\n", FILENAME, __func__, pid);
|
||||
return true;
|
||||
@@ -39,7 +39,7 @@ bool cPlayback::SelectSubtitles(int pid)
|
||||
|
||||
bool cPlayback::SetSpeed(int speed)
|
||||
{
|
||||
printf("%s:%s playing %d speed %d\n", FILENAME, __func__, playing, speed);
|
||||
printf("%s:%s speed %d\n", FILENAME, __func__, speed);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -62,53 +62,16 @@ bool cPlayback::SetPosition(int position, bool)
|
||||
return true;
|
||||
}
|
||||
|
||||
void cPlayback::FindAllPids(int *, unsigned int *, unsigned int *numpida, std::string *)
|
||||
void cPlayback::FindAllPids(uint16_t *, unsigned short *, uint16_t *numpida, std::string *)
|
||||
{
|
||||
printf("%s:%s\n", FILENAME, __func__);
|
||||
*numpida = 0;
|
||||
}
|
||||
|
||||
void cPlayback::FindAllSubtitlePids(int * /*pids*/, unsigned int *numpids, std::string * /*language*/)
|
||||
{
|
||||
*numpids = 0;
|
||||
}
|
||||
|
||||
bool cPlayback::SetSubtitlePid(int /*pid*/)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void cPlayback::GetPts(uint64_t &/*pts*/)
|
||||
{
|
||||
}
|
||||
|
||||
bool cPlayback::SetTeletextPid(int /*pid*/)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void cPlayback::FindAllTeletextsubtitlePids(int *, unsigned int *numpids, std::string *, int *, int *)
|
||||
{
|
||||
*numpids = 0;
|
||||
}
|
||||
|
||||
void cPlayback::SuspendSubtitle(bool /*b*/)
|
||||
{
|
||||
}
|
||||
|
||||
void cPlayback::RequestAbort()
|
||||
{
|
||||
}
|
||||
|
||||
int cPlayback::GetTeletextPid(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void cPlayback::FindAllSubs(uint16_t * /*pids*/, unsigned short * /*supp*/, uint16_t *num, std::string * /*lang*/)
|
||||
void cPlayback::FindAllSubs(uint16_t *, unsigned short *, uint16_t *numpida, std::string *)
|
||||
{
|
||||
printf("%s:%s\n", FILENAME, __func__);
|
||||
*num = 0;
|
||||
*numpida = 0;
|
||||
}
|
||||
|
||||
void cPlayback::GetChapters(std::vector<int> &positions, std::vector<std::string> &titles)
|
||||
@@ -117,20 +80,21 @@ void cPlayback::GetChapters(std::vector<int> &positions, std::vector<std::string
|
||||
titles.clear();
|
||||
}
|
||||
|
||||
void cPlayback::GetMetadata(std::vector<std::string> &keys, std::vector<std::string> &values)
|
||||
{
|
||||
keys.clear();
|
||||
values.clear();
|
||||
}
|
||||
|
||||
void cPlayback::GetTitles(std::vector<int> &playlists, std::vector<std::string> &titles, int ¤t)
|
||||
{
|
||||
playlists.clear();
|
||||
titles.clear();
|
||||
current = 0;
|
||||
}
|
||||
|
||||
void cPlayback::SetTitle(int /*title*/)
|
||||
{
|
||||
}
|
||||
|
||||
void cPlayback::RequestAbort(void)
|
||||
{
|
||||
}
|
||||
|
||||
uint64_t cPlayback::GetReadCount(void)
|
||||
{
|
||||
return 0;
|
||||
|
@@ -1,58 +0,0 @@
|
||||
#ifndef __PLAYBACK_H
|
||||
#define __PLAYBACK_H
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
typedef enum {
|
||||
PLAYMODE_TS = 0,
|
||||
PLAYMODE_FILE,
|
||||
} playmode_t;
|
||||
|
||||
struct AVFormatContext;
|
||||
class cPlayback
|
||||
{
|
||||
private:
|
||||
bool playing;
|
||||
int mAudioStream;
|
||||
int mSubtitleStream;
|
||||
int mTeletextStream;
|
||||
public:
|
||||
cPlayback(int);
|
||||
bool Open(playmode_t PlayMode);
|
||||
void Close(void);
|
||||
bool Start(char *filename, int vpid, int vtype, int apid, int ac3, int duration, std::string headers = "");
|
||||
bool Start(std::string filename, std::string headers = "");
|
||||
bool SetAPid(int pid, bool ac3);
|
||||
bool SetSubtitlePid(int pid);
|
||||
bool SetTeletextPid(int pid);
|
||||
int GetAPid(void) { return mAudioStream; }
|
||||
int GetVPid(void);
|
||||
int GetSubtitlePid(void) { return mSubtitleStream; }
|
||||
int GetTeletextPid(void);
|
||||
void SuspendSubtitle(bool);
|
||||
int GetFirstTeletextPid(void);
|
||||
bool SetSpeed(int speed);
|
||||
bool GetSpeed(int &speed) const;
|
||||
bool GetPosition(int &position, int &duration);
|
||||
void GetPts(uint64_t &pts);
|
||||
bool SetPosition(int position, bool absolute = false);
|
||||
void FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *numpida, std::string *language);
|
||||
void FindAllSubtitlePids(int *pids, unsigned int *numpids, std::string *language);
|
||||
void FindAllTeletextsubtitlePids(int *pids, unsigned int *numpidt, std::string *tlanguage, int *mags, int *pages);
|
||||
void RequestAbort(void);
|
||||
bool IsPlaying(void) { return false; }
|
||||
uint64_t GetReadCount(void);
|
||||
void FindAllSubs(uint16_t *pids, unsigned short *supported, uint16_t *numpida, std::string *language);
|
||||
bool SelectSubtitles(int pid);
|
||||
void GetTitles(std::vector<int> &playlists, std::vector<std::string> &titles, int ¤t);
|
||||
void SetTitle(int title);
|
||||
void GetChapters(std::vector<int> &positions, std::vector<std::string> &titles);
|
||||
void GetMetadata(std::vector<std::string> &keys, std::vector<std::string> &values);
|
||||
//
|
||||
~cPlayback();
|
||||
AVFormatContext *GetAVFormatContext(){ return NULL; }
|
||||
void ReleaseAVFormatContext() {}
|
||||
};
|
||||
#endif
|
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PLAYBACK_CS_H
|
||||
#define __PLAYBACK_CS_H
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STATE_STOP,
|
||||
STATE_PLAY,
|
||||
STATE_PAUSE,
|
||||
STATE_FF,
|
||||
STATE_REW,
|
||||
STATE_SLOW
|
||||
} playstate_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PLAYMODE_TS = 0,
|
||||
PLAYMODE_FILE,
|
||||
} playmode_t;
|
||||
|
||||
struct AVFormatContext;
|
||||
|
||||
class cPlayback
|
||||
{
|
||||
private:
|
||||
bool playing, first;
|
||||
bool decoders_closed;
|
||||
|
||||
int mSpeed;
|
||||
int mAudioStream;
|
||||
int init_jump;
|
||||
|
||||
public:
|
||||
playstate_t playstate;
|
||||
|
||||
cPlayback(int);
|
||||
bool Open(playmode_t PlayMode);
|
||||
void Close(void);
|
||||
bool Start(char *filename, int vpid, int vtype, int apid, int ac3, int duration, std::string headers = "");
|
||||
bool Start(std::string filename, std::string headers = "");
|
||||
bool Play(void);
|
||||
bool SyncAV(void);
|
||||
|
||||
bool Stop(void);
|
||||
bool SetAPid(int pid, bool ac3);
|
||||
bool SetSubtitlePid(int pid);
|
||||
bool SetTeletextPid(int pid);
|
||||
|
||||
void trickSeek(int ratio);
|
||||
bool SetSpeed(int speed);
|
||||
bool SetSlow(int slow);
|
||||
bool GetSpeed(int &speed) const;
|
||||
bool GetPosition(int &position, int &duration);
|
||||
void GetPts(uint64_t &pts);
|
||||
int GetAPid(void);
|
||||
int GetVPid(void);
|
||||
int GetSubtitlePid(void);
|
||||
bool SetPosition(int position, bool absolute = false);
|
||||
void FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *numpida, std::string *language);
|
||||
void FindAllSubtitlePids(int *pids, unsigned int *numpids, std::string *language);
|
||||
void FindAllTeletextsubtitlePids(int *pids, unsigned int *numpidt, std::string *tlanguage, int *mags, int *pages);
|
||||
void RequestAbort(void);
|
||||
void FindAllSubs(uint16_t *pids, unsigned short *supported, uint16_t *numpida, std::string *language);
|
||||
bool SelectSubtitles(int pid);
|
||||
uint64_t GetReadCount(void);
|
||||
void GetChapters(std::vector<int> &positions, std::vector<std::string> &titles);
|
||||
void GetMetadata(std::vector<std::string> &keys, std::vector<std::string> &values);
|
||||
AVFormatContext *GetAVFormatContext();
|
||||
void ReleaseAVFormatContext();
|
||||
std::string extra_headers;
|
||||
std::string user_agent;
|
||||
|
||||
//
|
||||
~cPlayback();
|
||||
void getMeta();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -1,822 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <syscall.h>
|
||||
|
||||
#include "dmx_lib.h"
|
||||
#include "audio_lib.h"
|
||||
#include "video_lib.h"
|
||||
#include "glfb.h"
|
||||
|
||||
#include "playback_gst.h"
|
||||
|
||||
#include "lt_debug.h"
|
||||
#define lt_debug(args...) _lt_debug(HAL_DEBUG_PLAYBACK, this, args)
|
||||
#define lt_info(args...) _lt_info(HAL_DEBUG_PLAYBACK, this, args)
|
||||
#define lt_debug_c(args...) _lt_debug(HAL_DEBUG_PLAYBACK, NULL, args)
|
||||
#define lt_info_c(args...) _lt_info(HAL_DEBUG_PLAYBACK, NULL, args)
|
||||
|
||||
static const char * FILENAME = "[playback.cpp]";
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/pbutils/missing-plugins.h>
|
||||
#include <gst/interfaces/xoverlay.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GST_PLAY_FLAG_VIDEO = 0x00000001,
|
||||
GST_PLAY_FLAG_AUDIO = 0x00000002,
|
||||
GST_PLAY_FLAG_TEXT = 0x00000004,
|
||||
GST_PLAY_FLAG_VIS = 0x00000008,
|
||||
GST_PLAY_FLAG_SOFT_VOLUME = 0x00000010,
|
||||
GST_PLAY_FLAG_NATIVE_AUDIO = 0x00000020,
|
||||
GST_PLAY_FLAG_NATIVE_VIDEO = 0x00000040,
|
||||
GST_PLAY_FLAG_DOWNLOAD = 0x00000080,
|
||||
GST_PLAY_FLAG_BUFFERING = 0x000000100
|
||||
} GstPlayFlags;
|
||||
|
||||
|
||||
GstElement * m_gst_playbin = NULL;
|
||||
GstElement * audioSink = NULL;
|
||||
GstElement * videoSink = NULL;
|
||||
gchar * uri = NULL;
|
||||
GstTagList * m_stream_tags = 0;
|
||||
static int end_eof = 0;
|
||||
|
||||
extern GLFramebuffer *glfb;
|
||||
|
||||
gint match_sinktype(GstElement *element, gpointer type)
|
||||
{
|
||||
return strcmp(g_type_name(G_OBJECT_TYPE(element)), (const char*)type);
|
||||
}
|
||||
GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data)
|
||||
{
|
||||
gchar * sourceName;
|
||||
|
||||
// source
|
||||
GstObject * source;
|
||||
source = GST_MESSAGE_SRC(msg);
|
||||
|
||||
if (!GST_IS_OBJECT(source))
|
||||
return GST_BUS_DROP;
|
||||
|
||||
sourceName = gst_object_get_name(source);
|
||||
|
||||
switch (GST_MESSAGE_TYPE(msg))
|
||||
{
|
||||
case GST_MESSAGE_EOS:
|
||||
{
|
||||
g_message("End-of-stream");
|
||||
end_eof = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case GST_MESSAGE_ERROR:
|
||||
{
|
||||
gchar * debug;
|
||||
GError *err;
|
||||
gst_message_parse_error(msg, &err, &debug);
|
||||
g_free (debug);
|
||||
lt_info_c( "%s:%s - GST_MESSAGE_ERROR: %s (%i) from %s\n", FILENAME, __FUNCTION__, err->message, err->code, sourceName );
|
||||
if ( err->domain == GST_STREAM_ERROR )
|
||||
{
|
||||
if ( err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND )
|
||||
{
|
||||
if ( g_strrstr(sourceName, "videosink") )
|
||||
lt_info_c( "%s:%s - GST_MESSAGE_ERROR: videosink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event???
|
||||
else if ( g_strrstr(sourceName, "audiosink") )
|
||||
lt_info_c( "%s:%s - GST_MESSAGE_ERROR: audioSink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event???
|
||||
}
|
||||
}
|
||||
g_error_free(err);
|
||||
|
||||
end_eof = 1; // NOTE: just to exit
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case GST_MESSAGE_INFO:
|
||||
{
|
||||
gchar *debug;
|
||||
GError *inf;
|
||||
|
||||
gst_message_parse_info (msg, &inf, &debug);
|
||||
g_free (debug);
|
||||
if ( inf->domain == GST_STREAM_ERROR && inf->code == GST_STREAM_ERROR_DECODE )
|
||||
{
|
||||
if ( g_strrstr(sourceName, "videosink") )
|
||||
lt_info_c( "%s:%s - GST_MESSAGE_INFO: videosink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event???
|
||||
}
|
||||
g_error_free(inf);
|
||||
break;
|
||||
}
|
||||
|
||||
case GST_MESSAGE_TAG:
|
||||
{
|
||||
GstTagList *tags, *result;
|
||||
gst_message_parse_tag(msg, &tags);
|
||||
|
||||
result = gst_tag_list_merge(m_stream_tags, tags, GST_TAG_MERGE_REPLACE);
|
||||
if (result)
|
||||
{
|
||||
if (m_stream_tags)
|
||||
gst_tag_list_free(m_stream_tags);
|
||||
m_stream_tags = result;
|
||||
}
|
||||
|
||||
const GValue *gv_image = gst_tag_list_get_value_index(tags, GST_TAG_IMAGE, 0);
|
||||
if ( gv_image )
|
||||
{
|
||||
GstBuffer *buf_image;
|
||||
buf_image = gst_value_get_buffer (gv_image);
|
||||
int fd = open("/tmp/.id3coverart", O_CREAT|O_WRONLY|O_TRUNC, 0644);
|
||||
if(fd >= 0)
|
||||
{
|
||||
int ret = write(fd, GST_BUFFER_DATA(buf_image), GST_BUFFER_SIZE(buf_image));
|
||||
close(fd);
|
||||
lt_info_c( "%s:%s - GST_MESSAGE_INFO: cPlayback::state /tmp/.id3coverart %d bytes written\n", FILENAME, __FUNCTION__ , ret);
|
||||
}
|
||||
//FIXME: how shall playback handle this event???
|
||||
}
|
||||
gst_tag_list_free(tags);
|
||||
lt_info_c( "%s:%s - GST_MESSAGE_INFO: update info tags\n", FILENAME, __FUNCTION__); //FIXME: how shall playback handle this event???
|
||||
break;
|
||||
}
|
||||
|
||||
case GST_MESSAGE_STATE_CHANGED:
|
||||
{
|
||||
if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin))
|
||||
break;
|
||||
|
||||
GstState old_state, new_state;
|
||||
gst_message_parse_state_changed(msg, &old_state, &new_state, NULL);
|
||||
|
||||
if(old_state == new_state)
|
||||
break;
|
||||
lt_info_c( "%s:%s - GST_MESSAGE_STATE_CHANGED: state transition %s -> %s\n", FILENAME, __FUNCTION__, gst_element_state_get_name(old_state), gst_element_state_get_name(new_state));
|
||||
|
||||
GstStateChange transition = (GstStateChange)GST_STATE_TRANSITION(old_state, new_state);
|
||||
|
||||
switch(transition)
|
||||
{
|
||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
||||
{
|
||||
} break;
|
||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||
{
|
||||
GstIterator *children;
|
||||
if (audioSink)
|
||||
{
|
||||
gst_object_unref(GST_OBJECT(audioSink));
|
||||
audioSink = NULL;
|
||||
}
|
||||
|
||||
if (videoSink)
|
||||
{
|
||||
gst_object_unref(GST_OBJECT(videoSink));
|
||||
videoSink = NULL;
|
||||
}
|
||||
children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin));
|
||||
audioSink = GST_ELEMENT_CAST(gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, (gpointer)"GstDVBAudioSink"));
|
||||
videoSink = GST_ELEMENT_CAST(gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, (gpointer)"GstDVBVideoSink"));
|
||||
gst_iterator_free(children);
|
||||
|
||||
} break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
||||
{
|
||||
} break;
|
||||
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
|
||||
{
|
||||
} break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||
{
|
||||
if (audioSink)
|
||||
{
|
||||
gst_object_unref(GST_OBJECT(audioSink));
|
||||
audioSink = NULL;
|
||||
}
|
||||
if (videoSink)
|
||||
{
|
||||
gst_object_unref(GST_OBJECT(videoSink));
|
||||
videoSink = NULL;
|
||||
}
|
||||
} break;
|
||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
||||
{
|
||||
} break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
case GST_MESSAGE_ELEMENT:
|
||||
{
|
||||
if(gst_structure_has_name(gst_message_get_structure(msg), "prepare-xwindow-id"))
|
||||
{
|
||||
// set window id
|
||||
gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(GST_MESSAGE_SRC (msg)), glfb->getWindowID());
|
||||
|
||||
// reshape window
|
||||
gst_x_overlay_set_render_rectangle(GST_X_OVERLAY(GST_MESSAGE_SRC (msg)), 0, 0, glfb->getOSDWidth(), glfb->getOSDHeight());
|
||||
|
||||
// sync frames
|
||||
gst_x_overlay_expose(GST_X_OVERLAY(GST_MESSAGE_SRC (msg)));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return GST_BUS_DROP;
|
||||
}
|
||||
|
||||
|
||||
cPlayback::cPlayback(int num)
|
||||
{
|
||||
lt_info( "%s:%s\n", FILENAME, __FUNCTION__);
|
||||
const gchar *nano_str;
|
||||
guint major, minor, micro, nano;
|
||||
|
||||
gst_init(NULL, NULL);
|
||||
|
||||
gst_version (&major, &minor, µ, &nano);
|
||||
|
||||
if (nano == 1)
|
||||
nano_str = "(CVS)";
|
||||
else if (nano == 2)
|
||||
nano_str = "(Prerelease)";
|
||||
else
|
||||
nano_str = "";
|
||||
|
||||
lt_info( "%s:%s - This program is linked against GStreamer %d.%d.%d %s\n",
|
||||
FILENAME, __FUNCTION__,
|
||||
major, minor, micro, nano_str);
|
||||
|
||||
mAudioStream = 0;
|
||||
mSpeed = 0;
|
||||
|
||||
playing = false;
|
||||
playstate = STATE_STOP;
|
||||
}
|
||||
|
||||
cPlayback::~cPlayback()
|
||||
{
|
||||
lt_info( "%s:%s\n", FILENAME, __FUNCTION__);
|
||||
//FIXME: all deleting stuff is done in Close()
|
||||
}
|
||||
|
||||
//Used by Fileplay
|
||||
bool cPlayback::Open(playmode_t PlayMode)
|
||||
{
|
||||
lt_info("%s: PlayMode %d\n", __func__, PlayMode);
|
||||
return true;
|
||||
}
|
||||
|
||||
// used by movieplay
|
||||
void cPlayback::Close(void)
|
||||
{
|
||||
lt_info( "%s:%s\n", FILENAME, __FUNCTION__);
|
||||
|
||||
Stop();
|
||||
|
||||
// disconnect bus handler
|
||||
if (m_gst_playbin)
|
||||
{
|
||||
// disconnect sync handler callback
|
||||
GstBus * bus = gst_pipeline_get_bus(GST_PIPELINE (m_gst_playbin));
|
||||
gst_bus_set_sync_handler(bus, NULL, NULL);
|
||||
gst_object_unref(bus);
|
||||
lt_info( "%s:%s - GST bus handler closed\n", FILENAME, __FUNCTION__);
|
||||
}
|
||||
|
||||
if (m_stream_tags)
|
||||
gst_tag_list_free(m_stream_tags);
|
||||
|
||||
// close gst
|
||||
if (m_gst_playbin)
|
||||
{
|
||||
if (audioSink)
|
||||
{
|
||||
gst_object_unref(GST_OBJECT(audioSink));
|
||||
audioSink = NULL;
|
||||
|
||||
lt_info( "%s:%s - GST audio Sink closed\n", FILENAME, __FUNCTION__);
|
||||
}
|
||||
|
||||
if (videoSink)
|
||||
{
|
||||
gst_object_unref(GST_OBJECT(videoSink));
|
||||
videoSink = NULL;
|
||||
|
||||
lt_info( "%s:%s - GST video Sink closed\n", FILENAME, __FUNCTION__);
|
||||
}
|
||||
|
||||
// unref m_gst_playbin
|
||||
gst_object_unref (GST_OBJECT (m_gst_playbin));
|
||||
lt_info( "%s:%s - GST playbin closed\n", FILENAME, __FUNCTION__);
|
||||
|
||||
m_gst_playbin = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// start
|
||||
bool cPlayback::Start(std::string filename, std::string headers)
|
||||
{
|
||||
return Start((char*) filename.c_str(),0,0,0,0,0, headers);
|
||||
}
|
||||
|
||||
bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, int /*ac3*/, int /*duration*/, std::string headers)
|
||||
{
|
||||
lt_info( "%s:%s\n", FILENAME, __FUNCTION__);
|
||||
|
||||
mAudioStream = 0;
|
||||
|
||||
//create playback path
|
||||
char file[400] = {""};
|
||||
bool isHTTP = false;
|
||||
|
||||
if(!strncmp("http://", filename, 7))
|
||||
{
|
||||
isHTTP = true;
|
||||
}
|
||||
else if(!strncmp("file://", filename, 7))
|
||||
{
|
||||
isHTTP = false;
|
||||
}
|
||||
else if(!strncmp("upnp://", filename, 7))
|
||||
{
|
||||
isHTTP = true;
|
||||
}
|
||||
else if(!strncmp("rtmp://", filename, 7))
|
||||
{
|
||||
isHTTP = true;
|
||||
}
|
||||
else if(!strncmp("rtsp://", filename, 7))
|
||||
{
|
||||
isHTTP = true;
|
||||
}
|
||||
else if(!strncmp("mms://", filename, 6))
|
||||
{
|
||||
isHTTP = true;
|
||||
}
|
||||
else
|
||||
strcat(file, "file://");
|
||||
|
||||
strcat(file, filename);
|
||||
|
||||
if (isHTTP)
|
||||
uri = g_uri_escape_string(filename, G_URI_RESERVED_CHARS_GENERIC_DELIMITERS, true);
|
||||
else
|
||||
uri = g_filename_to_uri(filename, NULL, NULL);
|
||||
|
||||
lt_info("%s:%s - filename=%s\n", FILENAME, __FUNCTION__, filename);
|
||||
|
||||
// create gst pipeline
|
||||
m_gst_playbin = gst_element_factory_make("playbin2", "playbin");
|
||||
|
||||
if(m_gst_playbin)
|
||||
{
|
||||
lt_info("%s:%s - m_gst_playbin\n", FILENAME, __FUNCTION__);
|
||||
|
||||
guint flags;
|
||||
g_object_get(G_OBJECT (m_gst_playbin), "flags", &flags, NULL);
|
||||
/* avoid video conversion, let the (hardware) sinks handle that */
|
||||
flags |= GST_PLAY_FLAG_NATIVE_VIDEO;
|
||||
/* volume control is done by hardware */
|
||||
flags &= ~GST_PLAY_FLAG_SOFT_VOLUME;
|
||||
|
||||
g_object_set(G_OBJECT (m_gst_playbin), "uri", uri, NULL);
|
||||
g_object_set(G_OBJECT (m_gst_playbin), "flags", flags, NULL);
|
||||
|
||||
//gstbus handler
|
||||
GstBus * bus = gst_pipeline_get_bus( GST_PIPELINE(m_gst_playbin) );
|
||||
gst_bus_set_sync_handler(bus, Gst_bus_call, NULL);
|
||||
gst_object_unref(bus);
|
||||
|
||||
// state playing
|
||||
gst_element_set_state(GST_ELEMENT(m_gst_playbin), GST_STATE_PLAYING);
|
||||
|
||||
playing = true;
|
||||
playstate = STATE_PLAY;
|
||||
}
|
||||
else
|
||||
{
|
||||
lt_info("%s:%s - failed to create GStreamer pipeline!, sorry we can not play\n", FILENAME, __FUNCTION__);
|
||||
playing = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
g_free(uri);
|
||||
|
||||
// set buffer size
|
||||
/* increase the default 2 second / 2 MB buffer limitations to 5s / 5MB */
|
||||
int m_buffer_size = 5*1024*1024;
|
||||
//g_object_set(G_OBJECT(m_gst_playbin), "buffer-duration", 5LL * GST_SECOND, NULL);
|
||||
g_object_set(G_OBJECT(m_gst_playbin), "buffer-size", m_buffer_size, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cPlayback::Play(void)
|
||||
{
|
||||
lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing);
|
||||
|
||||
if(playing == true)
|
||||
return true;
|
||||
|
||||
if(m_gst_playbin)
|
||||
{
|
||||
gst_element_set_state(GST_ELEMENT(m_gst_playbin), GST_STATE_PLAYING);
|
||||
|
||||
playing = true;
|
||||
playstate = STATE_PLAY;
|
||||
}
|
||||
lt_info("%s:%s playing %d\n", FILENAME, __FUNCTION__, playing);
|
||||
|
||||
return playing;
|
||||
}
|
||||
|
||||
bool cPlayback::Stop(void)
|
||||
{
|
||||
if(playing == false)
|
||||
return false;
|
||||
lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing);
|
||||
|
||||
// stop
|
||||
if(m_gst_playbin)
|
||||
{
|
||||
gst_element_set_state(m_gst_playbin, GST_STATE_NULL);
|
||||
}
|
||||
|
||||
playing = false;
|
||||
|
||||
lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing);
|
||||
|
||||
playstate = STATE_STOP;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cPlayback::SetAPid(int pid , bool /*ac3*/)
|
||||
{
|
||||
lt_info("%s: pid %i\n", __func__, pid);
|
||||
|
||||
int current_audio;
|
||||
|
||||
if(pid != mAudioStream)
|
||||
{
|
||||
g_object_set (G_OBJECT (m_gst_playbin), "current-audio", pid, NULL);
|
||||
printf("%s: switched to audio stream %i\n", __FUNCTION__, pid);
|
||||
mAudioStream = pid;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cPlayback::trickSeek(int ratio)
|
||||
{
|
||||
bool validposition = false;
|
||||
gint64 pos = 0;
|
||||
int position;
|
||||
int duration;
|
||||
|
||||
if( GetPosition(position, duration) )
|
||||
{
|
||||
validposition = true;
|
||||
pos = position;
|
||||
}
|
||||
|
||||
gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING);
|
||||
|
||||
if (validposition)
|
||||
{
|
||||
if(ratio >= 0.0)
|
||||
gst_element_seek(m_gst_playbin, ratio, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_SET, -1);
|
||||
else
|
||||
gst_element_seek(m_gst_playbin, ratio, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, pos);
|
||||
}
|
||||
}
|
||||
|
||||
bool cPlayback::SetSpeed(int speed)
|
||||
{
|
||||
lt_info( "%s:%s speed %d\n", FILENAME, __FUNCTION__, speed);
|
||||
|
||||
if(playing == false)
|
||||
return false;
|
||||
|
||||
if(m_gst_playbin)
|
||||
{
|
||||
// pause
|
||||
if(speed == 0)
|
||||
{
|
||||
gst_element_set_state(m_gst_playbin, GST_STATE_PAUSED);
|
||||
//trickSeek(0);
|
||||
playstate = STATE_PAUSE;
|
||||
}
|
||||
// play/continue
|
||||
else if(speed == 1)
|
||||
{
|
||||
trickSeek(1);
|
||||
//gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING);
|
||||
//
|
||||
playstate = STATE_PLAY;
|
||||
}
|
||||
//ff
|
||||
else if(speed > 1)
|
||||
{
|
||||
trickSeek(speed);
|
||||
//
|
||||
playstate = STATE_FF;
|
||||
}
|
||||
//rf
|
||||
else if(speed < 0)
|
||||
{
|
||||
trickSeek(speed);
|
||||
//
|
||||
playstate = STATE_REW;
|
||||
}
|
||||
}
|
||||
|
||||
mSpeed = speed;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cPlayback::SetSlow(int slow)
|
||||
{
|
||||
lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing);
|
||||
|
||||
if(playing == false)
|
||||
return false;
|
||||
|
||||
if(m_gst_playbin)
|
||||
{
|
||||
trickSeek(0.5);
|
||||
}
|
||||
|
||||
playstate = STATE_SLOW;
|
||||
|
||||
mSpeed = slow;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cPlayback::GetSpeed(int &speed) const
|
||||
{
|
||||
speed = mSpeed;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// in milliseconds
|
||||
bool cPlayback::GetPosition(int &position, int &duration)
|
||||
{
|
||||
if(playing == false)
|
||||
return false;
|
||||
|
||||
//EOF
|
||||
if(end_eof)
|
||||
{
|
||||
end_eof = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(m_gst_playbin)
|
||||
{
|
||||
//position
|
||||
GstFormat fmt = GST_FORMAT_TIME; //Returns time in nanosecs
|
||||
|
||||
gint64 pts = 0;
|
||||
unsigned long long int sec = 0;
|
||||
|
||||
gst_element_query_position(m_gst_playbin, &fmt, &pts);
|
||||
position = pts / 1000000.0;
|
||||
|
||||
// duration
|
||||
GstFormat fmt_d = GST_FORMAT_TIME; //Returns time in nanosecs
|
||||
double length = 0;
|
||||
gint64 len;
|
||||
|
||||
gst_element_query_duration(m_gst_playbin, &fmt_d, &len);
|
||||
length = len / 1000000.0;
|
||||
if(length < 0)
|
||||
length = 0;
|
||||
|
||||
duration = (int)(length);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cPlayback::SetPosition(int position, bool absolute)
|
||||
{
|
||||
lt_info("%s: pos %d abs %d playing %d\n", __func__, position, absolute, playing);
|
||||
|
||||
if(playing == false)
|
||||
return false;
|
||||
|
||||
gint64 time_nanoseconds;
|
||||
gint64 pos;
|
||||
GstFormat fmt = GST_FORMAT_TIME;
|
||||
|
||||
if(m_gst_playbin)
|
||||
{
|
||||
gst_element_query_position(m_gst_playbin, &fmt, &pos);
|
||||
time_nanoseconds = pos + (position * 1000000.0);
|
||||
if(time_nanoseconds < 0)
|
||||
time_nanoseconds = 0;
|
||||
|
||||
gst_element_seek(m_gst_playbin, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, time_nanoseconds, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *numpida, std::string * language)
|
||||
{
|
||||
lt_info( "%s:%s\n", FILENAME, __FUNCTION__);
|
||||
|
||||
if(m_gst_playbin)
|
||||
{
|
||||
gint i, n_audio = 0;
|
||||
//GstStructure * structure = NULL;
|
||||
|
||||
// get audio
|
||||
g_object_get (m_gst_playbin, "n-audio", &n_audio, NULL);
|
||||
printf("%s: %d audio\n", __FUNCTION__, n_audio);
|
||||
|
||||
if(n_audio == 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < n_audio; i++)
|
||||
{
|
||||
// apids
|
||||
apids[i]=i;
|
||||
|
||||
GstPad * pad = 0;
|
||||
g_signal_emit_by_name (m_gst_playbin, "get-audio-pad", i, &pad);
|
||||
GstCaps * caps = gst_pad_get_negotiated_caps(pad);
|
||||
if (!caps)
|
||||
continue;
|
||||
|
||||
GstStructure * structure = gst_caps_get_structure(caps, 0);
|
||||
//const gchar *g_type = gst_structure_get_name(structure);
|
||||
|
||||
//if (!structure)
|
||||
//return atUnknown;
|
||||
//ac3flags[0] = 0;
|
||||
|
||||
// ac3flags
|
||||
if ( gst_structure_has_name (structure, "audio/mpeg"))
|
||||
{
|
||||
gint mpegversion, layer = -1;
|
||||
|
||||
if (!gst_structure_get_int (structure, "mpegversion", &mpegversion))
|
||||
//return atUnknown;
|
||||
ac3flags[i] = 0;
|
||||
|
||||
switch (mpegversion)
|
||||
{
|
||||
case 1:
|
||||
/*
|
||||
{
|
||||
gst_structure_get_int (structure, "layer", &layer);
|
||||
if ( layer == 3 )
|
||||
return atMP3;
|
||||
else
|
||||
return atMPEG;
|
||||
ac3flags[0] = 4;
|
||||
break;
|
||||
}
|
||||
*/
|
||||
ac3flags[i] = 4;
|
||||
case 2:
|
||||
//return atAAC;
|
||||
ac3flags[i] = 5;
|
||||
case 4:
|
||||
//return atAAC;
|
||||
ac3flags[i] = 5;
|
||||
default:
|
||||
//return atUnknown;
|
||||
ac3flags[i] = 0;
|
||||
}
|
||||
}
|
||||
else if ( gst_structure_has_name (structure, "audio/x-ac3") || gst_structure_has_name (structure, "audio/ac3") )
|
||||
//return atAC3;
|
||||
ac3flags[i] = 1;
|
||||
else if ( gst_structure_has_name (structure, "audio/x-dts") || gst_structure_has_name (structure, "audio/dts") )
|
||||
//return atDTS;
|
||||
ac3flags[i] = 6;
|
||||
else if ( gst_structure_has_name (structure, "audio/x-raw-int") )
|
||||
//return atPCM;
|
||||
ac3flags[i] = 0;
|
||||
|
||||
gst_caps_unref(caps);
|
||||
}
|
||||
|
||||
// numpids
|
||||
*numpida=i;
|
||||
}
|
||||
}
|
||||
|
||||
void cPlayback::getMeta()
|
||||
{
|
||||
if(playing)
|
||||
return;
|
||||
}
|
||||
|
||||
bool cPlayback::SyncAV(void)
|
||||
{
|
||||
lt_info( "%s:%s playing %d\n", FILENAME, __FUNCTION__, playing);
|
||||
|
||||
if(playing == false )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cPlayback::RequestAbort()
|
||||
{
|
||||
}
|
||||
|
||||
void cPlayback::FindAllSubs(uint16_t *, unsigned short *, uint16_t *numpida, std::string *)
|
||||
{
|
||||
printf("%s:%s\n", FILENAME, __func__);
|
||||
*numpida = 0;
|
||||
}
|
||||
|
||||
void cPlayback::GetChapters(std::vector<int> &positions, std::vector<std::string> &titles)
|
||||
{
|
||||
positions.clear();
|
||||
titles.clear();
|
||||
}
|
||||
|
||||
bool cPlayback::SelectSubtitles(int pid)
|
||||
{
|
||||
printf("%s:%s pid %i\n", FILENAME, __func__, pid);
|
||||
return true;
|
||||
}
|
||||
|
||||
void cPlayback::GetMetadata(std::vector<std::string> &keys, std::vector<std::string> &values)
|
||||
{
|
||||
keys.clear();
|
||||
values.clear();
|
||||
}
|
||||
|
||||
void cPlayback::FindAllTeletextsubtitlePids(int *, unsigned int *numpids, std::string *, int *, int *)
|
||||
{
|
||||
*numpids = 0;
|
||||
}
|
||||
|
||||
void cPlayback::FindAllSubtitlePids(int * /*pids*/, unsigned int *numpids, std::string * /*language*/)
|
||||
{
|
||||
*numpids = 0;
|
||||
}
|
||||
|
||||
bool cPlayback::SetSubtitlePid(int /*pid*/)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void cPlayback::GetPts(uint64_t &/*pts*/)
|
||||
{
|
||||
}
|
||||
|
||||
bool cPlayback::SetTeletextPid(int /*pid*/)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t cPlayback::GetReadCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
../libspark/pwrmngr.cpp
|
@@ -1 +0,0 @@
|
||||
../libspark/pwrmngr.h
|
@@ -1 +0,0 @@
|
||||
../libspark/record_lib.h
|
@@ -23,6 +23,7 @@
|
||||
* TODO: buffer handling surely needs some locking...
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
@@ -30,6 +31,7 @@
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
#include <libswscale/swscale.h>
|
||||
}
|
||||
|
||||
@@ -38,17 +40,26 @@ extern "C" {
|
||||
/* my own buf 256k */
|
||||
#define DMX_BUF_SZ 0x20000
|
||||
|
||||
#include "video_lib.h"
|
||||
#include "dmx_lib.h"
|
||||
#include "glfb.h"
|
||||
#if USE_OPENGL
|
||||
#define VDEC_PIXFMT AV_PIX_FMT_RGB32
|
||||
#endif
|
||||
#if USE_CLUTTER
|
||||
#define VDEC_PIXFMT AV_PIX_FMT_BGR24
|
||||
#endif
|
||||
|
||||
#include "video_hal.h"
|
||||
#include "dmx_hal.h"
|
||||
#include "glfb_priv.h"
|
||||
#include "video_priv.h"
|
||||
#include "lt_debug.h"
|
||||
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, this, args)
|
||||
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_VIDEO, this, args)
|
||||
#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_VIDEO, NULL, args)
|
||||
|
||||
VDec *vdec = NULL;
|
||||
cVideo *videoDecoder = NULL;
|
||||
extern cDemux *videoDemux;
|
||||
extern GLFramebuffer *glfb;
|
||||
extern GLFbPC *glfb_priv;
|
||||
int system_rev = 0;
|
||||
|
||||
extern bool HAL_nodec;
|
||||
@@ -68,6 +79,13 @@ static const AVRational aspect_ratios[6] = {
|
||||
cVideo::cVideo(int, void *, void *, unsigned int)
|
||||
{
|
||||
lt_debug("%s\n", __func__);
|
||||
vdec = new VDec();
|
||||
/* quick hack to export private stuff to other libstb-hal modules */
|
||||
::vdec = vdec;
|
||||
}
|
||||
|
||||
VDec::VDec()
|
||||
{
|
||||
av_register_all();
|
||||
if (!HAL_nodec)
|
||||
dmxbuf = (uint8_t *)malloc(DMX_BUF_SZ);
|
||||
@@ -79,20 +97,35 @@ cVideo::cVideo(int, void *, void *, unsigned int)
|
||||
buf_in = 0;
|
||||
buf_out = 0;
|
||||
pig_x = pig_y = pig_w = pig_h = 0;
|
||||
pig_changed = false;
|
||||
display_aspect = DISPLAY_AR_16_9;
|
||||
display_crop = DISPLAY_AR_MODE_LETTERBOX;
|
||||
v_format = VIDEO_FORMAT_MPEG2;
|
||||
output_h = 0;
|
||||
stillpicture = false;
|
||||
}
|
||||
|
||||
VDec::~VDec(void)
|
||||
{
|
||||
free(dmxbuf);
|
||||
}
|
||||
|
||||
cVideo::~cVideo(void)
|
||||
{
|
||||
Stop();
|
||||
/* ouch :-( */
|
||||
videoDecoder = NULL;
|
||||
// videoDecoder = NULL;
|
||||
delete vdec;
|
||||
::vdec = NULL;
|
||||
}
|
||||
|
||||
|
||||
int cVideo::setAspectRatio(int vformat, int cropping)
|
||||
{
|
||||
return vdec->setAspectRatio(vformat, cropping);
|
||||
}
|
||||
|
||||
int VDec::setAspectRatio(int vformat, int cropping)
|
||||
{
|
||||
lt_info("%s(%d, %d)\n", __func__, vformat, cropping);
|
||||
if (vformat >= 0)
|
||||
@@ -100,11 +133,16 @@ int cVideo::setAspectRatio(int vformat, int cropping)
|
||||
if (cropping >= 0)
|
||||
display_crop = (DISPLAY_AR_MODE) cropping;
|
||||
if (display_aspect < DISPLAY_AR_RAW && output_h > 0) /* don't know what to do with this */
|
||||
glfb->setOutputFormat(aspect_ratios[display_aspect], output_h, display_crop);
|
||||
glfb_priv->setOutputFormat(aspect_ratios[display_aspect], output_h, display_crop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cVideo::getAspectRatio(void)
|
||||
{
|
||||
return vdec->getAspectRatio();
|
||||
}
|
||||
|
||||
int VDec::getAspectRatio(void)
|
||||
{
|
||||
buf_m.lock();
|
||||
int ret = 0;
|
||||
@@ -133,26 +171,36 @@ int cVideo::getAspectRatio(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cVideo::setCroppingMode(int)
|
||||
int cVideo::setCroppingMode(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cVideo::Start(void *, unsigned short, unsigned short, void *)
|
||||
{
|
||||
return vdec->Start();
|
||||
}
|
||||
|
||||
int cVideo::Stop(bool b)
|
||||
{
|
||||
return vdec->Stop(b);
|
||||
}
|
||||
|
||||
int VDec::Start()
|
||||
{
|
||||
lt_debug("%s running %d >\n", __func__, thread_running);
|
||||
if (!thread_running && !HAL_nodec)
|
||||
Thread::startThread();
|
||||
OpenThreads::Thread::start();
|
||||
lt_debug("%s running %d <\n", __func__, thread_running);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cVideo::Stop(bool)
|
||||
int VDec::Stop(bool)
|
||||
{
|
||||
lt_debug("%s running %d >\n", __func__, thread_running);
|
||||
if (thread_running) {
|
||||
thread_running = false;
|
||||
Thread::joinThread();
|
||||
OpenThreads::Thread::join();
|
||||
}
|
||||
lt_debug("%s running %d <\n", __func__, thread_running);
|
||||
return 0;
|
||||
@@ -163,7 +211,29 @@ int cVideo::setBlank(int)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cVideo::GetVideoSystem()
|
||||
{
|
||||
return vdec->GetVideoSystem();
|
||||
}
|
||||
|
||||
int VDec::GetVideoSystem()
|
||||
{
|
||||
int current_video_system = VIDEO_STD_1080I50;
|
||||
|
||||
if(dec_w < 720)
|
||||
current_video_system = VIDEO_STD_PAL;
|
||||
else if(dec_w > 720 && dec_w <= 1280)
|
||||
current_video_system = VIDEO_STD_720P50;
|
||||
|
||||
return current_video_system;
|
||||
}
|
||||
|
||||
int cVideo::SetVideoSystem(int system, bool)
|
||||
{
|
||||
return vdec->SetVideoSystem(system);
|
||||
}
|
||||
|
||||
int VDec::SetVideoSystem(int system)
|
||||
{
|
||||
int h;
|
||||
switch(system)
|
||||
@@ -196,39 +266,39 @@ int cVideo::SetVideoSystem(int system, bool)
|
||||
lt_info("%s: unhandled value %d\n", __func__, system);
|
||||
return 0;
|
||||
}
|
||||
v_std = (VIDEO_STD) system;
|
||||
// v_std = (VIDEO_STD) system;
|
||||
output_h = h;
|
||||
if (display_aspect < DISPLAY_AR_RAW && output_h > 0) /* don't know what to do with this */
|
||||
glfb->setOutputFormat(aspect_ratios[display_aspect], output_h, display_crop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cVideo::GetVideoSystem()
|
||||
{
|
||||
int current_video_system = VIDEO_STD_1080I50;
|
||||
|
||||
if(dec_w < 720)
|
||||
current_video_system = VIDEO_STD_PAL;
|
||||
else if(dec_w > 720 && dec_w <= 1280)
|
||||
current_video_system = VIDEO_STD_720P50;
|
||||
|
||||
glfb_priv->setOutputFormat(aspect_ratios[display_aspect], output_h, display_crop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cVideo::getPlayState(void)
|
||||
{
|
||||
return VIDEO_PLAYING;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void cVideo::SetVideoMode(analog_mode_t)
|
||||
{
|
||||
}
|
||||
|
||||
void cVideo::ShowPicture(const char *fname, const char *)
|
||||
bool cVideo::ShowPicture(const char *fname)
|
||||
{
|
||||
return vdec->ShowPicture(fname);
|
||||
}
|
||||
|
||||
bool VDec::ShowPicture(const char *fname)
|
||||
{
|
||||
bool ret = false;
|
||||
lt_info("%s(%s)\n", __func__, fname);
|
||||
if (access(fname, R_OK))
|
||||
return;
|
||||
return ret;
|
||||
still_m.lock();
|
||||
stillpicture = true;
|
||||
buf_num = 0;
|
||||
buf_in = 0;
|
||||
buf_out = 0;
|
||||
still_m.unlock();
|
||||
|
||||
unsigned int i;
|
||||
int stream_id = -1;
|
||||
@@ -236,13 +306,14 @@ void cVideo::ShowPicture(const char *fname, const char *)
|
||||
int len;
|
||||
AVFormatContext *avfc = NULL;
|
||||
AVCodecContext *c = NULL;
|
||||
AVCodecParameters *p = NULL;
|
||||
AVCodec *codec;
|
||||
AVFrame *frame, *rgbframe;
|
||||
AVPacket avpkt;
|
||||
|
||||
if (avformat_open_input(&avfc, fname, NULL, NULL) < 0) {
|
||||
lt_info("%s: Could not open file %s\n", __func__, fname);
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (avformat_find_stream_info(avfc, NULL) < 0) {
|
||||
@@ -250,17 +321,18 @@ void cVideo::ShowPicture(const char *fname, const char *)
|
||||
goto out_close;
|
||||
}
|
||||
for (i = 0; i < avfc->nb_streams; i++) {
|
||||
if (avfc->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
if (avfc->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
stream_id = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stream_id < 0)
|
||||
goto out_close;
|
||||
c = avfc->streams[stream_id]->codec;
|
||||
codec = avcodec_find_decoder(c->codec_id);
|
||||
if (!avcodec_open2(c, codec, NULL) < 0) {
|
||||
lt_info("%s: Could not find/open the codec, id 0x%x\n", __func__, c->codec_id);
|
||||
p = avfc->streams[stream_id]->codecpar;
|
||||
codec = avcodec_find_decoder(p->codec_id);
|
||||
c = avcodec_alloc_context3(codec);
|
||||
if (avcodec_open2(c, codec, NULL) < 0) {
|
||||
lt_info("%s: Could not find/open the codec, id 0x%x\n", __func__, p->codec_id);
|
||||
goto out_close;
|
||||
}
|
||||
frame = av_frame_alloc();
|
||||
@@ -277,15 +349,15 @@ void cVideo::ShowPicture(const char *fname, const char *)
|
||||
len = avcodec_decode_video2(c, frame, &got_frame, &avpkt);
|
||||
if (len < 0) {
|
||||
lt_info("%s: avcodec_decode_video2 %d\n", __func__, len);
|
||||
av_free_packet(&avpkt);
|
||||
av_packet_unref(&avpkt);
|
||||
goto out_free;
|
||||
}
|
||||
if (avpkt.size > len)
|
||||
lt_info("%s: WARN: pkt->size %d != len %d\n", __func__, avpkt.size, len);
|
||||
if (got_frame) {
|
||||
unsigned int need = avpicture_get_size(PIX_FMT_RGB32, c->width, c->height);
|
||||
unsigned int need = av_image_get_buffer_size(VDEC_PIXFMT, c->width, c->height, 1);
|
||||
struct SwsContext *convert = sws_getContext(c->width, c->height, c->pix_fmt,
|
||||
c->width, c->height, PIX_FMT_RGB32,
|
||||
c->width, c->height, VDEC_PIXFMT,
|
||||
SWS_BICUBIC, 0, 0, 0);
|
||||
if (!convert)
|
||||
lt_info("%s: ERROR setting up SWS context\n", __func__);
|
||||
@@ -294,8 +366,8 @@ void cVideo::ShowPicture(const char *fname, const char *)
|
||||
SWFramebuffer *f = &buffers[buf_in];
|
||||
if (f->size() < need)
|
||||
f->resize(need);
|
||||
avpicture_fill((AVPicture *)rgbframe, &(*f)[0], PIX_FMT_RGB32,
|
||||
c->width, c->height);
|
||||
av_image_fill_arrays(rgbframe->data, rgbframe->linesize, &(*f)[0], VDEC_PIXFMT,
|
||||
c->width, c->height, 1);
|
||||
sws_scale(convert, frame->data, frame->linesize, 0, c->height,
|
||||
rgbframe->data, rgbframe->linesize);
|
||||
sws_freeContext(convert);
|
||||
@@ -308,26 +380,33 @@ void cVideo::ShowPicture(const char *fname, const char *)
|
||||
buf_in %= VDEC_MAXBUFS;
|
||||
buf_num++;
|
||||
if (buf_num > (VDEC_MAXBUFS - 1)) {
|
||||
lt_debug("%s: buf_num overflow\n", __func__);
|
||||
lt_info("%s: buf_num overflow\n", __func__);
|
||||
buf_out++;
|
||||
buf_out %= VDEC_MAXBUFS;
|
||||
buf_num--;
|
||||
}
|
||||
buf_m.unlock();
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
av_free_packet(&avpkt);
|
||||
av_packet_unref(&avpkt);
|
||||
out_free:
|
||||
avcodec_close(c);
|
||||
av_free(c);
|
||||
av_frame_free(&frame);
|
||||
av_frame_free(&rgbframe);
|
||||
out_close:
|
||||
avformat_close_input(&avfc);
|
||||
lt_debug("%s(%s) end\n", __func__, fname);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cVideo::StopPicture()
|
||||
{
|
||||
lt_info("%s\n", __func__);
|
||||
vdec->still_m.lock();
|
||||
vdec->stillpicture = false;
|
||||
vdec->still_m.unlock();
|
||||
}
|
||||
|
||||
void cVideo::Standby(unsigned int)
|
||||
@@ -339,19 +418,55 @@ int cVideo::getBlank(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cVideo::Pig(int x, int y, int w, int h, int /*osd_w*/, int /*osd_h*/, int /*startx*/, int /*starty*/, int /*endx*/, int /*endy*/)
|
||||
void cVideo::Pig(int x, int y, int w, int h, int, int)
|
||||
{
|
||||
vdec->Pig(x, y, w, h);
|
||||
}
|
||||
|
||||
void VDec::Pig(int x, int y, int w, int h)
|
||||
{
|
||||
pig_x = x;
|
||||
pig_y = y;
|
||||
pig_w = w;
|
||||
pig_h = h;
|
||||
pig_changed = true;
|
||||
}
|
||||
|
||||
void cVideo::getPictureInfo(int &width, int &height, int &rate)
|
||||
{
|
||||
vdec->getPictureInfo(width, height, rate);
|
||||
}
|
||||
|
||||
void VDec::getPictureInfo(int &width, int &height, int &rate)
|
||||
{
|
||||
width = dec_w;
|
||||
height = dec_h;
|
||||
rate = dec_r;
|
||||
switch (dec_r) {
|
||||
case 23://23.976fps
|
||||
rate = VIDEO_FRAME_RATE_23_976;
|
||||
break;
|
||||
case 24:
|
||||
rate = VIDEO_FRAME_RATE_24;
|
||||
break;
|
||||
case 25:
|
||||
rate = VIDEO_FRAME_RATE_25;
|
||||
break;
|
||||
case 29://29,976fps
|
||||
rate = VIDEO_FRAME_RATE_29_97;
|
||||
break;
|
||||
case 30:
|
||||
rate = VIDEO_FRAME_RATE_30;
|
||||
break;
|
||||
case 50:
|
||||
rate = VIDEO_FRAME_RATE_50;
|
||||
break;
|
||||
case 60:
|
||||
rate = VIDEO_FRAME_RATE_60;
|
||||
break;
|
||||
default:
|
||||
rate = dec_r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void cVideo::SetSyncMode(AVSYNC_TYPE)
|
||||
@@ -359,12 +474,17 @@ void cVideo::SetSyncMode(AVSYNC_TYPE)
|
||||
};
|
||||
|
||||
int cVideo::SetStreamType(VIDEO_FORMAT v)
|
||||
{
|
||||
return vdec->SetStreamType(v);
|
||||
}
|
||||
|
||||
int VDec::SetStreamType(VIDEO_FORMAT v)
|
||||
{
|
||||
v_format = v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
cVideo::SWFramebuffer *cVideo::getDecBuf(void)
|
||||
VDec::SWFramebuffer *VDec::getDecBuf(void)
|
||||
{
|
||||
buf_m.lock();
|
||||
if (buf_num == 0) {
|
||||
@@ -403,10 +523,11 @@ static int my_read(void *, uint8_t *buf, int buf_size)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void cVideo::run(void)
|
||||
void VDec::run(void)
|
||||
{
|
||||
lt_info("====================== start decoder thread ================================\n");
|
||||
AVCodec *codec;
|
||||
AVCodecParameters *p = NULL;
|
||||
AVCodecContext *c= NULL;
|
||||
AVFormatContext *avfc = NULL;
|
||||
AVInputFormat *inp;
|
||||
@@ -447,20 +568,21 @@ void cVideo::run(void)
|
||||
lt_info("%s: nb_streams %d, should be 1 => retry\n", __func__, avfc->nb_streams);
|
||||
if (av_read_frame(avfc, &avpkt) < 0)
|
||||
lt_info("%s: av_read_frame < 0\n", __func__);
|
||||
av_free_packet(&avpkt);
|
||||
av_packet_unref(&avpkt);
|
||||
if (! thread_running)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (avfc->streams[0]->codec->codec_type != AVMEDIA_TYPE_VIDEO)
|
||||
lt_info("%s: no video codec? 0x%x\n", __func__, avfc->streams[0]->codec->codec_type);
|
||||
p = avfc->streams[0]->codecpar;
|
||||
if (p->codec_type != AVMEDIA_TYPE_VIDEO)
|
||||
lt_info("%s: no video codec? 0x%x\n", __func__, p->codec_type);
|
||||
|
||||
c = avfc->streams[0]->codec;
|
||||
codec = avcodec_find_decoder(c->codec_id);
|
||||
codec = avcodec_find_decoder(p->codec_id);
|
||||
if (!codec) {
|
||||
lt_info("%s: Codec for %s not found\n", __func__, avcodec_get_name(c->codec_id));
|
||||
lt_info("%s: Codec for %s not found\n", __func__, avcodec_get_name(p->codec_id));
|
||||
goto out;
|
||||
}
|
||||
c = avcodec_alloc_context3(codec);
|
||||
if (avcodec_open2(c, codec, NULL) < 0) {
|
||||
lt_info("%s: Could not open codec\n", __func__);
|
||||
goto out;
|
||||
@@ -488,16 +610,17 @@ void cVideo::run(void)
|
||||
lt_info("%s: avcodec_decode_video2 %d\n", __func__, len);
|
||||
warn_d = time(NULL);
|
||||
}
|
||||
av_free_packet(&avpkt);
|
||||
av_packet_unref(&avpkt);
|
||||
continue;
|
||||
}
|
||||
if (avpkt.size > len)
|
||||
lt_info("%s: WARN: pkt->size %d != len %d\n", __func__, avpkt.size, len);
|
||||
if (got_frame) {
|
||||
unsigned int need = avpicture_get_size(PIX_FMT_RGB32, c->width, c->height);
|
||||
still_m.lock();
|
||||
if (got_frame && ! stillpicture) {
|
||||
unsigned int need = av_image_get_buffer_size(VDEC_PIXFMT, c->width, c->height, 1);
|
||||
convert = sws_getCachedContext(convert,
|
||||
c->width, c->height, c->pix_fmt,
|
||||
c->width, c->height, PIX_FMT_RGB32,
|
||||
c->width, c->height, VDEC_PIXFMT,
|
||||
SWS_BICUBIC, 0, 0, 0);
|
||||
if (!convert)
|
||||
lt_info("%s: ERROR setting up SWS context\n", __func__);
|
||||
@@ -506,8 +629,8 @@ void cVideo::run(void)
|
||||
SWFramebuffer *f = &buffers[buf_in];
|
||||
if (f->size() < need)
|
||||
f->resize(need);
|
||||
avpicture_fill((AVPicture *)rgbframe, &(*f)[0], PIX_FMT_RGB32,
|
||||
c->width, c->height);
|
||||
av_image_fill_arrays(rgbframe->data, rgbframe->linesize, &(*f)[0], VDEC_PIXFMT,
|
||||
c->width, c->height, 1);
|
||||
sws_scale(convert, frame->data, frame->linesize, 0, c->height,
|
||||
rgbframe->data, rgbframe->linesize);
|
||||
if (dec_w != c->width || dec_h != c->height) {
|
||||
@@ -520,8 +643,18 @@ void cVideo::run(void)
|
||||
f->width(c->width);
|
||||
f->height(c->height);
|
||||
int64_t vpts = av_frame_get_best_effort_timestamp(frame);
|
||||
/* a/v delay determined experimentally :-) */
|
||||
#if USE_OPENGL
|
||||
if (v_format == VIDEO_FORMAT_MPEG2)
|
||||
vpts += 90000*4/10; /* 400ms */
|
||||
else
|
||||
vpts += 90000*3/10; /* 300ms */
|
||||
#endif
|
||||
#if USE_CLUTTER
|
||||
/* no idea why there's a difference between OpenGL and clutter rendering... */
|
||||
if (v_format == VIDEO_FORMAT_MPEG2)
|
||||
vpts += 90000*3/10; /* 300ms */
|
||||
#endif
|
||||
f->pts(vpts);
|
||||
AVRational a = av_guess_sample_aspect_ratio(avfc, avfc->streams[0], frame);
|
||||
f->AR(a);
|
||||
@@ -529,7 +662,7 @@ void cVideo::run(void)
|
||||
buf_in %= VDEC_MAXBUFS;
|
||||
buf_num++;
|
||||
if (buf_num > (VDEC_MAXBUFS - 1)) {
|
||||
lt_debug("%s: buf_num overflow\n", __func__);
|
||||
lt_info("%s: buf_num overflow\n", __func__);
|
||||
buf_out++;
|
||||
buf_out %= VDEC_MAXBUFS;
|
||||
buf_num--;
|
||||
@@ -540,12 +673,15 @@ void cVideo::run(void)
|
||||
lt_debug("%s: time_base: %d/%d, ticks: %d rate: %d pts 0x%" PRIx64 "\n", __func__,
|
||||
c->time_base.num, c->time_base.den, c->ticks_per_frame, dec_r,
|
||||
av_frame_get_best_effort_timestamp(frame));
|
||||
}
|
||||
av_free_packet(&avpkt);
|
||||
} else
|
||||
lt_info("%s: got_frame: %d stillpicture: %d\n", __func__, got_frame, stillpicture);
|
||||
still_m.unlock();
|
||||
av_packet_unref(&avpkt);
|
||||
}
|
||||
sws_freeContext(convert);
|
||||
out2:
|
||||
avcodec_close(c);
|
||||
av_free(c);
|
||||
av_frame_free(&frame);
|
||||
av_frame_free(&rgbframe);
|
||||
out:
|
||||
@@ -554,39 +690,67 @@ void cVideo::run(void)
|
||||
av_free(pIOCtx);
|
||||
/* reset output buffers */
|
||||
bufpos = 0;
|
||||
buf_num = 0;
|
||||
buf_in = 0;
|
||||
buf_out = 0;
|
||||
still_m.lock();
|
||||
if (!stillpicture) {
|
||||
buf_num = 0;
|
||||
buf_in = 0;
|
||||
buf_out = 0;
|
||||
}
|
||||
still_m.unlock();
|
||||
lt_info("======================== end decoder thread ================================\n");
|
||||
}
|
||||
|
||||
static bool swscale(unsigned char *src, unsigned char *dst, int sw, int sh, int dw, int dh)
|
||||
static bool swscale(unsigned char *src, unsigned char *dst, int sw, int sh, int dw, int dh, AVPixelFormat sfmt)
|
||||
{
|
||||
bool ret = false;
|
||||
int len = 0;
|
||||
struct SwsContext *scale = NULL;
|
||||
AVFrame *sframe, *dframe;
|
||||
scale = sws_getCachedContext(scale, sw, sh, PIX_FMT_RGB32, dw, dh, PIX_FMT_RGB32, SWS_BICUBIC, 0, 0, 0);
|
||||
scale = sws_getCachedContext(scale, sw, sh, sfmt, dw, dh, AV_PIX_FMT_RGB32, SWS_BICUBIC, 0, 0, 0);
|
||||
if (!scale) {
|
||||
lt_info_c("%s: ERROR setting up SWS context\n", __func__);
|
||||
return false;
|
||||
return ret;
|
||||
}
|
||||
sframe = av_frame_alloc();
|
||||
dframe = av_frame_alloc();
|
||||
if (!sframe || !dframe) {
|
||||
AVFrame *sframe = av_frame_alloc();
|
||||
AVFrame *dframe = av_frame_alloc();
|
||||
if (sframe && dframe) {
|
||||
len = av_image_fill_arrays(sframe->data, sframe->linesize, &(src)[0], sfmt, sw, sh, 1);
|
||||
if(len>-1)
|
||||
ret = true;
|
||||
|
||||
if(ret && (len = av_image_fill_arrays(dframe->data, dframe->linesize, &(dst)[0], AV_PIX_FMT_RGB32, dw, dh, 1)<0))
|
||||
ret = false;
|
||||
|
||||
if(ret && (len = sws_scale(scale, sframe->data, sframe->linesize, 0, sh, dframe->data, dframe->linesize)<0))
|
||||
ret = false;
|
||||
else
|
||||
ret = true;
|
||||
}else{
|
||||
lt_info_c("%s: could not alloc sframe (%p) or dframe (%p)\n", __func__, sframe, dframe);
|
||||
goto out;
|
||||
ret = false;
|
||||
}
|
||||
avpicture_fill((AVPicture *)sframe, &(src[0]), PIX_FMT_RGB32, sw, sh);
|
||||
avpicture_fill((AVPicture *)dframe, &(dst[0]), PIX_FMT_RGB32, dw, dh);
|
||||
sws_scale(scale, sframe->data, sframe->linesize, 0, sh, dframe->data, dframe->linesize);
|
||||
out:
|
||||
av_frame_free(&sframe);
|
||||
av_frame_free(&dframe);
|
||||
sws_freeContext(scale);
|
||||
|
||||
if(sframe){
|
||||
av_frame_free(&sframe);
|
||||
sframe = NULL;
|
||||
}
|
||||
if(dframe){
|
||||
av_frame_free(&dframe);
|
||||
dframe = NULL;
|
||||
}
|
||||
if(scale){
|
||||
sws_freeContext(scale);
|
||||
scale = NULL;
|
||||
}
|
||||
lt_info_c("%s: %s scale %ix%i to %ix%i ,len %i\n",ret?" ":"ERROR",__func__, sw, sh, dw, dh,len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool cVideo::GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video, bool get_osd, bool scale_to_video)
|
||||
{
|
||||
return vdec->GetScreenImage(data, xres,yres,get_video,get_osd,scale_to_video);
|
||||
}
|
||||
|
||||
bool VDec::GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video, bool get_osd, bool scale_to_video)
|
||||
{
|
||||
lt_info("%s: data 0x%p xres %d yres %d vid %d osd %d scale %d\n",
|
||||
__func__, data, xres, yres, get_video, get_osd, scale_to_video);
|
||||
@@ -594,8 +758,8 @@ bool cVideo::GetScreenImage(unsigned char * &data, int &xres, int &yres, bool ge
|
||||
std::vector<unsigned char> *osd = NULL;
|
||||
std::vector<unsigned char> s_osd; /* scaled OSD */
|
||||
int vid_w = 0, vid_h = 0;
|
||||
int osd_w = glfb->getOSDWidth();
|
||||
int osd_h = glfb->getOSDHeight();
|
||||
int osd_w = glfb_priv->getOSDWidth();
|
||||
int osd_h = glfb_priv->getOSDHeight();
|
||||
xres = osd_w;
|
||||
yres = osd_h;
|
||||
if (get_video) {
|
||||
@@ -613,24 +777,42 @@ bool cVideo::GetScreenImage(unsigned char * &data, int &xres, int &yres, bool ge
|
||||
xres = vid_w * a.num / a.den;
|
||||
}
|
||||
}
|
||||
if(video.empty()){
|
||||
get_video=false;
|
||||
xres = osd_w;
|
||||
yres = osd_h;
|
||||
}
|
||||
if (get_osd)
|
||||
osd = glfb->getOSDBuffer();
|
||||
unsigned int need = avpicture_get_size(PIX_FMT_RGB32, xres, yres);
|
||||
osd = glfb_priv->getOSDBuffer();
|
||||
unsigned int need = av_image_get_buffer_size(AV_PIX_FMT_RGB32, xres, yres, 1);
|
||||
data = (unsigned char *)realloc(data, need); /* will be freed by caller */
|
||||
if (data == NULL) /* out of memory? */
|
||||
return false;
|
||||
|
||||
if (get_video) {
|
||||
if (vid_w != xres || vid_h != yres) /* scale video into data... */
|
||||
swscale(&video[0], data, vid_w, vid_h, xres, yres);
|
||||
else /* get_video and no fancy scaling needed */
|
||||
#if USE_OPENGL //memcpy dont work with copy BGR24 to RGB32
|
||||
if (vid_w != xres || vid_h != yres){ /* scale video into data... */
|
||||
#endif
|
||||
bool ret = swscale(&video[0], data, vid_w, vid_h, xres, yres,VDEC_PIXFMT);
|
||||
if(!ret){
|
||||
free(data);
|
||||
return false;
|
||||
}
|
||||
#if USE_OPENGL //memcpy dont work with copy BGR24 to RGB32
|
||||
}else{ /* get_video and no fancy scaling needed */
|
||||
memcpy(data, &video[0], xres * yres * sizeof(uint32_t));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (get_osd && (osd_w != xres || osd_h != yres)) {
|
||||
/* rescale osd */
|
||||
s_osd.resize(need);
|
||||
swscale(&(*osd)[0], &s_osd[0], osd_w, osd_h, xres, yres);
|
||||
bool ret = swscale(&(*osd)[0], &s_osd[0], osd_w, osd_h, xres, yres,AV_PIX_FMT_RGB32);
|
||||
if(!ret){
|
||||
free(data);
|
||||
return false;
|
||||
}
|
||||
osd = &s_osd;
|
||||
}
|
||||
|
||||
@@ -664,7 +846,7 @@ bool cVideo::GetScreenImage(unsigned char * &data, int &xres, int &yres, bool ge
|
||||
return true;
|
||||
}
|
||||
|
||||
int64_t cVideo::GetPTS(void)
|
||||
int64_t VDec::GetPTS(void)
|
||||
{
|
||||
int64_t pts = 0;
|
||||
buf_m.lock();
|
||||
|
@@ -1,223 +0,0 @@
|
||||
#ifndef _VIDEO_TD_H
|
||||
#define _VIDEO_TD_H
|
||||
|
||||
#include <thread_abstraction.h>
|
||||
#include <mutex_abstraction.h>
|
||||
#include <vector>
|
||||
#include <linux/dvb/video.h>
|
||||
#include "../common/cs_types.h"
|
||||
#include "dmx_lib.h"
|
||||
extern "C" {
|
||||
#include <libavutil/rational.h>
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
ANALOG_SD_RGB_CINCH = 0x00,
|
||||
ANALOG_SD_YPRPB_CINCH,
|
||||
ANALOG_HD_RGB_CINCH,
|
||||
ANALOG_HD_YPRPB_CINCH,
|
||||
ANALOG_SD_RGB_SCART = 0x10,
|
||||
ANALOG_SD_YPRPB_SCART,
|
||||
ANALOG_HD_RGB_SCART,
|
||||
ANALOG_HD_YPRPB_SCART,
|
||||
ANALOG_SCART_MASK = 0x10
|
||||
} analog_mode_t;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_FORMAT_MPEG2 = 0,
|
||||
VIDEO_FORMAT_MPEG4_H264,
|
||||
VIDEO_FORMAT_VC1,
|
||||
VIDEO_FORMAT_JPEG,
|
||||
VIDEO_FORMAT_GIF,
|
||||
VIDEO_FORMAT_PNG,
|
||||
VIDEO_FORMAT_MPEG4_H265,
|
||||
VIDEO_FORMAT_AVS = 16
|
||||
} VIDEO_FORMAT;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_SD = 0,
|
||||
VIDEO_HD,
|
||||
VIDEO_120x60i,
|
||||
VIDEO_320x240i,
|
||||
VIDEO_1440x800i,
|
||||
VIDEO_360x288i
|
||||
} VIDEO_DEFINITION;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_FRAME_RATE_23_976 = 0,
|
||||
VIDEO_FRAME_RATE_24,
|
||||
VIDEO_FRAME_RATE_25,
|
||||
VIDEO_FRAME_RATE_29_97,
|
||||
VIDEO_FRAME_RATE_30,
|
||||
VIDEO_FRAME_RATE_50,
|
||||
VIDEO_FRAME_RATE_59_94,
|
||||
VIDEO_FRAME_RATE_60
|
||||
} VIDEO_FRAME_RATE;
|
||||
|
||||
typedef enum {
|
||||
DISPLAY_AR_1_1,
|
||||
DISPLAY_AR_4_3,
|
||||
DISPLAY_AR_14_9,
|
||||
DISPLAY_AR_16_9,
|
||||
DISPLAY_AR_20_9,
|
||||
DISPLAY_AR_RAW,
|
||||
} DISPLAY_AR;
|
||||
|
||||
typedef enum {
|
||||
DISPLAY_AR_MODE_PANSCAN = 0,
|
||||
DISPLAY_AR_MODE_LETTERBOX,
|
||||
DISPLAY_AR_MODE_NONE,
|
||||
DISPLAY_AR_MODE_PANSCAN2
|
||||
} DISPLAY_AR_MODE;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_DB_DR_NEITHER = 0,
|
||||
VIDEO_DB_ON,
|
||||
VIDEO_DB_DR_BOTH
|
||||
} VIDEO_DB_DR;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_PLAY_STILL = 0,
|
||||
VIDEO_PLAY_CLIP,
|
||||
VIDEO_PLAY_TRICK,
|
||||
VIDEO_PLAY_MOTION,
|
||||
VIDEO_PLAY_MOTION_NO_SYNC
|
||||
} VIDEO_PLAY_MODE;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_STD_NTSC,
|
||||
VIDEO_STD_SECAM,
|
||||
VIDEO_STD_PAL,
|
||||
VIDEO_STD_480P,
|
||||
VIDEO_STD_576P,
|
||||
VIDEO_STD_720P60,
|
||||
VIDEO_STD_1080I60,
|
||||
VIDEO_STD_720P50,
|
||||
VIDEO_STD_1080I50,
|
||||
VIDEO_STD_1080P30,
|
||||
VIDEO_STD_1080P24,
|
||||
VIDEO_STD_1080P25,
|
||||
VIDEO_STD_AUTO,
|
||||
VIDEO_STD_1080P50, /* SPARK only */
|
||||
VIDEO_STD_MAX
|
||||
} VIDEO_STD;
|
||||
|
||||
/* not used, for dummy functions */
|
||||
typedef enum {
|
||||
VIDEO_HDMI_CEC_MODE_OFF = 0,
|
||||
VIDEO_HDMI_CEC_MODE_TUNER,
|
||||
VIDEO_HDMI_CEC_MODE_RECORDER
|
||||
} VIDEO_HDMI_CEC_MODE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VIDEO_CONTROL_BRIGHTNESS = 0,
|
||||
VIDEO_CONTROL_CONTRAST,
|
||||
VIDEO_CONTROL_SATURATION,
|
||||
VIDEO_CONTROL_HUE,
|
||||
VIDEO_CONTROL_SHARPNESS,
|
||||
VIDEO_CONTROL_MAX = VIDEO_CONTROL_SHARPNESS
|
||||
} VIDEO_CONTROL;
|
||||
|
||||
|
||||
#define VDEC_MAXBUFS 0x30
|
||||
class cVideo : public Thread
|
||||
{
|
||||
friend class GLFramebuffer;
|
||||
friend class cDemux;
|
||||
private:
|
||||
/* called from GL thread */
|
||||
class SWFramebuffer : public std::vector<unsigned char>
|
||||
{
|
||||
public:
|
||||
SWFramebuffer() : mWidth(0), mHeight(0) {}
|
||||
void width(int w) { mWidth = w; }
|
||||
void height(int h) { mHeight = h; }
|
||||
void pts(uint64_t p) { mPts = p; }
|
||||
void AR(AVRational a) { mAR = a; }
|
||||
int width() const { return mWidth; }
|
||||
int height() const { return mHeight; }
|
||||
int64_t pts() const { return mPts; }
|
||||
AVRational AR() const { return mAR; }
|
||||
private:
|
||||
int mWidth;
|
||||
int mHeight;
|
||||
int64_t mPts;
|
||||
AVRational mAR;
|
||||
};
|
||||
int buf_in, buf_out, buf_num;
|
||||
int64_t GetPTS(void);
|
||||
public:
|
||||
/* constructor & destructor */
|
||||
cVideo(int mode, void *, void *, unsigned int unit = 0);
|
||||
~cVideo(void);
|
||||
|
||||
void * GetTVEnc() { return NULL; };
|
||||
void * GetTVEncSD() { return NULL; };
|
||||
|
||||
/* aspect ratio */
|
||||
int getAspectRatio(void);
|
||||
void getPictureInfo(int &width, int &height, int &rate);
|
||||
int setAspectRatio(int aspect, int mode);
|
||||
|
||||
/* cropping mode */
|
||||
int setCroppingMode(int x = 0 /*vidDispMode_t x = VID_DISPMODE_NORM*/);
|
||||
|
||||
/* get play state */
|
||||
int getPlayState(void);
|
||||
|
||||
/* blank on freeze */
|
||||
int getBlank(void);
|
||||
int setBlank(int enable);
|
||||
|
||||
/* change video play state. Parameters are all unused. */
|
||||
int Start(void *PcrChannel = NULL, unsigned short PcrPid = 0, unsigned short VideoPid = 0, void *x = NULL);
|
||||
int Stop(bool blank = true);
|
||||
bool Pause(void);
|
||||
|
||||
/* set video_system */
|
||||
int SetVideoSystem(int video_system, bool remember = true);
|
||||
int GetVideoSystem();
|
||||
int SetStreamType(VIDEO_FORMAT type);
|
||||
void SetSyncMode(AVSYNC_TYPE mode);
|
||||
bool SetCECMode(VIDEO_HDMI_CEC_MODE) { return true; };
|
||||
void SetCECAutoView(bool) { return; };
|
||||
void SetCECAutoStandby(bool) { return; };
|
||||
void ShowPicture(const char * fname, const char * destname = NULL);
|
||||
void StopPicture();
|
||||
void Standby(unsigned int bOn);
|
||||
void Pig(int x, int y, int w, int h, int osd_w = 1064, int osd_h = 600, int startx = 0, int starty = 0, int endx = 1279, int endy = 719);
|
||||
void SetControl(int, int) { return; };
|
||||
void setContrast(int val);
|
||||
void SetVideoMode(analog_mode_t mode);
|
||||
void SetDBDR(int) { return; };
|
||||
void SetAudioHandle(void *) { return; };
|
||||
void SetAutoModes(int [VIDEO_STD_MAX]) { return; };
|
||||
int OpenVBI(int) { return 0; };
|
||||
int CloseVBI(void) { return 0; };
|
||||
int StartVBI(unsigned short) { return 0; };
|
||||
int StopVBI(void) { return 0; };
|
||||
void SetDemux(cDemux *dmx);
|
||||
bool GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video = true, bool get_osd = false, bool scale_to_video = false);
|
||||
SWFramebuffer *getDecBuf(void);
|
||||
private:
|
||||
void run();
|
||||
SWFramebuffer buffers[VDEC_MAXBUFS];
|
||||
int dec_w, dec_h;
|
||||
int dec_r;
|
||||
bool w_h_changed;
|
||||
bool thread_running;
|
||||
VIDEO_FORMAT v_format;
|
||||
VIDEO_STD v_std;
|
||||
//OpenThreads::Mutex buf_m;
|
||||
Mutex buf_m;
|
||||
DISPLAY_AR display_aspect;
|
||||
DISPLAY_AR_MODE display_crop;
|
||||
int output_h;
|
||||
int pig_x;
|
||||
int pig_y;
|
||||
int pig_w;
|
||||
int pig_h;
|
||||
};
|
||||
|
||||
#endif
|
109
generic-pc/video_priv.h
Normal file
109
generic-pc/video_priv.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
Copyright 2013 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __vdec__
|
||||
|
||||
#include <OpenThreads/Thread>
|
||||
#include <OpenThreads/Mutex>
|
||||
|
||||
#include "video_hal.h"
|
||||
extern "C" {
|
||||
#include <libavutil/rational.h>
|
||||
}
|
||||
|
||||
#define VDEC_MAXBUFS 0x40
|
||||
class VDec : public OpenThreads::Thread
|
||||
{
|
||||
friend class GLFbPC;
|
||||
friend class cDemux;
|
||||
friend class cVideo;
|
||||
private:
|
||||
/* called from GL thread */
|
||||
class SWFramebuffer : public std::vector<unsigned char>
|
||||
{
|
||||
public:
|
||||
SWFramebuffer() : mWidth(0), mHeight(0) {}
|
||||
void width(int w) { mWidth = w; }
|
||||
void height(int h) { mHeight = h; }
|
||||
void pts(uint64_t p) { mPts = p; }
|
||||
void AR(AVRational a) { mAR = a; }
|
||||
int width() const { return mWidth; }
|
||||
int height() const { return mHeight; }
|
||||
int64_t pts() const { return mPts; }
|
||||
AVRational AR() const { return mAR; }
|
||||
private:
|
||||
int mWidth;
|
||||
int mHeight;
|
||||
int64_t mPts;
|
||||
AVRational mAR;
|
||||
};
|
||||
int buf_in, buf_out, buf_num;
|
||||
public:
|
||||
/* constructor & destructor */
|
||||
VDec(void);
|
||||
~VDec(void);
|
||||
/* aspect ratio */
|
||||
int getAspectRatio(void);
|
||||
int setAspectRatio(int aspect, int mode);
|
||||
void getPictureInfo(int &width, int &height, int &rate);
|
||||
|
||||
#if 0
|
||||
/* cropping mode */
|
||||
int setCroppingMode(int x = 0 /*vidDispMode_t x = VID_DISPMODE_NORM*/);
|
||||
|
||||
/* get play state */
|
||||
int getPlayState(void);
|
||||
|
||||
/* blank on freeze */
|
||||
int getBlank(void);
|
||||
int setBlank(int enable);
|
||||
#endif
|
||||
int GetVideoSystem();
|
||||
int SetVideoSystem(int system);
|
||||
|
||||
/* change video play state. Parameters are all unused. */
|
||||
int Start();
|
||||
int Stop(bool blank = true);
|
||||
|
||||
int SetStreamType(VIDEO_FORMAT type);
|
||||
bool ShowPicture(const char * fname);
|
||||
void Pig(int x, int y, int w, int h);
|
||||
bool GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video = true, bool get_osd = false, bool scale_to_video = false);
|
||||
SWFramebuffer *getDecBuf(void);
|
||||
int64_t GetPTS(void);
|
||||
private:
|
||||
void run();
|
||||
SWFramebuffer buffers[VDEC_MAXBUFS];
|
||||
int dec_w, dec_h;
|
||||
int dec_r;
|
||||
bool w_h_changed;
|
||||
bool thread_running;
|
||||
VIDEO_FORMAT v_format;
|
||||
OpenThreads::Mutex buf_m;
|
||||
DISPLAY_AR display_aspect;
|
||||
DISPLAY_AR_MODE display_crop;
|
||||
int output_h;
|
||||
VIDEO_STD v_std;
|
||||
int pig_x;
|
||||
int pig_y;
|
||||
int pig_w;
|
||||
int pig_h;
|
||||
bool pig_changed;
|
||||
OpenThreads::Mutex still_m;
|
||||
bool stillpicture;
|
||||
};
|
||||
#endif
|
@@ -1,23 +1,99 @@
|
||||
#include <config.h>
|
||||
#if HAVE_TRIPLEDRAGON
|
||||
#include "../libtriple/audio_td.h"
|
||||
#elif HAVE_DUCKBOX_HARDWARE
|
||||
#include "../libduckbox/audio_lib.h"
|
||||
#include "../libduckbox/audio_mixer.h"
|
||||
#elif HAVE_SPARK_HARDWARE
|
||||
#include "../libspark/audio_lib.h"
|
||||
#include "../libspark/audio_mixer.h"
|
||||
#elif HAVE_ARM_HARDWARE
|
||||
#include "../libarmbox/audio_lib.h"
|
||||
#include "../libarmbox/audio_mixer.h"
|
||||
#elif HAVE_AZBOX_HARDWARE
|
||||
#include "../azbox/audio_lib.h"
|
||||
#elif HAVE_GENERIC_HARDWARE
|
||||
#if BOXMODEL_RASPI
|
||||
#include "../raspi/audio_lib.h"
|
||||
#else
|
||||
#include "../generic-pc/audio_lib.h"
|
||||
#endif
|
||||
#else
|
||||
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
||||
/*
|
||||
* (C) 2010-2013 Stefan Seyfried
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __audio_hal__
|
||||
#define __audio_hal__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cs_types.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_SYNC_WITH_PTS,
|
||||
AUDIO_NO_SYNC,
|
||||
AUDIO_SYNC_AUDIO_MASTER
|
||||
} AUDIO_SYNC_MODE;
|
||||
|
||||
typedef enum {
|
||||
HDMI_ENCODED_OFF,
|
||||
HDMI_ENCODED_AUTO,
|
||||
HDMI_ENCODED_FORCED
|
||||
} HDMI_ENCODED_MODE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_FMT_AUTO = 0,
|
||||
AUDIO_FMT_MPEG,
|
||||
AUDIO_FMT_MP3,
|
||||
AUDIO_FMT_DOLBY_DIGITAL,
|
||||
AUDIO_FMT_BASIC = AUDIO_FMT_DOLBY_DIGITAL,
|
||||
AUDIO_FMT_AAC,
|
||||
AUDIO_FMT_AAC_PLUS,
|
||||
AUDIO_FMT_DD_PLUS,
|
||||
AUDIO_FMT_DTS,
|
||||
AUDIO_FMT_AVS,
|
||||
AUDIO_FMT_MLP,
|
||||
AUDIO_FMT_WMA,
|
||||
AUDIO_FMT_MPG1, // TD only. For Movieplayer / cPlayback
|
||||
AUDIO_FMT_ADVANCED = AUDIO_FMT_MLP
|
||||
} AUDIO_FORMAT;
|
||||
|
||||
class cAudio
|
||||
{
|
||||
public:
|
||||
/* construct & destruct */
|
||||
cAudio(void *, void *, void *);
|
||||
~cAudio(void);
|
||||
|
||||
void *GetHandle() { return NULL; };
|
||||
/* shut up */
|
||||
int mute(void);
|
||||
int unmute(void);
|
||||
int SetMute(bool enable);
|
||||
|
||||
/* volume, min = 0, max = 255 */
|
||||
int setVolume(unsigned int left, unsigned int right);
|
||||
int getVolume(void) { return volume;}
|
||||
bool getMuteStatus(void) { return muted; };
|
||||
|
||||
/* start and stop audio */
|
||||
int Start(void);
|
||||
int Stop(void);
|
||||
bool Pause(bool Pcm = true);
|
||||
void SetStreamType(AUDIO_FORMAT type);
|
||||
void SetSyncMode(AVSYNC_TYPE Mode);
|
||||
|
||||
/* select channels */
|
||||
int setChannel(int channel);
|
||||
int PrepareClipPlay(int uNoOfChannels, int uSampleRate, int uBitsPerSample, int bLittleEndian);
|
||||
int WriteClip(unsigned char * buffer, int size);
|
||||
int StopClip();
|
||||
void getAudioInfo(int &type, int &layer, int& freq, int &bitrate, int &mode);
|
||||
void SetSRS(int iq_enable, int nmgr_enable, int iq_mode, int iq_level);
|
||||
bool IsHdmiDDSupported();
|
||||
void SetHdmiDD(bool enable);
|
||||
void SetSpdifDD(bool enable);
|
||||
void ScheduleMute(bool On);
|
||||
void EnableAnalogOut(bool enable);
|
||||
private:
|
||||
bool muted;
|
||||
int volume;
|
||||
void *pdata;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -1,9 +1,6 @@
|
||||
/*
|
||||
* dummy functions to implement ca_cs.h interface
|
||||
*/
|
||||
#if HAVE_DUCKBOX_HARDWARE || HAVE_ARM_HARDWARE
|
||||
#include "ca_ci.h"
|
||||
#else
|
||||
#ifndef __CA_LIBTRIPLE_H_
|
||||
#define __CA_LIBTRIPLE_H_
|
||||
|
||||
@@ -11,12 +8,15 @@
|
||||
#include "cs_types.h"
|
||||
#include <vector>
|
||||
#include <set>
|
||||
typedef std::set<int> ca_map_t;
|
||||
typedef ca_map_t::iterator ca_map_iterator_t;
|
||||
|
||||
typedef std::vector<u16> CaIdVector;
|
||||
typedef std::vector<u16>::iterator CaIdVectorIterator;
|
||||
typedef std::vector<u16>::const_iterator CaIdVectorConstIterator;
|
||||
|
||||
enum CA_INIT_MASK {
|
||||
CA_INIT_SC = 1,
|
||||
CA_INIT_SC = 1,
|
||||
CA_INIT_CI,
|
||||
CA_INIT_BOTH
|
||||
};
|
||||
@@ -24,7 +24,7 @@ enum CA_INIT_MASK {
|
||||
enum CA_SLOT_TYPE {
|
||||
CA_SLOT_TYPE_SMARTCARD,
|
||||
CA_SLOT_TYPE_CI,
|
||||
CA_SLOT_TYPE_ALL
|
||||
CA_SLOT_TYPE_ALL,
|
||||
};
|
||||
|
||||
enum CA_MESSAGE_FLAGS {
|
||||
@@ -67,18 +67,13 @@ enum CA_MESSAGE_MSGID {
|
||||
CA_MESSAGE_MSG_MMI_CLOSE,
|
||||
CA_MESSAGE_MSG_INTERNAL,
|
||||
CA_MESSAGE_MSG_PMT_ARRIVED,
|
||||
CA_MESSAGE_MSG_CAPMT_ARRIVED,
|
||||
CA_MESSAGE_MSG_CAT_ARRIVED,
|
||||
CA_MESSAGE_MSG_ECM_ARRIVED,
|
||||
CA_MESSAGE_MSG_EMM_ARRIVED,
|
||||
CA_MESSAGE_MSG_CHANNEL_CHANGE,
|
||||
CA_MESSAGE_MSG_GUI_READY,
|
||||
CA_MESSAGE_MSG_EXIT
|
||||
CA_MESSAGE_MSG_EXIT,
|
||||
};
|
||||
|
||||
typedef std::set<int> ca_map_t;
|
||||
typedef ca_map_t::iterator ca_map_iterator_t;
|
||||
|
||||
typedef struct CA_MESSAGE {
|
||||
uint32_t MsgId;
|
||||
enum CA_SLOT_TYPE SlotType;
|
||||
@@ -100,9 +95,9 @@ public:
|
||||
uint32_t GetNumberSmartCardSlots(void);
|
||||
static cCA *GetInstance(void);
|
||||
bool SendPMT(int Unit, unsigned char *Data, int Len, CA_SLOT_TYPE SlotType = CA_SLOT_TYPE_ALL);
|
||||
// bool SendCAPMT(u64 /*Source*/, u8 /*DemuxSource*/, u8 /*DemuxMask*/, const unsigned char * /*CAPMT*/, u32 /*CAPMTLen*/, const unsigned char * /*RawPMT*/, u32 /*RawPMTLen*/) { return true; };
|
||||
bool SendCAPMT(u64 /*Source*/, u8 /*DemuxSource*/, u8 /*DemuxMask*/, const unsigned char * /*CAPMT*/, u32 /*CAPMTLen*/, const unsigned char * /*RawPMT*/, u32 /*RawPMTLen*/, enum CA_SLOT_TYPE
|
||||
/*SlotType*/, unsigned char /*scrambled = 0*/, ca_map_t /*camap = std::set<int>()*/, int /*mode = 0*/, bool /*enabled = false*/) { return true; };
|
||||
bool SendCAPMT(u64 /*Source*/, u8 /*DemuxSource*/, u8 /*DemuxMask*/, const unsigned char * /*CAPMT*/, u32 /*CAPMTLen*/, const unsigned char * /*RawPMT*/, u32 /*RawPMTLen*/, enum CA_SLOT_TYPE SlotType = CA_SLOT_TYPE_ALL) { (void)SlotType; return true; };
|
||||
bool SendCAPMT(u64 /*Source*/, u8 /*DemuxSource*/, u8 /*DemuxMask*/, const unsigned char * /*CAPMT*/, u32 /*CAPMTLen*/, const unsigned char * /*RawPMT*/, u32 /*RawPMTLen*/, enum CA_SLOT_TYPE SlotType = CA_SLOT_TYPE_ALL, unsigned char scrambled = 0, ca_map_t camap ={0}, int mode = 0, bool enable = false) { (void)SlotType;(void)scrambled;(void)camap;(void)mode;(void)enable; return true; };
|
||||
|
||||
bool SendMessage(const CA_MESSAGE *Msg);
|
||||
void SetInitMask(enum CA_INIT_MASK InitMask);
|
||||
int GetCAIDS(CaIdVector & /*Caids*/) { return 0; };
|
||||
@@ -117,10 +112,7 @@ public:
|
||||
void InputAnswer(enum CA_SLOT_TYPE, uint32_t Slot, uint8_t * Data, int Len);
|
||||
void MenuClose(enum CA_SLOT_TYPE, uint32_t Slot);
|
||||
void SetTSClock(u32 /*Speed*/) { return; };
|
||||
bool checkChannelID(u64 /*chanID*/) { return false; };
|
||||
void setCheckLiveSlot(int /*check*/) { return; };
|
||||
virtual ~cCA();
|
||||
};
|
||||
|
||||
#endif // __CA_LIBTRIPLE_H_
|
||||
#endif // HAVE_DUCKBOX_HARDWARE
|
@@ -1 +1 @@
|
||||
#include "../common/ca.h"
|
||||
#include "ca.h"
|
||||
|
@@ -1,23 +0,0 @@
|
||||
#ifndef _CONDITION_ABSTRACTION_H
|
||||
#define _CONDITION_ABSTRACTION_H
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "mutex_abstraction.h"
|
||||
|
||||
class Condition
|
||||
{
|
||||
pthread_cond_t mCondition;
|
||||
|
||||
Condition(const Condition&);
|
||||
const Condition& operator=(const Condition&);
|
||||
|
||||
public:
|
||||
Condition();
|
||||
virtual ~Condition();
|
||||
virtual int wait(Mutex* const aMutex);
|
||||
virtual int broadcast();
|
||||
virtual int signal();
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,20 +1,67 @@
|
||||
#include <config.h>
|
||||
#if HAVE_TRIPLEDRAGON
|
||||
#include "../libtriple/cs_api.h"
|
||||
#elif HAVE_DUCKBOX_HARDWARE
|
||||
#include "../libduckbox/cs_api.h"
|
||||
#elif HAVE_SPARK_HARDWARE
|
||||
#include "../libspark/cs_api.h"
|
||||
#elif HAVE_ARM_HARDWARE
|
||||
#include "../libarmbox/cs_api.h"
|
||||
#elif HAVE_AZBOX_HARDWARE
|
||||
#include "../azbox/cs_api.h"
|
||||
#elif HAVE_GENERIC_HARDWARE
|
||||
#if BOXMODEL_RASPI
|
||||
#include "../raspi/cs_api.h"
|
||||
#else
|
||||
#include "../generic-pc/cs_api.h"
|
||||
/* compatibility header for tripledragon. I'm lazy, so I just left it
|
||||
as "cs_api.h" so that I don't need too many ifdefs in the code */
|
||||
|
||||
#ifndef __CS_API_H_
|
||||
#define __CS_API_H_
|
||||
|
||||
#include "init_td.h"
|
||||
typedef void (*cs_messenger) (unsigned int msg, unsigned int data);
|
||||
|
||||
#if 0
|
||||
enum CS_LOG_MODULE {
|
||||
CS_LOG_CI = 0,
|
||||
CS_LOG_HDMI_CEC,
|
||||
CS_LOG_HDMI,
|
||||
CS_LOG_VIDEO,
|
||||
CS_LOG_VIDEO_DRM,
|
||||
CS_LOG_AUDIO,
|
||||
CS_LOG_DEMUX,
|
||||
CS_LOG_DENC,
|
||||
CS_LOG_PVR_RECORD,
|
||||
CS_LOG_PVR_PLAY,
|
||||
CS_LOG_POWER_CTRL,
|
||||
CS_LOG_POWER_CLK,
|
||||
CS_LOG_MEM,
|
||||
CS_LOG_API,
|
||||
};
|
||||
#endif
|
||||
#else
|
||||
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
||||
|
||||
inline void cs_api_init()
|
||||
{
|
||||
init_td_api();
|
||||
};
|
||||
|
||||
inline void cs_api_exit()
|
||||
{
|
||||
shutdown_td_api();
|
||||
};
|
||||
|
||||
#define cs_malloc_uncached malloc
|
||||
#define cs_free_uncached free
|
||||
|
||||
// Callback function helpers
|
||||
static inline void cs_register_messenger(cs_messenger) { return; };
|
||||
static inline void cs_deregister_messenger(void) { return; };
|
||||
//cs_messenger cs_get_messenger(void);
|
||||
|
||||
#if 0
|
||||
// Logging functions
|
||||
void cs_log_enable(void);
|
||||
void cs_log_disable(void);
|
||||
void cs_log_message(const char *prefix, const char *fmt, ...);
|
||||
void cs_log_module_enable(enum CS_LOG_MODULE module);
|
||||
void cs_log_module_disable(enum CS_LOG_MODULE module);
|
||||
void cs_log_module_message(enum CS_LOG_MODULE module, const char *fmt, ...);
|
||||
|
||||
// TS Routing
|
||||
unsigned int cs_get_ts_output(void);
|
||||
int cs_set_ts_output(unsigned int port);
|
||||
|
||||
// Serial nr and revision accessors
|
||||
unsigned long long cs_get_serial(void);
|
||||
#endif
|
||||
/* compat... HD1 seems to be version 6. everything newer ist > 6... */
|
||||
static inline unsigned int cs_get_revision(void) { return 1; };
|
||||
static inline unsigned int cs_get_chip_type(void) { return 0; };
|
||||
extern int cnxt_debug;
|
||||
#endif //__CS_API_H_
|
||||
|
@@ -1,320 +0,0 @@
|
||||
#ifndef __DUCKBOX_VFD__
|
||||
#define __DUCKBOX_VFD__
|
||||
|
||||
#define VFDDISPLAYCHARS 0xc0425a00
|
||||
#define VFDWRITECGRAM 0x40425a01
|
||||
#define VFDBRIGHTNESS 0xc0425a03
|
||||
#define VFDPWRLED 0xc0425a04
|
||||
#define VFDDRIVERINIT 0xc0425a08
|
||||
#define VFDICONDISPLAYONOFF 0xc0425a0a
|
||||
#define VFDDISPLAYWRITEONOFF 0xc0425a05
|
||||
|
||||
#define VFDCLEARICONS 0xc0425af6
|
||||
#define VFDSETRF 0xc0425af7
|
||||
#define VFDSETFAN 0xc0425af8
|
||||
#define VFDGETWAKEUPMODE 0xc0425af9
|
||||
#define VFDGETTIME 0xc0425afa
|
||||
#define VFDSETTIME 0xc0425afb
|
||||
#define VFDSTANDBY 0xc0425afc
|
||||
#define VFDREBOOT 0xc0425afd
|
||||
#define VFDSETLED 0xc0425afe
|
||||
#define VFDSETMODE 0xc0425aff
|
||||
|
||||
#define VFDGETWAKEUPTIME 0xc0425b00
|
||||
#define VFDGETVERSION 0xc0425b01
|
||||
#define VFDSETDISPLAYTIME 0xc0425b02
|
||||
#define VFDSETTIMEMODE 0xc0425b03
|
||||
#define VFDDISPLAYCLR 0xc0425b00
|
||||
|
||||
typedef enum {
|
||||
#if defined(BOXMODEL_OCTAGON1008)
|
||||
ICON_DOLBY = 0x10,
|
||||
ICON_DTS,
|
||||
ICON_VIDEO,
|
||||
ICON_AUDIO,
|
||||
ICON_LINK,
|
||||
ICON_HDD,
|
||||
ICON_DISC,
|
||||
ICON_DVB,
|
||||
ICON_DVD,
|
||||
ICON_TIME,
|
||||
ICON_TIMER,
|
||||
ICON_CARD,
|
||||
ICON_1,
|
||||
ICON_2,
|
||||
ICON_KEY,
|
||||
ICON_16_9,
|
||||
ICON_USB,
|
||||
ICON_CRYPTED,
|
||||
ICON_PLAY,
|
||||
ICON_REWIND,
|
||||
ICON_PAUSE,
|
||||
ICON_FF,
|
||||
ICON_REC,
|
||||
ICON_ARROW,
|
||||
ICON_COLON1,
|
||||
ICON_COLON2,
|
||||
ICON_COLON3,
|
||||
ICON_MAX,
|
||||
FP_ICON_USB = ICON_USB,
|
||||
FP_ICON_HD = ICON_16_9,
|
||||
FP_ICON_HDD = ICON_HDD,
|
||||
FP_ICON_LOCK = ICON_CRYPTED,
|
||||
FP_ICON_BT,
|
||||
FP_ICON_MP3,
|
||||
FP_ICON_MUSIC,
|
||||
FP_ICON_DD = ICON_DOLBY,
|
||||
FP_ICON_MAIL,
|
||||
FP_ICON_MUTE = ICON_TIME,
|
||||
FP_ICON_PLAY = ICON_PLAY,
|
||||
FP_ICON_PAUSE = ICON_PAUSE,
|
||||
FP_ICON_FF = ICON_FF,
|
||||
FP_ICON_FR = ICON_REWIND,
|
||||
FP_ICON_REC = ICON_REC,
|
||||
FP_ICON_CLOCK = ICON_TIMER,
|
||||
FP_ICON_RADIO = ICON_AUDIO,
|
||||
FP_ICON_TV = ICON_VIDEO,
|
||||
FP_ICON_DOWNLOAD = ICON_LINK,
|
||||
FP_ICON_CAM1 = ICON_REC,
|
||||
#elif defined(BOXMODEL_FORTIS_HDBOX)
|
||||
ICON_USB = 0x10,
|
||||
ICON_STANDBY,
|
||||
ICON_SAT,
|
||||
ICON_REC,
|
||||
ICON_TIMESHIFT,
|
||||
ICON_TIMER,
|
||||
ICON_HD,
|
||||
ICON_SCRAMBLED,
|
||||
ICON_DOLBY,
|
||||
ICON_MUTE,
|
||||
ICON_TUNER1,
|
||||
ICON_TUNER2,
|
||||
ICON_MP3,
|
||||
ICON_REPEAT,
|
||||
ICON_Play,
|
||||
ICON_TER,
|
||||
ICON_FILE,
|
||||
ICON_480i,
|
||||
ICON_480p,
|
||||
ICON_576i,
|
||||
ICON_576p,
|
||||
ICON_720p,
|
||||
ICON_1080i,
|
||||
ICON_1080p,
|
||||
ICON_Circ0,
|
||||
ICON_Circ1,
|
||||
ICON_Circ2,
|
||||
ICON_Circ3,
|
||||
ICON_Circ4,
|
||||
ICON_Circ5,
|
||||
ICON_Circ6,
|
||||
ICON_Circ7,
|
||||
ICON_Circ8,
|
||||
ICON_COLON1,
|
||||
ICON_COLON2,
|
||||
ICON_COLON3,
|
||||
ICON_COLON4,
|
||||
ICON_TV,
|
||||
ICON_RADIO,
|
||||
ICON_MAX,
|
||||
FP_ICON_USB = ICON_USB,
|
||||
FP_ICON_REC = ICON_REC,
|
||||
FP_ICON_CAM1 = ICON_REC,
|
||||
FP_ICON_TIMESHIFT = ICON_TIMESHIFT,
|
||||
FP_ICON_CLOCK = ICON_TIMER,
|
||||
FP_ICON_HD = ICON_HD,
|
||||
FP_ICON_LOCK = ICON_SCRAMBLED,
|
||||
FP_ICON_DD = ICON_DOLBY,
|
||||
FP_ICON_MUTE = ICON_MUTE,
|
||||
FP_ICON_BT = 0,
|
||||
FP_ICON_MP3 = ICON_MP3,
|
||||
FP_ICON_PLAY = ICON_Play,
|
||||
FP_ICON_PAUSE = 0,
|
||||
FP_ICON_HDD = 0,
|
||||
FP_ICON_MAIL = 0,
|
||||
FP_ICON_FF = 0,
|
||||
FP_ICON_FR = 0,
|
||||
FP_ICON_RADIO = ICON_RADIO,
|
||||
FP_ICON_TV = ICON_TV,
|
||||
FP_ICON_MUSIC = ICON_RADIO,
|
||||
FP_ICON_MAX = ICON_MAX
|
||||
#elif defined(BOXMODEL_UFS910) || defined(BOXMODEL_UFS922) || defined(BOXMODEL_UFS912) || defined(BOXMODEL_UFS913)
|
||||
FP_ICON_USB = 0x10,
|
||||
FP_ICON_HD,
|
||||
FP_ICON_HDD,
|
||||
FP_ICON_LOCK,
|
||||
FP_ICON_BT,
|
||||
FP_ICON_MP3,
|
||||
FP_ICON_MUSIC,
|
||||
FP_ICON_DD,
|
||||
FP_ICON_MAIL,
|
||||
FP_ICON_MUTE,
|
||||
FP_ICON_PLAY,
|
||||
FP_ICON_PAUSE,
|
||||
FP_ICON_FF,
|
||||
FP_ICON_FR,
|
||||
FP_ICON_REC,
|
||||
FP_ICON_CLOCK,
|
||||
FP_ICON_MAX,
|
||||
FP_ICON_CAM1 = FP_ICON_REC,
|
||||
FP_ICON_TV = 0,
|
||||
FP_ICON_RADIO = FP_ICON_MUSIC,
|
||||
FP_ICON_RECORD = FP_ICON_REC,
|
||||
FP_ICON_DOWNLOAD = 0,
|
||||
FP_ICON_TIMESHIFT = 0
|
||||
#elif defined(BOXMODEL_IPBOX9900) || defined(BOXMODEL_IPBOX99)
|
||||
ICON_STANDBY,
|
||||
ICON_SAT,
|
||||
ICON_REC,
|
||||
ICON_TIMESHIFT,
|
||||
ICON_TIMER,
|
||||
ICON_HD,
|
||||
ICON_SCRAMBLED,
|
||||
ICON_MUTE,
|
||||
ICON_TUNER1,
|
||||
ICON_TUNER2,
|
||||
ICON_MP3,
|
||||
ICON_REPEAT,
|
||||
ICON_PLAY,
|
||||
ICON_PAUSE,
|
||||
ICON_TER,
|
||||
ICON_FILE,
|
||||
ICON_480I,
|
||||
ICON_480P,
|
||||
ICON_576I,
|
||||
ICON_576P,
|
||||
ICON_720P,
|
||||
ICON_1080I,
|
||||
ICON_1080P,
|
||||
ICON_TV,
|
||||
ICON_RADIO,
|
||||
ICON_MAX,
|
||||
FP_ICON_480P = ICON_480P,
|
||||
FP_ICON_480I = ICON_480I,
|
||||
FP_ICON_576P = ICON_576P,
|
||||
FP_ICON_576I = ICON_576I,
|
||||
FP_ICON_PLAY = ICON_PLAY,
|
||||
FP_ICON_PAUSE = ICON_PAUSE,
|
||||
FP_ICON_1080P = 0x0A,
|
||||
FP_ICON_1080I = 0x09,
|
||||
FP_ICON_720P = 0x08,
|
||||
FP_ICON_POWER = 0x00,
|
||||
FP_ICON_HD = 0x05,
|
||||
FP_ICON_RADIO = 0x0D,
|
||||
FP_ICON_MP3 = FP_ICON_RADIO,
|
||||
FP_ICON_MUSIC = FP_ICON_RADIO,
|
||||
FP_ICON_DD = 0x04,
|
||||
FP_ICON_REC = 0x03,
|
||||
FP_ICON_FF = 0,
|
||||
FP_ICON_FR = 0,
|
||||
FP_ICON_USB = 0,
|
||||
FP_ICON_HDD = 0,
|
||||
FP_ICON_MUTE = 0,
|
||||
FP_ICON_CLOCK = 0,
|
||||
FP_ICON_CAM1 = 0,
|
||||
FP_ICON_LOCK = 0,
|
||||
FP_ICON_DOWNLOAD = 0,
|
||||
FP_ICON_TIMESHIFT = FP_ICON_REC,
|
||||
FP_ICON_TV = 0,
|
||||
FP_ICON_MAIL = 0,
|
||||
FP_ICON_BT = 0,
|
||||
|
||||
#else
|
||||
FP_ICON_USB = 0x10,
|
||||
FP_ICON_HD,
|
||||
FP_ICON_HDD,
|
||||
FP_ICON_LOCK,
|
||||
FP_ICON_BT,
|
||||
FP_ICON_MP3,
|
||||
FP_ICON_MUSIC,
|
||||
FP_ICON_DD,
|
||||
FP_ICON_MAIL,
|
||||
FP_ICON_MUTE,
|
||||
FP_ICON_PLAY,
|
||||
FP_ICON_PAUSE,
|
||||
FP_ICON_FF,
|
||||
FP_ICON_FR,
|
||||
FP_ICON_REC,
|
||||
FP_ICON_CLOCK,
|
||||
FP_ICON_CAM1 = FP_ICON_REC,
|
||||
FP_ICON_TV = FP_ICON_MUSIC,
|
||||
FP_ICON_RADIO = FP_ICON_MUSIC,
|
||||
FP_ICON_RECORD = FP_ICON_REC,
|
||||
FP_ICON_DOWNLOAD,
|
||||
FP_ICON_TIMESHIFT,
|
||||
#endif
|
||||
#if !defined(BOXMODEL_UFS910) && !defined(BOXMODEL_UFS922) && !defined(BOXMODEL_UFS912) && !defined(BOXMODEL_UFS913) && !defined(BOXMODEL_FORTIS_HDBOX)
|
||||
FP_ICON_MAX
|
||||
#endif
|
||||
} fp_icon;
|
||||
|
||||
typedef enum {
|
||||
FP_FLAG_NONE = 0x00,
|
||||
FP_FLAG_SCROLL_ON = 0x01, /* switch scrolling on */
|
||||
FP_FLAG_SCROLL_LTR = 0x02, /* scroll from left to rightinstead of default right to left direction (i.e. for arabic text) */
|
||||
FP_FLAG_SCROLL_SIO = 0x04, /* start/stop scrolling with empty screen (scroll in/out) */
|
||||
FP_FLAG_SCROLL_DELAY = 0x08, /* delayed scroll start */
|
||||
FP_FLAG_ALIGN_LEFT = 0x10, /* align the text in display from the left (default) */
|
||||
FP_FLAG_ALIGN_RIGHT = 0x20, /* align the text in display from the right (arabic) */
|
||||
FP_FLAG_UPDATE_SCROLL_POS = 0x40, /* update the current position for scrolling */
|
||||
} fp_flag;
|
||||
|
||||
typedef struct {
|
||||
unsigned char brightness;
|
||||
unsigned char flags;
|
||||
unsigned char current_hour;
|
||||
unsigned char current_minute;
|
||||
unsigned char timer_minutes_hi;
|
||||
unsigned char timer_minutes_lo;
|
||||
} fp_standby_data_t;
|
||||
|
||||
typedef enum {
|
||||
FP_LED_1_ON = 0x81,
|
||||
FP_LED_2_ON = 0x82,
|
||||
FP_LED_3_ON = 0x83,
|
||||
FP_LED_1_OFF = 0x01,
|
||||
FP_LED_2_OFF = 0x02,
|
||||
FP_LED_3_OFF = 0x03,
|
||||
} fp_led_ctrl_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned char source;
|
||||
unsigned char time_minutes_hi;
|
||||
unsigned char time_minutes_lo;
|
||||
} fp_wakeup_data_t;
|
||||
|
||||
typedef enum {
|
||||
FP_WAKEUP_SOURCE_TIMER = 0x01,
|
||||
FP_WAKEUP_SOURCE_BUTTON = 0x02,
|
||||
FP_WAKEUP_SOURCE_REMOTE = 0x04,
|
||||
FP_WAKEUP_SOURCE_PWLOST = 0x7F,
|
||||
FP_WAKEUP_SOURCE_POWER = 0xFF
|
||||
} fp_wakeup_source;
|
||||
|
||||
typedef struct {
|
||||
unsigned short addr;
|
||||
unsigned short cmd;
|
||||
} fp_standby_cmd_data_t;
|
||||
|
||||
typedef enum {
|
||||
FP_DISPLAY_TEXT_NONE = 0,
|
||||
FP_DISPLAY_TEXT_LIMITED,
|
||||
FP_DISPLAY_TEXT_ALL,
|
||||
} fp_display_text_type_t;
|
||||
|
||||
typedef enum {
|
||||
FP_DISPLAY_TYPE_NONE = 0,
|
||||
FP_DISPLAY_TYPE_VFD,
|
||||
FP_DISPLAY_TYPE_OLED,
|
||||
FP_DISPLAY_TYPE_LED_SEGMENT
|
||||
} fp_display_type_t;
|
||||
|
||||
typedef struct {
|
||||
fp_display_type_t display_type;
|
||||
unsigned short xres, yres;
|
||||
unsigned int segment_count;
|
||||
fp_display_text_type_t text_support;
|
||||
bool number_support;
|
||||
} fp_display_caps_t;
|
||||
|
||||
#endif /* __DUCKBOX_VFD__ */
|
@@ -1,20 +1,97 @@
|
||||
#include <config.h>
|
||||
#if HAVE_TRIPLEDRAGON
|
||||
#include "../libtriple/dmx_td.h"
|
||||
#elif HAVE_DUCKBOX_HARDWARE
|
||||
#include "../libduckbox/dmx_lib.h"
|
||||
#elif HAVE_SPARK_HARDWARE
|
||||
#include "../libspark/dmx_lib.h"
|
||||
#elif HAVE_AZBOX_HARDWARE
|
||||
#include "../azbox/dmx_lib.h"
|
||||
#elif HAVE_ARM_HARDWARE
|
||||
#include "../libarmbox/dmx_lib.h"
|
||||
#elif HAVE_GENERIC_HARDWARE
|
||||
#if BOXMODEL_RASPI
|
||||
#include "../raspi/dmx_lib.h"
|
||||
#else
|
||||
#include "../generic-pc/dmx_lib.h"
|
||||
#endif
|
||||
#else
|
||||
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
||||
/*
|
||||
* (C) 2010-2013 Stefan Seyfried
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __dmx_hal__
|
||||
#define __dmx_hal__
|
||||
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
#include <inttypes.h>
|
||||
/* at least on td, config.h needs to be included before... */
|
||||
#ifndef HAVE_TRIPLEDRAGON
|
||||
#include <linux/dvb/dmx.h>
|
||||
#else /* TRIPLEDRAGON */
|
||||
extern "C" {
|
||||
#include <hardware/xp/xp_osd_user.h>
|
||||
}
|
||||
#if defined DMX_FILTER_SIZE
|
||||
#undef DMX_FILTER_SIZE
|
||||
#endif
|
||||
#define DMX_FILTER_SIZE FILTER_LENGTH
|
||||
#endif /* TRIPLEDRAGON */
|
||||
|
||||
#include <cs_types.h>
|
||||
|
||||
#define MAX_DMX_UNITS 4
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DMX_INVALID = 0,
|
||||
DMX_VIDEO_CHANNEL = 1,
|
||||
DMX_AUDIO_CHANNEL,
|
||||
DMX_PES_CHANNEL,
|
||||
DMX_PSI_CHANNEL,
|
||||
DMX_PIP_CHANNEL,
|
||||
DMX_TP_CHANNEL,
|
||||
DMX_PCR_ONLY_CHANNEL
|
||||
} DMX_CHANNEL_TYPE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int fd;
|
||||
unsigned short pid;
|
||||
} pes_pids;
|
||||
|
||||
class cRecord;
|
||||
class cPlayback;
|
||||
class cDemux
|
||||
{
|
||||
friend class cRecord;
|
||||
friend class cPlayback;
|
||||
public:
|
||||
bool Open(DMX_CHANNEL_TYPE pes_type, void * x = NULL, int y = 0);
|
||||
void Close(void);
|
||||
bool Start(bool record = false);
|
||||
bool Stop(void);
|
||||
int Read(unsigned char *buff, int len, int Timeout = 0);
|
||||
bool sectionFilter(unsigned short pid, const unsigned char * const filter, const unsigned char * const mask, int len, int Timeout = 0, const unsigned char * const negmask = NULL);
|
||||
bool pesFilter(const unsigned short pid);
|
||||
void SetSyncMode(AVSYNC_TYPE mode);
|
||||
void * getBuffer();
|
||||
void * getChannel();
|
||||
DMX_CHANNEL_TYPE getChannelType(void) { return dmx_type; };
|
||||
bool addPid(unsigned short pid);
|
||||
void getSTC(int64_t * STC);
|
||||
int getUnit(void);
|
||||
static bool SetSource(int unit, int source);
|
||||
static int GetSource(int unit);
|
||||
cDemux(int num = 0);
|
||||
~cDemux();
|
||||
int getFD(void) { return fd; }; /* needed by cPlayback class */
|
||||
private:
|
||||
void removePid(unsigned short Pid); /* needed by cRecord class */
|
||||
int num;
|
||||
int fd;
|
||||
int buffersize;
|
||||
uint16_t pid;
|
||||
uint8_t flt;
|
||||
std::vector<pes_pids> pesfds;
|
||||
DMX_CHANNEL_TYPE dmx_type;
|
||||
void *pdata;
|
||||
};
|
||||
|
||||
#endif //__dmx_hal__
|
||||
|
@@ -1,10 +1,42 @@
|
||||
#include <config.h>
|
||||
#if HAVE_GENERIC_HARDWARE
|
||||
#if BOXMODEL_RASPI
|
||||
#include "../raspi/glfb.h"
|
||||
#else
|
||||
#include "../generic-pc/glfb.h"
|
||||
#endif
|
||||
#else
|
||||
#error glfb.h only works with HAVE_GENERIC_HARDWARE defined
|
||||
/*
|
||||
Copyright 2010 Carsten Juttner <carjay@gmx.net>
|
||||
Copyright 2012,2013 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __glfb__
|
||||
#define __glfb__
|
||||
#include <OpenThreads/Thread>
|
||||
#include <vector>
|
||||
#include <linux/fb.h> /* for screeninfo etc. */
|
||||
|
||||
class GLFramebuffer : public OpenThreads::Thread
|
||||
{
|
||||
public:
|
||||
GLFramebuffer(int x, int y);
|
||||
~GLFramebuffer();
|
||||
std::vector<unsigned char> *getOSDBuffer() { return &osd_buf; } /* pointer to OSD bounce buffer */
|
||||
void blit();
|
||||
fb_var_screeninfo getScreenInfo() { return si; }
|
||||
|
||||
private:
|
||||
fb_var_screeninfo si;
|
||||
std::vector<unsigned char> osd_buf; /* silly bounce buffer */
|
||||
void run(); /* for OpenThreads::Thread */
|
||||
void setup();
|
||||
void blit_osd();
|
||||
void *pdata; /* not yet used */
|
||||
};
|
||||
#endif
|
||||
|
@@ -36,13 +36,13 @@ typedef struct hw_caps
|
||||
display_type_t display_type;
|
||||
int display_xres; /* x resolution or chars per line */
|
||||
int display_yres;
|
||||
int display_can_set_brightness;
|
||||
int display_can_deepstandby;
|
||||
int display_can_set_brightness;
|
||||
int display_has_statusline;
|
||||
int has_button_vformat;
|
||||
char boxvendor[64];
|
||||
char boxname[64];
|
||||
char boxarch[64];
|
||||
int boxtype;
|
||||
int has_CI;
|
||||
} hw_caps_t;
|
||||
|
||||
hw_caps_t *get_hwcaps(void);
|
||||
|
@@ -5,30 +5,7 @@
|
||||
#define MAX_MMI_TEXT_LEN 255
|
||||
#define MAX_MMI_CHOICE_TEXT_LEN 255
|
||||
|
||||
typedef enum {
|
||||
MMI_TOP_MENU_SUBS = 1,
|
||||
MMI_TOP_MENU_EVENTS,
|
||||
MMI_TOP_MENU_TOKENS,
|
||||
MMI_TOP_MENU_PIN,
|
||||
MMI_TOP_MENU_MATURE,
|
||||
MMI_TOP_MENU_ABOUT
|
||||
} MMI_MENU_CURRENT;
|
||||
|
||||
typedef enum {
|
||||
MMI_MENU_LEVEL_MAIN = 0,
|
||||
MMI_MENU_LEVEL_MATURE,
|
||||
MMI_MENU_LEVEL_ASK_PIN_MATURE
|
||||
} MMI_MENU_LEVEL;
|
||||
|
||||
typedef enum {
|
||||
MMI_PIN_LEVEL_ASK_OLD = 0,
|
||||
MMI_PIN_LEVEL_CHECK_CURRENT,
|
||||
MMI_PIN_LEVEL_ASK_REPEAT,
|
||||
MMI_PIN_LEVEL_CHECK_AND_CHANGE
|
||||
} MMI_PIN_LEVEL;
|
||||
|
||||
typedef struct {
|
||||
int slot;
|
||||
int choice_nb;
|
||||
char title[MAX_MMI_TEXT_LEN];
|
||||
char subtitle[MAX_MMI_TEXT_LEN];
|
||||
@@ -37,7 +14,6 @@ typedef struct {
|
||||
} MMI_MENU_LIST_INFO;
|
||||
|
||||
typedef struct {
|
||||
int slot;
|
||||
int blind;
|
||||
int answerlen;
|
||||
char enquiryText[MAX_MMI_TEXT_LEN];
|
||||
|
@@ -1,25 +0,0 @@
|
||||
#ifndef _MUTEX_ABSTRACTION_H
|
||||
#define _MUTEX_ABSTRACTION_H
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
class Mutex
|
||||
{
|
||||
friend class Condition;
|
||||
|
||||
pthread_mutex_t mMutex;
|
||||
|
||||
Mutex(const Mutex&);
|
||||
const Mutex& operator=(const Mutex&);
|
||||
|
||||
protected:
|
||||
explicit Mutex(int);
|
||||
|
||||
public:
|
||||
Mutex();
|
||||
virtual ~Mutex();
|
||||
virtual void lock();
|
||||
virtual void unlock();
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,2 +1 @@
|
||||
#include <config.h>
|
||||
#include "playback_hal.h"
|
||||
|
@@ -1,24 +1,82 @@
|
||||
#include <config.h>
|
||||
#if HAVE_TRIPLEDRAGON
|
||||
#include "../libtriple/playback_td.h"
|
||||
#elif HAVE_DUCKBOX_HARDWARE
|
||||
#include "../libduckbox/playback_libeplayer3.h"
|
||||
#elif HAVE_SPARK_HARDWARE
|
||||
#include "../libspark/playback_libeplayer3.h"
|
||||
#elif HAVE_ARM_HARDWARE
|
||||
#include "../libarmbox/playback_gst.h"
|
||||
#elif HAVE_AZBOX_HARDWARE
|
||||
#include "../azbox/playback.h"
|
||||
#elif HAVE_GENERIC_HARDWARE
|
||||
#if BOXMODEL_RASPI
|
||||
#include "../raspi/playback.h"
|
||||
#else
|
||||
#if ENABLE_GSTREAMER
|
||||
#include "../generic-pc/playback_gst.h"
|
||||
#else
|
||||
#include "../generic-pc/playback.h"
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
||||
/*
|
||||
* (C) 2010-2013 Stefan Seyfried
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __playback_hal__
|
||||
#define __playback_hal__
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
}
|
||||
|
||||
/*
|
||||
* This is actually the max number that could be returned by
|
||||
* FindAllPids() / FindAllSubs().
|
||||
* not yet implemented, most archs return max. 10 PIDs.
|
||||
*/
|
||||
#define MAX_PLAYBACK_PIDS 40
|
||||
|
||||
typedef enum {
|
||||
PLAYMODE_TS = 0,
|
||||
PLAYMODE_FILE,
|
||||
} playmode_t;
|
||||
|
||||
class PBPrivate;
|
||||
class cPlayback
|
||||
{
|
||||
public:
|
||||
bool Open(playmode_t PlayMode);
|
||||
void Close(void);
|
||||
bool Start(char *filename, unsigned short vpid, int vtype, unsigned short apid, int ac3, unsigned int duration);
|
||||
bool Start(std::string filename, std::string headers = "");
|
||||
bool Stop(void);
|
||||
bool SetAPid(unsigned short pid, int audio_flag);
|
||||
bool SetSpeed(int speed);
|
||||
bool GetSpeed(int &speed) const;
|
||||
bool GetPosition(int &position, int &duration);
|
||||
bool SetPosition(int position, bool absolute = false);
|
||||
void FindAllPids(uint16_t *pids, unsigned short *aud_flags, uint16_t *num, std::string *language);
|
||||
void FindAllPids(int *apids, unsigned int *ac3flags, uint32_t *numpida, std::string *language){FindAllPids((uint16_t*)apids, (unsigned short*)ac3flags, (uint16_t*) numpida, language);}
|
||||
void FindAllSubs(uint16_t *pids, unsigned short *supported, uint16_t *num, std::string *language);
|
||||
bool SelectSubtitles(int pid, std::string charset = "");
|
||||
void GetChapters(std::vector<int> &positions, std::vector<std::string> &titles);
|
||||
void RequestAbort();
|
||||
void GetTitles(std::vector<int> &playlists, std::vector<std::string> &titles, int ¤t);
|
||||
void SetTitle(int title);
|
||||
uint64_t GetReadCount(void);
|
||||
void FindAllTeletextsubtitlePids(int *, unsigned int *numpids, std::string *, int *, int *){*numpids = 0;}
|
||||
void FindAllSubtitlePids(int * /*pids*/, unsigned int *numpids, std::string * /*language*/){*numpids = 0;}
|
||||
int GetSubtitlePid(void){return 0;}
|
||||
bool SetTeletextPid(int /*pid*/){return true;}
|
||||
int GetAPid(){return 0;}
|
||||
void GetMetadata(std::vector<std::string> /*&keys*/, std::vector<std::string> /*&values*/){}
|
||||
void GetPts(uint64_t &/*pts*/){}
|
||||
bool SetSubtitlePid(int /*pid*/){return false;}
|
||||
AVFormatContext *GetAVFormatContext(){return NULL;}
|
||||
void ReleaseAVFormatContext(){}
|
||||
|
||||
//
|
||||
cPlayback(int num = 0);
|
||||
~cPlayback();
|
||||
private:
|
||||
PBPrivate *pd;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -1,20 +1,47 @@
|
||||
#include <config.h>
|
||||
#if HAVE_TRIPLEDRAGON
|
||||
#include "../libtriple/pwrmngr.h"
|
||||
#elif HAVE_DUCKBOX_HARDWARE
|
||||
#include "../libduckbox/pwrmngr.h"
|
||||
#elif HAVE_SPARK_HARDWARE
|
||||
#include "../libspark/pwrmngr.h"
|
||||
#elif HAVE_ARM_HARDWARE
|
||||
#include "../libarmbox/pwrmngr.h"
|
||||
#elif HAVE_AZBOX_HARDWARE
|
||||
#include "../azbox/pwrmngr.h"
|
||||
#elif HAVE_GENERIC_HARDWARE
|
||||
#if BOXMODEL_RASPI
|
||||
#include "../raspi/pwrmngr.h"
|
||||
#else
|
||||
#include "../generic-pc/pwrmngr.h"
|
||||
#endif
|
||||
#else
|
||||
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
||||
/*
|
||||
* (C) 2010-2013 Stefan Seyfried
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __pwrmngr_hal__
|
||||
#define __pwrmngr_hal__
|
||||
|
||||
class cCpuFreqManager
|
||||
{
|
||||
public:
|
||||
cCpuFreqManager(void);
|
||||
void Up(void);
|
||||
void Down(void);
|
||||
void Reset(void);
|
||||
|
||||
bool SetCpuFreq(unsigned long CpuFreq);
|
||||
bool SetDelta(unsigned long Delta);
|
||||
unsigned long GetCpuFreq(void);
|
||||
unsigned long GetDelta(void);
|
||||
};
|
||||
|
||||
class cPowerManager
|
||||
{
|
||||
public:
|
||||
cPowerManager(void);
|
||||
virtual ~cPowerManager();
|
||||
|
||||
bool Open(void);
|
||||
void Close(void);
|
||||
|
||||
bool SetStandby(bool Active, bool Passive);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -1,20 +1,41 @@
|
||||
#include <config.h>
|
||||
#if HAVE_TRIPLEDRAGON
|
||||
#include "../libtriple/record_td.h"
|
||||
#elif HAVE_DUCKBOX_HARDWARE
|
||||
#include "../libduckbox/record_lib.h"
|
||||
#elif HAVE_SPARK_HARDWARE
|
||||
#include "../libspark/record_lib.h"
|
||||
#elif HAVE_ARM_HARDWARE
|
||||
#include "../libarmbox/record_lib.h"
|
||||
#elif HAVE_AZBOX_HARDWARE
|
||||
#include "../azbox/record_lib.h"
|
||||
#elif HAVE_GENERIC_HARDWARE
|
||||
#if BOXMODEL_RASPI
|
||||
#include "../raspi/record_lib.h"
|
||||
#else
|
||||
#include "../generic-pc/record_lib.h"
|
||||
#endif
|
||||
#else
|
||||
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
||||
/*
|
||||
* (C) 2010-2013 Stefan Seyfried
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef __record_hal__
|
||||
#define __record_hal__
|
||||
|
||||
#define REC_STATUS_OK 0
|
||||
#define REC_STATUS_SLOW 1
|
||||
#define REC_STATUS_OVERFLOW 2
|
||||
|
||||
class RecData;
|
||||
class cRecord
|
||||
{
|
||||
public:
|
||||
cRecord(int num = 0);
|
||||
~cRecord();
|
||||
|
||||
bool Open();
|
||||
bool Start(int fd, unsigned short vpid, unsigned short *apids, int numapids, uint64_t ch = 0);
|
||||
bool Stop(void);
|
||||
bool AddPid(unsigned short pid);
|
||||
int GetStatus();
|
||||
void ResetStatus();
|
||||
bool ChangePids(unsigned short vpid, unsigned short *apids, int numapids);
|
||||
private:
|
||||
RecData *pd;
|
||||
};
|
||||
#endif
|
||||
|
@@ -1,16 +0,0 @@
|
||||
#ifndef _REENTRANT_MUTEX_H
|
||||
#define _REENTRANT_MUTEX_H
|
||||
|
||||
#include "mutex_abstraction.h"
|
||||
|
||||
class ReentrantMutex : public Mutex
|
||||
{
|
||||
ReentrantMutex(const ReentrantMutex&);
|
||||
const ReentrantMutex& operator=(const ReentrantMutex&);
|
||||
|
||||
public:
|
||||
ReentrantMutex();
|
||||
virtual ~ReentrantMutex();
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,18 +0,0 @@
|
||||
#ifndef _SCOPED_LOCK_H
|
||||
#define _SCOPED_LOCK_H
|
||||
|
||||
#include "mutex_abstraction.h"
|
||||
|
||||
class ScopedLock
|
||||
{
|
||||
Mutex& mMutex;
|
||||
|
||||
ScopedLock(const ScopedLock&);
|
||||
const ScopedLock& operator=(const ScopedLock&);
|
||||
|
||||
public:
|
||||
ScopedLock(Mutex&);
|
||||
~ScopedLock();
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,30 +0,0 @@
|
||||
#ifndef _THREAD_ABSTRACTION_H
|
||||
#define _THREAD_ABSTRACTION_H
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
class Thread
|
||||
{
|
||||
bool mIsRunning;
|
||||
pthread_t mThread;
|
||||
|
||||
static void* runThread(void*);
|
||||
Thread(const Thread&);
|
||||
const Thread& operator=(const Thread&);
|
||||
|
||||
public:
|
||||
Thread();
|
||||
virtual ~Thread();
|
||||
int startThread();
|
||||
int cancelThread();
|
||||
int detachThread();
|
||||
int joinThread();
|
||||
|
||||
int setCancelModeDisable();
|
||||
int setSchedulePriority(int);
|
||||
|
||||
protected:
|
||||
virtual void run() = 0;
|
||||
};
|
||||
|
||||
#endif
|
22
include/version_hal.h
Normal file
22
include/version_hal.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef __VERSION_HAL_H__
|
||||
#define __VERSION_HAL_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
// library version functions
|
||||
typedef struct hal_libversion_t
|
||||
{
|
||||
std::string vVersion;
|
||||
int vMajor;
|
||||
int vMinor;
|
||||
int vPatch;;
|
||||
std::string vName;
|
||||
std::string vStr;
|
||||
std::string vGitDescribe;
|
||||
} hal_libversion_struct_t;
|
||||
|
||||
void hal_get_lib_version(hal_libversion_t *ver);
|
||||
|
||||
|
||||
#endif //__VERSION_HAL_H__
|
||||
|
@@ -1,24 +1,213 @@
|
||||
#include <config.h>
|
||||
#if HAVE_TRIPLEDRAGON
|
||||
#include "../libtriple/video_td.h"
|
||||
#elif HAVE_DUCKBOX_HARDWARE
|
||||
#include "../libduckbox/video_lib.h"
|
||||
#elif HAVE_SPARK_HARDWARE
|
||||
#include "../libspark/video_lib.h"
|
||||
#elif HAVE_ARM_HARDWARE
|
||||
#include "../libarmbox/video_lib.h"
|
||||
#elif HAVE_AZBOX_HARDWARE
|
||||
#include "../azbox/video_lib.h"
|
||||
#elif HAVE_GENERIC_HARDWARE
|
||||
#if BOXMODEL_RASPI
|
||||
#include "../raspi/video_lib.h"
|
||||
#else
|
||||
#include "../generic-pc/video_lib.h"
|
||||
#endif
|
||||
#else
|
||||
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
||||
#endif
|
||||
/*
|
||||
Copyright 2010-2013 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _VIDEO_LIB_H
|
||||
#define _VIDEO_LIB_H
|
||||
|
||||
#include <vector>
|
||||
#include <cs_types.h>
|
||||
|
||||
typedef enum {
|
||||
ANALOG_SD_RGB_CINCH = 0x00,
|
||||
ANALOG_SD_YPRPB_CINCH,
|
||||
ANALOG_HD_RGB_CINCH,
|
||||
ANALOG_HD_YPRPB_CINCH,
|
||||
ANALOG_SD_RGB_SCART = 0x10,
|
||||
ANALOG_SD_YPRPB_SCART,
|
||||
ANALOG_HD_RGB_SCART,
|
||||
ANALOG_HD_YPRPB_SCART,
|
||||
ANALOG_SCART_MASK = 0x10
|
||||
} analog_mode_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
VIDEO_FORMAT_MPEG2 = 0,
|
||||
VIDEO_FORMAT_MPEG4, /* H264 */
|
||||
VIDEO_FORMAT_VC1,
|
||||
VIDEO_FORMAT_JPEG,
|
||||
VIDEO_FORMAT_GIF,
|
||||
VIDEO_FORMAT_PNG,
|
||||
VIDEO_FORMAT_DIVX,/* DIVX 3.11 */
|
||||
VIDEO_FORMAT_MPEG4PART2,/* MPEG4 SVH, MPEG4 SP, MPEG4 ASP, DIVX4,5,6 */
|
||||
VIDEO_FORMAT_REALVIDEO8,
|
||||
VIDEO_FORMAT_REALVIDEO9,
|
||||
VIDEO_FORMAT_ON2_VP6,
|
||||
VIDEO_FORMAT_ON2_VP8,
|
||||
VIDEO_FORMAT_SORENSON_SPARK,
|
||||
VIDEO_FORMAT_H263,
|
||||
VIDEO_FORMAT_H263_ENCODER,
|
||||
VIDEO_FORMAT_H264_ENCODER,
|
||||
VIDEO_FORMAT_MPEG4PART2_ENCODER,
|
||||
VIDEO_FORMAT_AVS,
|
||||
VIDEO_FORMAT_VIP656,
|
||||
VIDEO_FORMAT_UNSUPPORTED
|
||||
} VIDEO_FORMAT;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_SD = 0,
|
||||
VIDEO_HD,
|
||||
VIDEO_120x60i,
|
||||
VIDEO_320x240i,
|
||||
VIDEO_1440x800i,
|
||||
VIDEO_360x288i
|
||||
} VIDEO_DEFINITION;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_FRAME_RATE_23_976 = 0,
|
||||
VIDEO_FRAME_RATE_24,
|
||||
VIDEO_FRAME_RATE_25,
|
||||
VIDEO_FRAME_RATE_29_97,
|
||||
VIDEO_FRAME_RATE_30,
|
||||
VIDEO_FRAME_RATE_50,
|
||||
VIDEO_FRAME_RATE_59_94,
|
||||
VIDEO_FRAME_RATE_60
|
||||
} VIDEO_FRAME_RATE;
|
||||
|
||||
typedef enum {
|
||||
DISPLAY_AR_1_1,
|
||||
DISPLAY_AR_4_3,
|
||||
DISPLAY_AR_14_9,
|
||||
DISPLAY_AR_16_9,
|
||||
DISPLAY_AR_20_9,
|
||||
DISPLAY_AR_RAW,
|
||||
} DISPLAY_AR;
|
||||
|
||||
typedef enum {
|
||||
DISPLAY_AR_MODE_PANSCAN = 0,
|
||||
DISPLAY_AR_MODE_LETTERBOX,
|
||||
DISPLAY_AR_MODE_NONE,
|
||||
DISPLAY_AR_MODE_PANSCAN2
|
||||
} DISPLAY_AR_MODE;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_DB_DR_NEITHER = 0,
|
||||
VIDEO_DB_ON,
|
||||
VIDEO_DB_DR_BOTH
|
||||
} VIDEO_DB_DR;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_PLAY_STILL = 0,
|
||||
VIDEO_PLAY_CLIP,
|
||||
VIDEO_PLAY_TRICK,
|
||||
VIDEO_PLAY_MOTION,
|
||||
VIDEO_PLAY_MOTION_NO_SYNC
|
||||
} VIDEO_PLAY_MODE;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_STD_NTSC,
|
||||
VIDEO_STD_SECAM,
|
||||
VIDEO_STD_PAL,
|
||||
VIDEO_STD_480P,
|
||||
VIDEO_STD_576P,
|
||||
VIDEO_STD_720P60,
|
||||
VIDEO_STD_1080I60,
|
||||
VIDEO_STD_720P50,
|
||||
VIDEO_STD_1080I50,
|
||||
VIDEO_STD_1080P30,
|
||||
VIDEO_STD_1080P24,
|
||||
VIDEO_STD_1080P25,
|
||||
VIDEO_STD_1080P50,
|
||||
VIDEO_STD_1080P60,
|
||||
VIDEO_STD_AUTO,
|
||||
VIDEO_STD_MAX
|
||||
} VIDEO_STD;
|
||||
|
||||
/* not used, for dummy functions */
|
||||
typedef enum {
|
||||
VIDEO_HDMI_CEC_MODE_OFF = 0,
|
||||
VIDEO_HDMI_CEC_MODE_TUNER,
|
||||
VIDEO_HDMI_CEC_MODE_RECORDER
|
||||
} VIDEO_HDMI_CEC_MODE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VIDEO_CONTROL_BRIGHTNESS = 0,
|
||||
VIDEO_CONTROL_CONTRAST,
|
||||
VIDEO_CONTROL_SATURATION,
|
||||
VIDEO_CONTROL_HUE,
|
||||
VIDEO_CONTROL_SHARPNESS,
|
||||
VIDEO_CONTROL_MAX = VIDEO_CONTROL_SHARPNESS
|
||||
} VIDEO_CONTROL;
|
||||
|
||||
class cDemux;
|
||||
class cPlayback;
|
||||
class VDec;
|
||||
|
||||
class cVideo
|
||||
{
|
||||
friend class cPlayback;
|
||||
friend class cDemux;
|
||||
public:
|
||||
/* constructor & destructor */
|
||||
cVideo(int mode, void *, void *, unsigned int unit = 0);
|
||||
~cVideo(void);
|
||||
|
||||
void * GetTVEnc() { return NULL; };
|
||||
void * GetTVEncSD() { return NULL; };
|
||||
|
||||
/* aspect ratio */
|
||||
int getAspectRatio(void);
|
||||
void getPictureInfo(int &width, int &height, int &rate);
|
||||
int setAspectRatio(int aspect, int mode);
|
||||
|
||||
/* cropping mode */
|
||||
int setCroppingMode(void);
|
||||
|
||||
/* get play state */
|
||||
int getPlayState(void);
|
||||
|
||||
/* blank on freeze */
|
||||
int getBlank(void);
|
||||
int setBlank(int enable);
|
||||
|
||||
/* change video play state. Parameters are all unused. */
|
||||
int Start(void *PcrChannel = NULL, unsigned short PcrPid = 0, unsigned short VideoPid = 0, void *x = NULL);
|
||||
int Stop(bool blank = true);
|
||||
bool Pause(void);
|
||||
|
||||
int GetVideoSystem();
|
||||
|
||||
/* set video_system */
|
||||
int SetVideoSystem(int video_system, bool remember = true);
|
||||
int SetStreamType(VIDEO_FORMAT type);
|
||||
void SetSyncMode(AVSYNC_TYPE mode);
|
||||
bool SetCECMode(VIDEO_HDMI_CEC_MODE) { return true; };
|
||||
void SetCECAutoView(bool) { return; };
|
||||
void SetCECAutoStandby(bool) { return; };
|
||||
bool ShowPicture(const char * fname);
|
||||
void StopPicture();
|
||||
void Standby(unsigned int bOn);
|
||||
void Pig(int x, int y, int w, int h, int osd_w = 1064, int osd_h = 600);
|
||||
void SetControl(int, int) { return; };
|
||||
void setContrast(int val);
|
||||
void SetVideoMode(analog_mode_t mode);
|
||||
void SetDBDR(int) { return; };
|
||||
void SetAudioHandle(void *) { return; };
|
||||
void SetAutoModes(int [VIDEO_STD_MAX]) { return; };
|
||||
int OpenVBI(int) { return 0; };
|
||||
int CloseVBI(void) { return 0; };
|
||||
int StartVBI(unsigned short) { return 0; };
|
||||
int StopVBI(void) { return 0; };
|
||||
void SetDemux(cDemux *dmx);
|
||||
bool GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video = true, bool get_osd = false, bool scale_to_video = false);
|
||||
private:
|
||||
VDec *vdec;
|
||||
void *pdata;
|
||||
};
|
||||
|
||||
#if STB_HAL_VIDEO_HAS_GETSCREENIMAGE
|
||||
#define SCREENSHOT 1
|
||||
#endif
|
||||
|
@@ -1,29 +0,0 @@
|
||||
noinst_LTLIBRARIES = libarmbox.la
|
||||
|
||||
AM_CPPFLAGS = -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
|
||||
AM_CPPFLAGS += \
|
||||
-I$(top_srcdir)/common \
|
||||
-I$(top_srcdir)/include
|
||||
|
||||
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
|
||||
|
||||
AM_LDFLAGS = \
|
||||
-lOpenThreads \
|
||||
@AVFORMAT_LIBS@ \
|
||||
@AVUTIL_LIBS@ \
|
||||
@AVCODEC_LIBS@ \
|
||||
@SWRESAMPLE_LIBS@ \
|
||||
-lpthread -lasound -lrt \
|
||||
-lgstreamer-1.0 \
|
||||
-lgsttag-1.0 \
|
||||
-lgstmpegts-1.0
|
||||
|
||||
libarmbox_la_SOURCES = \
|
||||
hardware_caps.c \
|
||||
dmx.cpp \
|
||||
video.cpp \
|
||||
audio.cpp \
|
||||
init.cpp \
|
||||
playback_gst.cpp \
|
||||
pwrmngr.cpp \
|
||||
record.cpp
|
@@ -1,480 +0,0 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <linux/dvb/audio.h>
|
||||
|
||||
#include <proc_tools.h>
|
||||
#include "audio_lib.h"
|
||||
//#include "audio_mixer.h"
|
||||
#include "lt_debug.h"
|
||||
|
||||
#define AUDIO_DEVICE "/dev/dvb/adapter0/audio0"
|
||||
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_AUDIO, this, args)
|
||||
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_AUDIO, this, args)
|
||||
|
||||
#include <linux/soundcard.h>
|
||||
|
||||
cAudio * audioDecoder = NULL;
|
||||
|
||||
cAudio::cAudio(void *, void *, void *)
|
||||
{
|
||||
fd = -1;
|
||||
clipfd = -1;
|
||||
mixer_fd = -1;
|
||||
|
||||
/*
|
||||
mixerAnalog = mixerHDMI = mixerSPDIF = NULL;
|
||||
volumeAnalog = volumeHDMI = volumeSPDIF = 0;
|
||||
mixersMuted = false
|
||||
*/
|
||||
|
||||
openDevice();
|
||||
Muted = false;
|
||||
}
|
||||
|
||||
cAudio::~cAudio(void)
|
||||
{
|
||||
//closeMixers();
|
||||
closeDevice();
|
||||
}
|
||||
|
||||
void cAudio::openDevice(void)
|
||||
{
|
||||
//openMixers();
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
if ((fd = open(AUDIO_DEVICE, O_RDWR)) < 0)
|
||||
lt_info("openDevice: open failed (%m)\n");
|
||||
fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
do_mute(true, false);
|
||||
}
|
||||
else
|
||||
lt_info("openDevice: already open (fd = %d)\n", fd);
|
||||
}
|
||||
|
||||
void cAudio::closeDevice(void)
|
||||
{
|
||||
//closeMixers();
|
||||
|
||||
if (fd > -1) {
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
if (clipfd > -1) {
|
||||
close(clipfd);
|
||||
clipfd = -1;
|
||||
}
|
||||
if (mixer_fd > -1) {
|
||||
close(mixer_fd);
|
||||
mixer_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int cAudio::do_mute(bool enable, bool remember)
|
||||
{
|
||||
lt_debug("%s(%d, %d)\n", __FUNCTION__, enable, remember);
|
||||
char str[4];
|
||||
|
||||
if (remember)
|
||||
Muted = enable;
|
||||
|
||||
sprintf(str, "%d", Muted);
|
||||
proc_put("/proc/stb/audio/j1_mute", str, strlen(str));
|
||||
|
||||
if (!enable)
|
||||
{
|
||||
int f = open("/proc/stb/avs/0/volume", O_RDWR);
|
||||
read(f, str, 4);
|
||||
close(f);
|
||||
str[3] = '\0';
|
||||
proc_put("/proc/stb/avs/0/volume", str, strlen(str));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int map_volume(const int volume)
|
||||
{
|
||||
unsigned char vol = volume;
|
||||
if (vol > 100)
|
||||
vol = 100;
|
||||
|
||||
vol = 63 - vol * 63 / 100;
|
||||
return vol;
|
||||
}
|
||||
|
||||
int cAudio::setVolume(unsigned int left, unsigned int right)
|
||||
{
|
||||
lt_debug("%s(%d, %d)\n", __func__, left, right);
|
||||
|
||||
volume = (left + right) / 2;
|
||||
int v = map_volume(volume);
|
||||
#if 0
|
||||
if (clipfd != -1 && mixer_fd != -1) {
|
||||
int tmp = 0;
|
||||
/* not sure if left / right is correct here, but it is always the same anyways ;-) */
|
||||
if (! Muted)
|
||||
tmp = left << 8 | right;
|
||||
int ret = ioctl(mixer_fd, MIXER_WRITE(mixer_num), &tmp);
|
||||
if (ret == -1)
|
||||
lt_info("%s: MIXER_WRITE(%d),%04x: %m\n", __func__, mixer_num, tmp);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
char str[4];
|
||||
sprintf(str, "%d", v);
|
||||
|
||||
proc_put("/proc/stb/avs/0/volume", str, strlen(str));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cAudio::Start(void)
|
||||
{
|
||||
int ret;
|
||||
ret = ioctl(fd, AUDIO_PLAY);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cAudio::Stop(void)
|
||||
{
|
||||
return ioctl(fd, AUDIO_STOP);
|
||||
}
|
||||
|
||||
bool cAudio::Pause(bool Pcm)
|
||||
{
|
||||
ioctl(fd, Pcm ? AUDIO_PAUSE : AUDIO_CONTINUE, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
void cAudio::SetSyncMode(AVSYNC_TYPE Mode)
|
||||
{
|
||||
lt_debug("%s %d\n", __func__, Mode);
|
||||
ioctl(fd, AUDIO_SET_AV_SYNC, Mode);
|
||||
}
|
||||
|
||||
// E2 streamtype values. These correspond to
|
||||
// player2/linux/drivers/media/dvb/stm/dvb/dvb_audio.c:AudioIoctlSetBypassMode
|
||||
#define AUDIO_STREAMTYPE_AC3 0
|
||||
#define AUDIO_STREAMTYPE_MPEG 1
|
||||
#define AUDIO_STREAMTYPE_DTS 2
|
||||
#define AUDIO_STREAMTYPE_AAC 8
|
||||
#define AUDIO_STREAMTYPE_AACHE 9
|
||||
|
||||
void cAudio::SetStreamType(AUDIO_FORMAT type)
|
||||
{
|
||||
int bypass = AUDIO_STREAMTYPE_MPEG;
|
||||
lt_debug("%s %d\n", __FUNCTION__, type);
|
||||
StreamType = type;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case AUDIO_FMT_DD_PLUS:
|
||||
case AUDIO_FMT_DOLBY_DIGITAL:
|
||||
bypass = AUDIO_STREAMTYPE_AC3;
|
||||
break;
|
||||
case AUDIO_FMT_AAC:
|
||||
bypass = AUDIO_STREAMTYPE_AAC;
|
||||
break;
|
||||
case AUDIO_FMT_AAC_PLUS:
|
||||
bypass = AUDIO_STREAMTYPE_AACHE;
|
||||
break;
|
||||
case AUDIO_FMT_DTS:
|
||||
bypass = AUDIO_STREAMTYPE_DTS;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Normaly the encoding should be set using AUDIO_SET_ENCODING
|
||||
// But as we implemented the behavior to bypass (cause of e2) this is correct here
|
||||
if (ioctl(fd, AUDIO_SET_BYPASS_MODE, bypass) < 0)
|
||||
lt_info("%s: AUDIO_SET_BYPASS_MODE failed (%m)\n", __func__);
|
||||
}
|
||||
|
||||
int cAudio::setChannel(int channel)
|
||||
{
|
||||
lt_debug("%s %d\n", __FUNCTION__, channel);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cAudio::PrepareClipPlay(int ch, int srate, int bits, int little_endian)
|
||||
{
|
||||
int fmt;
|
||||
unsigned int devmask, stereo, usable;
|
||||
const char *dsp_dev = getenv("DSP_DEVICE");
|
||||
const char *mix_dev = getenv("MIX_DEVICE");
|
||||
lt_debug("%s ch %d srate %d bits %d le %d\n", __FUNCTION__, ch, srate, bits, little_endian);
|
||||
if (clipfd > -1) {
|
||||
lt_info("%s: clipfd already opened (%d)\n", __FUNCTION__, clipfd);
|
||||
return -1;
|
||||
}
|
||||
mixer_num = -1;
|
||||
/* a different DSP device can be given with DSP_DEVICE and MIX_DEVICE
|
||||
* if this device cannot be opened, we fall back to the internal OSS device
|
||||
* Example:
|
||||
* modprobe snd-usb-audio
|
||||
* export DSP_DEVICE=/dev/sound/dsp2
|
||||
* export MIX_DEVICE=/dev/sound/mixer2
|
||||
* neutrino
|
||||
*/
|
||||
if ((!dsp_dev) || (access(dsp_dev, W_OK))) {
|
||||
if (dsp_dev)
|
||||
lt_info("%s: DSP_DEVICE is set (%s) but cannot be opened,"
|
||||
" fall back to /dev/dsp\n", __func__, dsp_dev);
|
||||
dsp_dev = "/dev/dsp";
|
||||
}
|
||||
if ((!mix_dev) || (access(mix_dev, W_OK))) {
|
||||
if (mix_dev)
|
||||
lt_info("%s: MIX_DEVICE is set (%s) but cannot be opened,"
|
||||
" fall back to /dev/mixer\n", __func__, dsp_dev);
|
||||
mix_dev = "/dev/mixer";
|
||||
}
|
||||
lt_info("%s: dsp_dev %s mix_dev %s\n", __func__, dsp_dev, mix_dev); /* NULL mix_dev is ok */
|
||||
/* the tdoss dsp driver seems to work only on the second open(). really. */
|
||||
clipfd = open(dsp_dev, O_WRONLY);
|
||||
if (clipfd < 0) {
|
||||
lt_info("%s open %s: %m\n", dsp_dev, __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
fcntl(clipfd, F_SETFD, FD_CLOEXEC);
|
||||
/* no idea if we ever get little_endian == 0 */
|
||||
if (little_endian)
|
||||
fmt = AFMT_S16_BE;
|
||||
else
|
||||
fmt = AFMT_S16_LE;
|
||||
if (ioctl(clipfd, SNDCTL_DSP_SETFMT, &fmt))
|
||||
perror("SNDCTL_DSP_SETFMT");
|
||||
if (ioctl(clipfd, SNDCTL_DSP_CHANNELS, &ch))
|
||||
perror("SNDCTL_DSP_CHANNELS");
|
||||
if (ioctl(clipfd, SNDCTL_DSP_SPEED, &srate))
|
||||
perror("SNDCTL_DSP_SPEED");
|
||||
if (ioctl(clipfd, SNDCTL_DSP_RESET))
|
||||
perror("SNDCTL_DSP_RESET");
|
||||
|
||||
if (!mix_dev)
|
||||
return 0;
|
||||
|
||||
mixer_fd = open(mix_dev, O_RDWR);
|
||||
if (mixer_fd < 0) {
|
||||
lt_info("%s: open mixer %s failed (%m)\n", __func__, mix_dev);
|
||||
/* not a real error */
|
||||
return 0;
|
||||
}
|
||||
if (ioctl(mixer_fd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) {
|
||||
lt_info("%s: SOUND_MIXER_READ_DEVMASK %m\n", __func__);
|
||||
devmask = 0;
|
||||
}
|
||||
if (ioctl(mixer_fd, SOUND_MIXER_READ_STEREODEVS, &stereo) == -1) {
|
||||
lt_info("%s: SOUND_MIXER_READ_STEREODEVS %m\n", __func__);
|
||||
stereo = 0;
|
||||
}
|
||||
usable = devmask & stereo;
|
||||
if (usable == 0) {
|
||||
lt_info("%s: devmask: %08x stereo: %08x, no usable dev :-(\n",
|
||||
__func__, devmask, stereo);
|
||||
close(mixer_fd);
|
||||
mixer_fd = -1;
|
||||
return 0; /* TODO: should we treat this as error? */
|
||||
}
|
||||
/* __builtin_popcount needs GCC, it counts the set bits... */
|
||||
if (__builtin_popcount (usable) != 1) {
|
||||
/* TODO: this code is not yet tested as I have only single-mixer devices... */
|
||||
lt_info("%s: more than one mixer control: devmask %08x stereo %08x\n"
|
||||
"%s: querying MIX_NUMBER environment variable...\n",
|
||||
__func__, devmask, stereo, __func__);
|
||||
const char *tmp = getenv("MIX_NUMBER");
|
||||
if (tmp)
|
||||
mixer_num = atoi(tmp);
|
||||
lt_info("%s: mixer_num is %d -> device %08x\n",
|
||||
__func__, mixer_num, (mixer_num >= 0) ? (1 << mixer_num) : 0);
|
||||
/* no error checking, you'd better know what you are doing... */
|
||||
} else {
|
||||
mixer_num = 0;
|
||||
while (!(usable & 0x01)) {
|
||||
mixer_num++;
|
||||
usable >>= 1;
|
||||
}
|
||||
}
|
||||
setVolume(volume, volume);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cAudio::WriteClip(unsigned char *buffer, int size)
|
||||
{
|
||||
int ret;
|
||||
// lt_debug("cAudio::%s\n", __FUNCTION__);
|
||||
if (clipfd < 0) {
|
||||
lt_info("%s: clipfd not yet opened\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
ret = write(clipfd, buffer, size);
|
||||
if (ret < 0)
|
||||
lt_info("%s: write error (%m)\n", __FUNCTION__);
|
||||
return ret;
|
||||
};
|
||||
|
||||
int cAudio::StopClip()
|
||||
{
|
||||
lt_debug("%s\n", __FUNCTION__);
|
||||
if (clipfd < 0) {
|
||||
lt_info("%s: clipfd not yet opened\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
close(clipfd);
|
||||
clipfd = -1;
|
||||
if (mixer_fd >= -1) {
|
||||
close(mixer_fd);
|
||||
mixer_fd = -1;
|
||||
}
|
||||
setVolume(volume, volume);
|
||||
return 0;
|
||||
};
|
||||
|
||||
void cAudio::getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &mode)
|
||||
{
|
||||
lt_debug("%s\n", __FUNCTION__);
|
||||
type = 0;
|
||||
layer = 0;
|
||||
freq = 0;
|
||||
bitrate = 0;
|
||||
mode = 0;
|
||||
#if 0
|
||||
unsigned int atype;
|
||||
static const int freq_mpg[] = {44100, 48000, 32000, 0};
|
||||
static const int freq_ac3[] = {48000, 44100, 32000, 0};
|
||||
scratchl2 i;
|
||||
if (ioctl(fd, MPEG_AUD_GET_DECTYP, &atype) < 0)
|
||||
perror("cAudio::getAudioInfo MPEG_AUD_GET_DECTYP");
|
||||
if (ioctl(fd, MPEG_AUD_GET_STATUS, &i) < 0)
|
||||
perror("cAudio::getAudioInfo MPEG_AUD_GET_STATUS");
|
||||
|
||||
type = atype;
|
||||
#if 0
|
||||
/* this does not work, some of the values are negative?? */
|
||||
AMPEGStatus A;
|
||||
memcpy(&A, &i.word00, sizeof(i.word00));
|
||||
layer = A.audio_mpeg_layer;
|
||||
mode = A.audio_mpeg_mode;
|
||||
bitrate = A.audio_mpeg_bitrate;
|
||||
switch(A.audio_mpeg_frequency)
|
||||
#endif
|
||||
/* layer and bitrate are not used anyway... */
|
||||
layer = 0; //(i.word00 >> 17) & 3;
|
||||
bitrate = 0; //(i.word00 >> 12) & 3;
|
||||
switch (type)
|
||||
{
|
||||
case 0: /* MPEG */
|
||||
mode = (i.word00 >> 6) & 3;
|
||||
freq = freq_mpg[(i.word00 >> 10) & 3];
|
||||
break;
|
||||
case 1: /* AC3 */
|
||||
mode = (i.word00 >> 28) & 7;
|
||||
freq = freq_ac3[(i.word00 >> 16) & 3];
|
||||
break;
|
||||
default:
|
||||
mode = 0;
|
||||
freq = 0;
|
||||
}
|
||||
//fprintf(stderr, "type: %d layer: %d freq: %d bitrate: %d mode: %d\n", type, layer, freq, bitrate, mode);
|
||||
#endif
|
||||
};
|
||||
|
||||
void cAudio::SetSRS(int /*iq_enable*/, int /*nmgr_enable*/, int /*iq_mode*/, int /*iq_level*/)
|
||||
{
|
||||
lt_debug("%s\n", __FUNCTION__);
|
||||
};
|
||||
|
||||
void cAudio::SetHdmiDD(bool enable)
|
||||
{
|
||||
const char *opt[] = { "downmix", "passthrough" };
|
||||
lt_debug("%s %d\n", __func__, enable);
|
||||
proc_put("/proc/stb/audio/ac3", opt[enable], strlen(opt[enable]));
|
||||
}
|
||||
|
||||
void cAudio::SetSpdifDD(bool enable)
|
||||
{
|
||||
//using this function for dts passthrough
|
||||
const char *opt[] = { "downmix", "passthrough" };
|
||||
lt_debug("%s %d\n", __func__, enable);
|
||||
proc_put("/proc/stb/audio/dts", opt[enable], strlen(opt[enable]));
|
||||
}
|
||||
|
||||
void cAudio::ScheduleMute(bool On)
|
||||
{
|
||||
lt_debug("%s %d\n", __FUNCTION__, On);
|
||||
}
|
||||
|
||||
void cAudio::EnableAnalogOut(bool enable)
|
||||
{
|
||||
lt_debug("%s %d\n", __FUNCTION__, enable);
|
||||
}
|
||||
|
||||
#define AUDIO_BYPASS_ON 0
|
||||
#define AUDIO_BYPASS_OFF 1
|
||||
void cAudio::setBypassMode(bool disable)
|
||||
{
|
||||
int mode = disable ? AUDIO_BYPASS_OFF : AUDIO_BYPASS_ON;
|
||||
if (ioctl(fd, AUDIO_SET_BYPASS_MODE, mode) < 0)
|
||||
lt_info("%s AUDIO_SET_BYPASS_MODE %d: %m\n", __func__, mode);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void cAudio::openMixers(void)
|
||||
{
|
||||
if (!mixerAnalog)
|
||||
mixerAnalog = new mixerVolume("Analog", "1");
|
||||
if (!mixerHDMI)
|
||||
mixerHDMI = new mixerVolume("HDMI", "1");
|
||||
if (!mixerSPDIF)
|
||||
mixerSPDIF = new mixerVolume("SPDIF", "1");
|
||||
}
|
||||
|
||||
void cAudio::closeMixers(void)
|
||||
{
|
||||
delete mixerAnalog;
|
||||
delete mixerHDMI;
|
||||
delete mixerSPDIF;
|
||||
mixerAnalog = mixerHDMI = mixerSPDIF = NULL;
|
||||
}
|
||||
|
||||
void cAudio::setMixerVolume(const char *name, long value, bool remember)
|
||||
{
|
||||
if (!strcmp(name, "Analog")) {
|
||||
mixerAnalog->setVolume(value);
|
||||
if (remember)
|
||||
volumeAnalog = value;
|
||||
}
|
||||
if (!strcmp(name, "HDMI")) {
|
||||
mixerHDMI->setVolume(value);
|
||||
if (remember)
|
||||
volumeHDMI = value;
|
||||
}
|
||||
if (!strcmp(name, "SPDIF")) {
|
||||
mixerSPDIF->setVolume(value);
|
||||
if (remember)
|
||||
volumeSPDIF = value;
|
||||
}
|
||||
}
|
||||
|
||||
void cAudio::muteMixers(bool m)
|
||||
{
|
||||
if (m && !mixersMuted) {
|
||||
mixersMuted = true;
|
||||
setMixerVolume("Analog", 0, false);
|
||||
setMixerVolume("HDMI", 0, false);
|
||||
setMixerVolume("SPDIF", 0, false);
|
||||
} else if (!m && mixersMuted) {
|
||||
mixersMuted = false;
|
||||
setMixerVolume("Analog", volumeAnalog, false);
|
||||
setMixerVolume("HDMI", volumeHDMI, false);
|
||||
setMixerVolume("SPDIF", volumeSPDIF, false);
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -1,111 +0,0 @@
|
||||
/* public header file */
|
||||
|
||||
#ifndef _AUDIO_TD_H_
|
||||
#define _AUDIO_TD_H_
|
||||
#include "../common/cs_types.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_SYNC_WITH_PTS,
|
||||
AUDIO_NO_SYNC,
|
||||
AUDIO_SYNC_AUDIO_MASTER
|
||||
} AUDIO_SYNC_MODE;
|
||||
|
||||
typedef enum {
|
||||
HDMI_ENCODED_OFF,
|
||||
HDMI_ENCODED_AUTO,
|
||||
HDMI_ENCODED_FORCED
|
||||
} HDMI_ENCODED_MODE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_FMT_AUTO = 0,
|
||||
AUDIO_FMT_MPEG,
|
||||
AUDIO_FMT_MP3,
|
||||
AUDIO_FMT_DOLBY_DIGITAL,
|
||||
AUDIO_FMT_BASIC = AUDIO_FMT_DOLBY_DIGITAL,
|
||||
AUDIO_FMT_AAC,
|
||||
AUDIO_FMT_AAC_PLUS,
|
||||
AUDIO_FMT_DD_PLUS,
|
||||
AUDIO_FMT_DTS,
|
||||
AUDIO_FMT_AVS,
|
||||
AUDIO_FMT_MLP,
|
||||
AUDIO_FMT_WMA,
|
||||
AUDIO_FMT_MPG1, // TD only. For Movieplayer / cPlayback
|
||||
AUDIO_FMT_ADVANCED = AUDIO_FMT_MLP
|
||||
} AUDIO_FORMAT;
|
||||
|
||||
class mixerVolume;
|
||||
|
||||
class cAudio
|
||||
{
|
||||
friend class cPlayback;
|
||||
private:
|
||||
int fd;
|
||||
bool Muted;
|
||||
|
||||
int clipfd; /* for pcm playback */
|
||||
int mixer_fd; /* if we are using the OSS mixer */
|
||||
int mixer_num; /* oss mixer to use, if any */
|
||||
|
||||
AUDIO_FORMAT StreamType;
|
||||
AUDIO_SYNC_MODE SyncMode;
|
||||
bool started;
|
||||
|
||||
int volume;
|
||||
|
||||
int do_mute(bool enable, bool remember);
|
||||
void setBypassMode(bool disable);
|
||||
|
||||
mixerVolume *mixerAnalog, *mixerHDMI, *mixerSPDIF;
|
||||
int volumeAnalog, volumeHDMI, volumeSPDIF;
|
||||
bool mixersMuted;
|
||||
|
||||
public:
|
||||
/* construct & destruct */
|
||||
cAudio(void *, void *, void *);
|
||||
~cAudio(void);
|
||||
|
||||
void openDevice(void);
|
||||
void closeDevice(void);
|
||||
|
||||
void *GetHandle() { return NULL; };
|
||||
/* shut up */
|
||||
int mute(bool remember = true) { return do_mute(true, remember); };
|
||||
int unmute(bool remember = true) { return do_mute(false, remember); };
|
||||
|
||||
/* volume, min = 0, max = 255 */
|
||||
int setVolume(unsigned int left, unsigned int right);
|
||||
int getVolume(void) { return volume;}
|
||||
bool getMuteStatus(void) { return Muted; };
|
||||
|
||||
/* start and stop audio */
|
||||
int Start(void);
|
||||
int Stop(void);
|
||||
bool Pause(bool Pcm = true);
|
||||
void SetStreamType(AUDIO_FORMAT type);
|
||||
AUDIO_FORMAT GetStreamType(void) { return StreamType; }
|
||||
void SetSyncMode(AVSYNC_TYPE Mode);
|
||||
|
||||
/* select channels */
|
||||
int setChannel(int channel);
|
||||
int PrepareClipPlay(int uNoOfChannels, int uSampleRate, int uBitsPerSample, int bLittleEndian);
|
||||
int WriteClip(unsigned char * buffer, int size);
|
||||
int StopClip();
|
||||
void getAudioInfo(int &type, int &layer, int& freq, int &bitrate, int &mode);
|
||||
void SetSRS(int iq_enable, int nmgr_enable, int iq_mode, int iq_level);
|
||||
bool IsHdmiDDSupported() { return true; };
|
||||
void SetHdmiDD(bool enable);
|
||||
void SetSpdifDD(bool enable);
|
||||
void ScheduleMute(bool On);
|
||||
void EnableAnalogOut(bool enable);
|
||||
|
||||
#if 0
|
||||
void openMixers(void);
|
||||
void closeMixers(void);
|
||||
void setMixerVolume(const char *name, long value, bool remember = true);
|
||||
void muteMixers(bool m = true);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* audio_mixer.cpp
|
||||
*
|
||||
* (C) 2012 martii
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <audio_mixer.h>
|
||||
|
||||
mixerVolume::mixerVolume(const char *name, const char *card, long volume) {
|
||||
snd_mixer_selem_id_t *sid = NULL;
|
||||
elem = NULL;
|
||||
handle = NULL;
|
||||
min = 0;
|
||||
max = 100;
|
||||
char cardId[10];
|
||||
|
||||
if (!name || !card)
|
||||
return;
|
||||
|
||||
int cx = snd_card_get_index(card);
|
||||
if (cx < 0 || cx > 31)
|
||||
return;
|
||||
snprintf(cardId, sizeof(cardId), "hw:%i", cx);
|
||||
|
||||
if (0 > snd_mixer_open(&handle, 0))
|
||||
return;
|
||||
if (0 > snd_mixer_attach(handle, cardId))
|
||||
return;
|
||||
if (0 > snd_mixer_selem_register(handle, NULL, NULL))
|
||||
return;
|
||||
if (0 > snd_mixer_load(handle))
|
||||
return;
|
||||
snd_mixer_selem_id_alloca(&sid);
|
||||
if (!sid)
|
||||
return;
|
||||
snd_mixer_selem_id_set_index(sid, 0);
|
||||
snd_mixer_selem_id_set_name(sid, name);
|
||||
elem = snd_mixer_find_selem(handle, sid);
|
||||
if (elem) {
|
||||
snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
|
||||
setVolume(volume);
|
||||
}
|
||||
}
|
||||
mixerVolume::~mixerVolume()
|
||||
{
|
||||
if (handle)
|
||||
snd_mixer_close(handle);
|
||||
}
|
||||
|
||||
bool mixerVolume::setVolume(long volume) {
|
||||
return elem
|
||||
&& (volume > -1)
|
||||
&& (volume < 101)
|
||||
&& !snd_mixer_selem_set_playback_volume_all(elem, min + volume * (max - min)/100);
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* audio_mixer.h
|
||||
*
|
||||
* (C) 2012 martii
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __AUDIO_MIXER_H__
|
||||
#define __AUDIO_MIXER_H__
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
class mixerVolume
|
||||
{
|
||||
private:
|
||||
long min, max;
|
||||
snd_mixer_t *handle;
|
||||
snd_mixer_elem_t* elem;
|
||||
public:
|
||||
mixerVolume(const char *selem_name, const char *Card, long volume = -1);
|
||||
~mixerVolume(void);
|
||||
bool setVolume(long volume);
|
||||
};
|
||||
#endif
|
||||
|
@@ -1,67 +0,0 @@
|
||||
/* compatibility header for tripledragon. I'm lazy, so I just left it
|
||||
as "cs_api.h" so that I don't need too many ifdefs in the code */
|
||||
|
||||
#ifndef __CS_API_H_
|
||||
#define __CS_API_H_
|
||||
|
||||
#include "init_lib.h"
|
||||
typedef void (*cs_messenger) (unsigned int msg, unsigned int data);
|
||||
|
||||
#if 0
|
||||
enum CS_LOG_MODULE {
|
||||
CS_LOG_CI = 0,
|
||||
CS_LOG_HDMI_CEC,
|
||||
CS_LOG_HDMI,
|
||||
CS_LOG_VIDEO,
|
||||
CS_LOG_VIDEO_DRM,
|
||||
CS_LOG_AUDIO,
|
||||
CS_LOG_DEMUX,
|
||||
CS_LOG_DENC,
|
||||
CS_LOG_PVR_RECORD,
|
||||
CS_LOG_PVR_PLAY,
|
||||
CS_LOG_POWER_CTRL,
|
||||
CS_LOG_POWER_CLK,
|
||||
CS_LOG_MEM,
|
||||
CS_LOG_API,
|
||||
};
|
||||
#endif
|
||||
|
||||
inline void cs_api_init()
|
||||
{
|
||||
init_td_api();
|
||||
};
|
||||
|
||||
inline void cs_api_exit()
|
||||
{
|
||||
shutdown_td_api();
|
||||
};
|
||||
|
||||
#define cs_malloc_uncached malloc
|
||||
#define cs_free_uncached free
|
||||
|
||||
// Callback function helpers
|
||||
void cs_register_messenger(cs_messenger messenger);
|
||||
static inline void cs_deregister_messenger(void) { return; };
|
||||
//cs_messenger cs_get_messenger(void);
|
||||
|
||||
#if 0
|
||||
// Logging functions
|
||||
void cs_log_enable(void);
|
||||
void cs_log_disable(void);
|
||||
void cs_log_message(const char *prefix, const char *fmt, ...);
|
||||
void cs_log_module_enable(enum CS_LOG_MODULE module);
|
||||
void cs_log_module_disable(enum CS_LOG_MODULE module);
|
||||
void cs_log_module_message(enum CS_LOG_MODULE module, const char *fmt, ...);
|
||||
|
||||
// TS Routing
|
||||
unsigned int cs_get_ts_output(void);
|
||||
int cs_set_ts_output(unsigned int port);
|
||||
|
||||
// Serial nr and revision accessors
|
||||
unsigned long long cs_get_serial(void);
|
||||
#endif
|
||||
/* compat... HD1 seems to be version 6. everything newer ist > 6... */
|
||||
static inline unsigned int cs_get_revision(void) { return 1; };
|
||||
static inline unsigned int cs_get_chip_type(void) { return 0; };
|
||||
extern int cnxt_debug;
|
||||
#endif //__CS_API_H_
|
@@ -1,594 +0,0 @@
|
||||
/*
|
||||
* cDemux implementation for SH4 receivers (tested on fulan spark and
|
||||
* fulan spark7162 hardware)
|
||||
*
|
||||
* derived from libtriple/dmx_td.cpp
|
||||
*
|
||||
* (C) 2010-2013 Stefan Seyfried
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Theory of operation (or "why is this dmx_source thing so strange and
|
||||
* what is the _open() good for?")
|
||||
*
|
||||
* the sh4 pti driver, driving the /dev/dvb/adapter0/dmxN devices, can
|
||||
* apparently only map one input to on demux device at a time, so e.g.
|
||||
* DMX_SOURCE_FRONT1 -> demux0
|
||||
* DMX_SOURCE_FRONT2 -> demux0
|
||||
* DMX_SOURCE_FRONT1 -> demux1
|
||||
* does not work. The driver makes sure that a one-to-one mapping of
|
||||
* DMX_SOURCE_FRONTn to demuxM is maintained, and it does by e.g changing
|
||||
* the default of
|
||||
* FRONT0 -> demux0
|
||||
* FRONT1 -> demux1
|
||||
* FRONT2 -> demux2
|
||||
* to
|
||||
* FRONT1 -> demux0
|
||||
* FRONT0 -> demux1
|
||||
* FRONT2 -> demux2
|
||||
* if you do a DMX_SET_SOURCE(FRONT1) ioctl on demux0.
|
||||
* This means, it also changes demux1's source on the SET_SOURCE ioctl on
|
||||
* demux0, potentially disturbing any operation on demux1 (e.g. recording).
|
||||
*
|
||||
* In order to avoid this, I do not change the source->demuxdev mapping
|
||||
* but instead just always use the demux device that is attached to the
|
||||
* correct source.
|
||||
*
|
||||
* The tricky part is, that the source might actually be changed after
|
||||
* Open() has been called, so Open() gets a dummy placeholder that just
|
||||
* sets some variables while the real device open is put into _open().
|
||||
* _open() gets called later, whenever the device is actually used or
|
||||
* configured and -- if the source has changed -- closes the old and
|
||||
* opens the correct new device node.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include "dmx_lib.h"
|
||||
#include "lt_debug.h"
|
||||
|
||||
#include "video_lib.h"
|
||||
/* needed for getSTC... */
|
||||
extern cVideo *videoDecoder;
|
||||
|
||||
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_DEMUX, this, args)
|
||||
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_DEMUX, this, args)
|
||||
#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_DEMUX, NULL, args)
|
||||
|
||||
#define dmx_err(_errfmt, _errstr, _revents) do { \
|
||||
uint16_t _pid = (uint16_t)-1; uint16_t _f = 0;\
|
||||
if (dmx_type == DMX_PSI_CHANNEL) { \
|
||||
_pid = s_flt.pid; _f = s_flt.filter.filter[0]; \
|
||||
} else { \
|
||||
_pid = p_flt.pid; \
|
||||
}; \
|
||||
lt_info("%s " _errfmt " fd:%d, ev:0x%x %s pid:0x%04hx flt:0x%02hx\n", \
|
||||
__func__, _errstr, fd, _revents, DMX_T[dmx_type], _pid, _f); \
|
||||
} while(0);
|
||||
|
||||
cDemux *videoDemux = NULL;
|
||||
cDemux *audioDemux = NULL;
|
||||
|
||||
static const char *DMX_T[] = {
|
||||
"DMX_INVALID",
|
||||
"DMX_VIDEO",
|
||||
"DMX_AUDIO",
|
||||
"DMX_PES",
|
||||
"DMX_PSI",
|
||||
"DMX_PIP",
|
||||
"DMX_TP",
|
||||
"DMX_PCR"
|
||||
};
|
||||
|
||||
/* this is the number of different cDemux() units, not the number of
|
||||
* /dev/dvb/.../demuxX devices! */
|
||||
#define NUM_DEMUX 4
|
||||
/* the current source of each cDemux unit */
|
||||
static int dmx_source[NUM_DEMUX] = { 0, 0, 0, 0 };
|
||||
|
||||
/* map the device numbers. */
|
||||
#define NUM_DEMUXDEV 8
|
||||
static const char *devname[NUM_DEMUXDEV] = {
|
||||
"/dev/dvb/adapter0/demux0",
|
||||
"/dev/dvb/adapter0/demux1",
|
||||
"/dev/dvb/adapter0/demux2",
|
||||
"/dev/dvb/adapter0/demux3",
|
||||
"/dev/dvb/adapter0/demux4",
|
||||
"/dev/dvb/adapter0/demux5",
|
||||
"/dev/dvb/adapter0/demux6",
|
||||
"/dev/dvb/adapter0/demux7"
|
||||
};
|
||||
/* did we already DMX_SET_SOURCE on that demux device? */
|
||||
static bool init[NUM_DEMUXDEV] = { false, false, false, false, false, false, false, false };
|
||||
|
||||
cDemux::cDemux(int n)
|
||||
{
|
||||
if (n < 0 || n >= NUM_DEMUX)
|
||||
{
|
||||
lt_info("%s ERROR: n invalid (%d)\n", __FUNCTION__, n);
|
||||
num = 0;
|
||||
}
|
||||
else
|
||||
num = n;
|
||||
fd = -1;
|
||||
measure = false;
|
||||
last_measure = 0;
|
||||
last_data = 0;
|
||||
last_source = -1;
|
||||
}
|
||||
|
||||
cDemux::~cDemux()
|
||||
{
|
||||
lt_debug("%s #%d fd: %d\n", __FUNCTION__, num, fd);
|
||||
Close();
|
||||
}
|
||||
|
||||
bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBufferSize)
|
||||
{
|
||||
if (fd > -1)
|
||||
lt_info("%s FD ALREADY OPENED? fd = %d\n", __FUNCTION__, fd);
|
||||
|
||||
dmx_type = pes_type;
|
||||
buffersize = uBufferSize;
|
||||
|
||||
/* return code is unchecked anyway... */
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cDemux::_open(void)
|
||||
{
|
||||
int flags = O_RDWR|O_CLOEXEC;
|
||||
int devnum = dmx_source[num];
|
||||
if (last_source == devnum) {
|
||||
lt_debug("%s #%d: source (%d) did not change\n", __func__, num, last_source);
|
||||
if (fd > -1)
|
||||
return true;
|
||||
}
|
||||
if (fd > -1) {
|
||||
/* we changed source -> close and reopen the fd */
|
||||
lt_debug("%s #%d: FD ALREADY OPENED fd = %d lastsource %d devnum %d\n",
|
||||
__func__, num, fd, last_source, devnum);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (dmx_type != DMX_PSI_CHANNEL)
|
||||
flags |= O_NONBLOCK;
|
||||
|
||||
fd = open(devname[devnum], flags);
|
||||
if (fd < 0)
|
||||
{
|
||||
lt_info("%s %s: %m\n", __FUNCTION__, devname[devnum]);
|
||||
return false;
|
||||
}
|
||||
lt_debug("%s #%d pes_type: %s(%d), uBufferSize: %d fd: %d\n", __func__,
|
||||
num, DMX_T[dmx_type], dmx_type, buffersize, fd);
|
||||
|
||||
/* this would actually need locking, but the worst that weill happen is, that
|
||||
* we'll DMX_SET_SOURCE twice per device, so don't bother... */
|
||||
if (!init[devnum])
|
||||
{
|
||||
/* this should not change anything... */
|
||||
int n = DMX_SOURCE_FRONT0 + devnum;
|
||||
lt_info("%s: setting %s to source %d\n", __func__, devname[devnum], n);
|
||||
if (ioctl(fd, DMX_SET_SOURCE, &n) < 0)
|
||||
lt_info("%s DMX_SET_SOURCE failed!\n", __func__);
|
||||
else
|
||||
init[devnum] = true;
|
||||
}
|
||||
if (buffersize == 0)
|
||||
buffersize = 0xffff; // may or may not be reasonable --martii
|
||||
if (buffersize > 0)
|
||||
{
|
||||
/* probably uBufferSize == 0 means "use default size". TODO: find a reasonable default */
|
||||
if (ioctl(fd, DMX_SET_BUFFER_SIZE, buffersize) < 0)
|
||||
lt_info("%s DMX_SET_BUFFER_SIZE failed (%m)\n", __func__);
|
||||
}
|
||||
|
||||
last_source = devnum;
|
||||
return true;
|
||||
}
|
||||
|
||||
void cDemux::Close(void)
|
||||
{
|
||||
lt_debug("%s #%d, fd = %d\n", __FUNCTION__, num, fd);
|
||||
if (fd < 0)
|
||||
{
|
||||
lt_info("%s #%d: not open!\n", __FUNCTION__, num);
|
||||
return;
|
||||
}
|
||||
|
||||
pesfds.clear();
|
||||
ioctl(fd, DMX_STOP);
|
||||
close(fd);
|
||||
fd = -1;
|
||||
if (measure)
|
||||
return;
|
||||
}
|
||||
|
||||
bool cDemux::Start(bool)
|
||||
{
|
||||
if (fd < 0)
|
||||
{
|
||||
lt_info("%s #%d: not open!\n", __FUNCTION__, num);
|
||||
return false;
|
||||
}
|
||||
ioctl(fd, DMX_START);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cDemux::Stop(void)
|
||||
{
|
||||
if (fd < 0)
|
||||
{
|
||||
lt_info("%s #%d: not open!\n", __FUNCTION__, num);
|
||||
return false;
|
||||
}
|
||||
ioctl(fd, DMX_STOP);
|
||||
return true;
|
||||
}
|
||||
|
||||
int cDemux::Read(unsigned char *buff, int len, int timeout)
|
||||
{
|
||||
#if 0
|
||||
if (len != 4095 && timeout != 10)
|
||||
fprintf(stderr, "cDemux::%s #%d fd: %d type: %s len: %d timeout: %d\n",
|
||||
__FUNCTION__, num, fd, DMX_T[dmx_type], len, timeout);
|
||||
#endif
|
||||
if (fd < 0)
|
||||
{
|
||||
lt_info("%s #%d: not open!\n", __func__, num);
|
||||
return -1;
|
||||
}
|
||||
int rc;
|
||||
int to = timeout;
|
||||
struct pollfd ufds;
|
||||
ufds.fd = fd;
|
||||
ufds.events = POLLIN|POLLPRI|POLLERR;
|
||||
ufds.revents = 0;
|
||||
|
||||
/* hack: if the frontend loses and regains lock, the demuxer often will not
|
||||
* return from read(), so as a "emergency exit" for e.g. NIT scan, set a (long)
|
||||
* timeout here */
|
||||
if (dmx_type == DMX_PSI_CHANNEL && timeout <= 0)
|
||||
to = 60 * 1000;
|
||||
|
||||
if (to > 0)
|
||||
{
|
||||
retry:
|
||||
rc = ::poll(&ufds, 1, to);
|
||||
if (!rc)
|
||||
{
|
||||
if (timeout == 0) /* we took the emergency exit */
|
||||
{
|
||||
dmx_err("timed out for timeout=0!, %s", "", 0);
|
||||
return -1; /* this timeout is an error */
|
||||
}
|
||||
return 0; // timeout
|
||||
}
|
||||
else if (rc < 0)
|
||||
{
|
||||
dmx_err("poll: %s,", strerror(errno), 0)
|
||||
//lt_info("%s poll: %m\n", __FUNCTION__);
|
||||
/* happens, when running under gdb... */
|
||||
if (errno == EINTR)
|
||||
goto retry;
|
||||
return -1;
|
||||
}
|
||||
#if 0
|
||||
if (ufds.revents & POLLERR) /* POLLERR means buffer error, i.e. buffer overflow */
|
||||
{
|
||||
dmx_err("received %s,", "POLLERR", ufds.revents);
|
||||
/* this seems to happen sometimes at recording start, without bad effects */
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (ufds.revents & POLLHUP) /* we get POLLHUP if e.g. a too big DMX_BUFFER_SIZE was set */
|
||||
{
|
||||
dmx_err("received %s,", "POLLHUP", ufds.revents);
|
||||
return -1;
|
||||
}
|
||||
if (!(ufds.revents & POLLIN)) /* we requested POLLIN but did not get it? */
|
||||
{
|
||||
dmx_err("received %s, please report!", "POLLIN", ufds.revents);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
rc = ::read(fd, buff, len);
|
||||
//fprintf(stderr, "fd %d ret: %d\n", fd, rc);
|
||||
if (rc < 0)
|
||||
dmx_err("read: %s", strerror(errno), 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool cDemux::sectionFilter(unsigned short pid, const unsigned char * const filter,
|
||||
const unsigned char * const mask, int len, int timeout,
|
||||
const unsigned char * const negmask)
|
||||
{
|
||||
memset(&s_flt, 0, sizeof(s_flt));
|
||||
|
||||
_open();
|
||||
|
||||
if (len > DMX_FILTER_SIZE)
|
||||
{
|
||||
lt_info("%s #%d: len too long: %d, DMX_FILTER_SIZE %d\n", __func__, num, len, DMX_FILTER_SIZE);
|
||||
len = DMX_FILTER_SIZE;
|
||||
}
|
||||
s_flt.pid = pid;
|
||||
s_flt.timeout = timeout;
|
||||
memcpy(s_flt.filter.filter, filter, len);
|
||||
memcpy(s_flt.filter.mask, mask, len);
|
||||
if (negmask != NULL)
|
||||
memcpy(s_flt.filter.mode, negmask, len);
|
||||
|
||||
s_flt.flags = DMX_IMMEDIATE_START|DMX_CHECK_CRC;
|
||||
|
||||
int to = 0;
|
||||
switch (filter[0]) {
|
||||
case 0x00: /* program_association_section */
|
||||
to = 2000;
|
||||
break;
|
||||
case 0x01: /* conditional_access_section */
|
||||
to = 6000;
|
||||
break;
|
||||
case 0x02: /* program_map_section */
|
||||
to = 1500;
|
||||
break;
|
||||
case 0x03: /* transport_stream_description_section */
|
||||
to = 10000;
|
||||
break;
|
||||
/* 0x04 - 0x3F: reserved */
|
||||
case 0x40: /* network_information_section - actual_network */
|
||||
to = 10000;
|
||||
break;
|
||||
case 0x41: /* network_information_section - other_network */
|
||||
to = 15000;
|
||||
break;
|
||||
case 0x42: /* service_description_section - actual_transport_stream */
|
||||
to = 10000;
|
||||
break;
|
||||
/* 0x43 - 0x45: reserved for future use */
|
||||
case 0x46: /* service_description_section - other_transport_stream */
|
||||
to = 10000;
|
||||
break;
|
||||
/* 0x47 - 0x49: reserved for future use */
|
||||
case 0x4A: /* bouquet_association_section */
|
||||
to = 11000;
|
||||
break;
|
||||
/* 0x4B - 0x4D: reserved for future use */
|
||||
case 0x4E: /* event_information_section - actual_transport_stream, present/following */
|
||||
to = 2000;
|
||||
break;
|
||||
case 0x4F: /* event_information_section - other_transport_stream, present/following */
|
||||
to = 10000;
|
||||
break;
|
||||
/* 0x50 - 0x5F: event_information_section - actual_transport_stream, schedule */
|
||||
/* 0x60 - 0x6F: event_information_section - other_transport_stream, schedule */
|
||||
case 0x70: /* time_date_section */
|
||||
s_flt.flags &= ~DMX_CHECK_CRC; /* section has no CRC */
|
||||
s_flt.flags |= DMX_ONESHOT;
|
||||
//s_flt.pid = 0x0014;
|
||||
to = 30000;
|
||||
break;
|
||||
case 0x71: /* running_status_section */
|
||||
s_flt.flags &= ~DMX_CHECK_CRC; /* section has no CRC */
|
||||
to = 0;
|
||||
break;
|
||||
case 0x72: /* stuffing_section */
|
||||
s_flt.flags &= ~DMX_CHECK_CRC; /* section has no CRC */
|
||||
to = 0;
|
||||
break;
|
||||
case 0x73: /* time_offset_section */
|
||||
s_flt.flags |= DMX_ONESHOT;
|
||||
//s_flt.pid = 0x0014;
|
||||
to = 30000;
|
||||
break;
|
||||
/* 0x74 - 0x7D: reserved for future use */
|
||||
case 0x7E: /* discontinuity_information_section */
|
||||
s_flt.flags &= ~DMX_CHECK_CRC; /* section has no CRC */
|
||||
to = 0;
|
||||
break;
|
||||
case 0x7F: /* selection_information_section */
|
||||
to = 0;
|
||||
break;
|
||||
/* 0x80 - 0x8F: ca_message_section */
|
||||
/* 0x90 - 0xFE: user defined */
|
||||
/* 0xFF: reserved */
|
||||
default:
|
||||
break;
|
||||
// return -1;
|
||||
}
|
||||
/* the negmask == NULL is a hack: the users of negmask are PMT-update
|
||||
* and sectionsd EIT-Version change. And they really want no timeout
|
||||
* if timeout == 0 instead of "default timeout" */
|
||||
if (timeout == 0 && negmask == NULL)
|
||||
s_flt.timeout = to;
|
||||
|
||||
lt_debug("%s #%d pid:0x%04hx fd:%d type:%s len:%d to:%d flags:%x flt[0]:%02x\n", __func__, num,
|
||||
pid, fd, DMX_T[dmx_type], len, s_flt.timeout,s_flt.flags, s_flt.filter.filter[0]);
|
||||
#if 0
|
||||
fprintf(stderr,"filt: ");for(int i=0;i<FILTER_LENGTH;i++)fprintf(stderr,"%02hhx ",s_flt.filter[i]);fprintf(stderr,"\n");
|
||||
fprintf(stderr,"mask: ");for(int i=0;i<FILTER_LENGTH;i++)fprintf(stderr,"%02hhx ",s_flt.mask [i]);fprintf(stderr,"\n");
|
||||
fprintf(stderr,"posi: ");for(int i=0;i<FILTER_LENGTH;i++)fprintf(stderr,"%02hhx ",s_flt.positive[i]);fprintf(stderr,"\n");
|
||||
#endif
|
||||
ioctl (fd, DMX_STOP);
|
||||
if (ioctl(fd, DMX_SET_FILTER, &s_flt) < 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cDemux::pesFilter(const unsigned short pid)
|
||||
{
|
||||
/* allow PID 0 for web streaming e.g.
|
||||
* this check originally is from tuxbox cvs but I'm not sure
|
||||
* what it is good for...
|
||||
if (pid <= 0x0001 && dmx_type != DMX_PCR_ONLY_CHANNEL)
|
||||
return false;
|
||||
*/
|
||||
if ((pid >= 0x0002 && pid <= 0x000f) || pid >= 0x1fff)
|
||||
return false;
|
||||
|
||||
lt_debug("%s #%d pid: 0x%04hx fd: %d type: %s\n", __FUNCTION__, num, pid, fd, DMX_T[dmx_type]);
|
||||
|
||||
_open();
|
||||
|
||||
memset(&p_flt, 0, sizeof(p_flt));
|
||||
p_flt.pid = pid;
|
||||
p_flt.output = DMX_OUT_DECODER;
|
||||
p_flt.input = DMX_IN_FRONTEND;
|
||||
p_flt.flags = 0;
|
||||
|
||||
switch (dmx_type) {
|
||||
case DMX_PCR_ONLY_CHANNEL:
|
||||
p_flt.pes_type = DMX_PES_PCR;
|
||||
break;
|
||||
case DMX_AUDIO_CHANNEL:
|
||||
p_flt.pes_type = DMX_PES_AUDIO;
|
||||
break;
|
||||
case DMX_VIDEO_CHANNEL:
|
||||
p_flt.pes_type = DMX_PES_VIDEO;
|
||||
break;
|
||||
case DMX_PIP_CHANNEL: /* PIP is a special version of DMX_VIDEO_CHANNEL */
|
||||
p_flt.pes_type = DMX_PES_VIDEO1;
|
||||
break;
|
||||
case DMX_PES_CHANNEL:
|
||||
p_flt.pes_type = DMX_PES_OTHER;
|
||||
p_flt.output = DMX_OUT_TAP;
|
||||
break;
|
||||
case DMX_TP_CHANNEL:
|
||||
p_flt.pes_type = DMX_PES_OTHER;
|
||||
p_flt.output = DMX_OUT_TSDEMUX_TAP;
|
||||
break;
|
||||
default:
|
||||
lt_info("%s #%d invalid dmx_type %d!\n", __func__, num, dmx_type);
|
||||
return false;
|
||||
}
|
||||
return (ioctl(fd, DMX_SET_PES_FILTER, &p_flt) >= 0);
|
||||
}
|
||||
|
||||
void cDemux::SetSyncMode(AVSYNC_TYPE /*mode*/)
|
||||
{
|
||||
lt_debug("%s #%d\n", __FUNCTION__, num);
|
||||
}
|
||||
|
||||
void *cDemux::getBuffer()
|
||||
{
|
||||
lt_debug("%s #%d\n", __FUNCTION__, num);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *cDemux::getChannel()
|
||||
{
|
||||
lt_debug("%s #%d\n", __FUNCTION__, num);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool cDemux::addPid(unsigned short Pid)
|
||||
{
|
||||
lt_debug("%s: pid 0x%04hx\n", __func__, Pid);
|
||||
pes_pids pfd;
|
||||
int ret;
|
||||
if (dmx_type != DMX_TP_CHANNEL)
|
||||
{
|
||||
lt_info("%s pes_type %s not implemented yet! pid=%hx\n", __FUNCTION__, DMX_T[dmx_type], Pid);
|
||||
return false;
|
||||
}
|
||||
_open();
|
||||
if (fd == -1)
|
||||
lt_info("%s bucketfd not yet opened? pid=%hx\n", __FUNCTION__, Pid);
|
||||
pfd.fd = fd; /* dummy */
|
||||
pfd.pid = Pid;
|
||||
pesfds.push_back(pfd);
|
||||
ret = (ioctl(fd, DMX_ADD_PID, &Pid));
|
||||
if (ret < 0)
|
||||
lt_info("%s: DMX_ADD_PID (%m) pid=%hx\n", __func__, Pid);
|
||||
return (ret != -1);
|
||||
}
|
||||
|
||||
void cDemux::removePid(unsigned short Pid)
|
||||
{
|
||||
if (dmx_type != DMX_TP_CHANNEL)
|
||||
{
|
||||
lt_info("%s pes_type %s not implemented yet! pid=%hx\n", __FUNCTION__, DMX_T[dmx_type], Pid);
|
||||
return;
|
||||
}
|
||||
for (std::vector<pes_pids>::iterator i = pesfds.begin(); i != pesfds.end(); ++i)
|
||||
{
|
||||
if ((*i).pid == Pid) {
|
||||
lt_debug("removePid: removing demux fd %d pid 0x%04x\n", fd, Pid);
|
||||
if (ioctl(fd, DMX_REMOVE_PID, Pid) < 0)
|
||||
lt_info("%s: (DMX_REMOVE_PID, 0x%04hx): %m\n", __func__, Pid);
|
||||
pesfds.erase(i);
|
||||
return; /* TODO: what if the same PID is there multiple times */
|
||||
}
|
||||
}
|
||||
lt_info("%s pid 0x%04x not found\n", __FUNCTION__, Pid);
|
||||
}
|
||||
|
||||
void cDemux::getSTC(int64_t * STC)
|
||||
{
|
||||
/* apparently I can only get the PTS of the video decoder,
|
||||
* but that's good enough for dvbsub */
|
||||
lt_debug("%s #%d\n", __func__, num);
|
||||
int64_t pts = 0;
|
||||
if (videoDecoder)
|
||||
pts = videoDecoder->GetPTS();
|
||||
*STC = pts;
|
||||
}
|
||||
|
||||
int cDemux::getUnit(void)
|
||||
{
|
||||
lt_debug("%s #%d\n", __FUNCTION__, num);
|
||||
/* just guessed that this is the right thing to do.
|
||||
right now this is only used by the CA code which is stubbed out
|
||||
anyway */
|
||||
return num;
|
||||
}
|
||||
|
||||
bool cDemux::SetSource(int unit, int source)
|
||||
{
|
||||
if (unit >= NUM_DEMUX || unit < 0) {
|
||||
lt_info_c("%s: unit (%d) out of range, NUM_DEMUX %d\n", __func__, unit, NUM_DEMUX);
|
||||
return false;
|
||||
}
|
||||
lt_info_c("%s(%d, %d) => %d to %d\n", __func__, unit, source, dmx_source[unit], source);
|
||||
if (source < 0 || source >= NUM_DEMUXDEV)
|
||||
lt_info_c("%s(%d, %d) ERROR: source %d out of range!\n", __func__, unit, source, source);
|
||||
else
|
||||
dmx_source[unit] = source;
|
||||
return true;
|
||||
}
|
||||
|
||||
int cDemux::GetSource(int unit)
|
||||
{
|
||||
if (unit >= NUM_DEMUX || unit < 0) {
|
||||
lt_info_c("%s: unit (%d) out of range, NUM_DEMUX %d\n", __func__, unit, NUM_DEMUX);
|
||||
return -1;
|
||||
}
|
||||
lt_info_c("%s(%d) => %d\n", __func__, unit, dmx_source[unit]);
|
||||
return dmx_source[unit];
|
||||
}
|
@@ -1 +0,0 @@
|
||||
#include "dmx_lib.h"
|
@@ -1,72 +0,0 @@
|
||||
#ifndef __DEMUX_TD_H
|
||||
#define __DEMUX_TD_H
|
||||
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
#include <inttypes.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/dvb/dmx.h>
|
||||
#include "../common/cs_types.h"
|
||||
|
||||
#define MAX_DMX_UNITS 4
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DMX_INVALID = 0,
|
||||
DMX_VIDEO_CHANNEL = 1,
|
||||
DMX_AUDIO_CHANNEL,
|
||||
DMX_PES_CHANNEL,
|
||||
DMX_PSI_CHANNEL,
|
||||
DMX_PIP_CHANNEL,
|
||||
DMX_TP_CHANNEL,
|
||||
DMX_PCR_ONLY_CHANNEL
|
||||
} DMX_CHANNEL_TYPE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int fd;
|
||||
unsigned short pid;
|
||||
} pes_pids;
|
||||
|
||||
class cDemux
|
||||
{
|
||||
private:
|
||||
int num;
|
||||
int fd;
|
||||
int buffersize;
|
||||
bool measure;
|
||||
uint64_t last_measure, last_data;
|
||||
DMX_CHANNEL_TYPE dmx_type;
|
||||
std::vector<pes_pids> pesfds;
|
||||
struct dmx_sct_filter_params s_flt;
|
||||
struct dmx_pes_filter_params p_flt;
|
||||
int last_source;
|
||||
bool _open(void);
|
||||
public:
|
||||
|
||||
bool Open(DMX_CHANNEL_TYPE pes_type, void * unused = NULL, int bufsize = 0);
|
||||
void Close(void);
|
||||
bool Start(bool record = false);
|
||||
bool Stop(void);
|
||||
int Read(unsigned char *buff, int len, int Timeout = 0);
|
||||
bool sectionFilter(unsigned short pid, const unsigned char * const filter, const unsigned char * const mask, int len, int Timeout = 0, const unsigned char * const negmask = NULL);
|
||||
bool pesFilter(const unsigned short pid);
|
||||
void SetSyncMode(AVSYNC_TYPE mode);
|
||||
void * getBuffer();
|
||||
void * getChannel();
|
||||
DMX_CHANNEL_TYPE getChannelType(void) { return dmx_type; };
|
||||
bool addPid(unsigned short pid);
|
||||
void getSTC(int64_t * STC);
|
||||
int getUnit(void);
|
||||
static bool SetSource(int unit, int source);
|
||||
static int GetSource(int unit);
|
||||
// TD only functions
|
||||
int getFD(void) { return fd; }; /* needed by cPlayback class */
|
||||
void removePid(unsigned short Pid); /* needed by cRecord class */
|
||||
std::vector<pes_pids> getPesPids(void) { return pesfds; };
|
||||
//
|
||||
cDemux(int num = 0);
|
||||
~cDemux();
|
||||
};
|
||||
|
||||
#endif //__DEMUX_H
|
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* determine the capabilities of the hardware.
|
||||
* part of libstb-hal
|
||||
*
|
||||
* (C) 2010-2012 Stefan Seyfried
|
||||
*
|
||||
* License: GPL v2 or later
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <hardware_caps.h>
|
||||
|
||||
#define FP_DEV "/dev/dbox/oled0"
|
||||
static int initialized = 0;
|
||||
static hw_caps_t caps;
|
||||
|
||||
hw_caps_t *get_hwcaps(void)
|
||||
{
|
||||
if (initialized)
|
||||
return ∩︀
|
||||
|
||||
memset(&caps, 0, sizeof(hw_caps_t));
|
||||
|
||||
initialized = 1;
|
||||
caps.has_CI = 1;
|
||||
caps.can_cec = 1;
|
||||
caps.can_shutdown = 1;
|
||||
caps.display_xres = 16;
|
||||
caps.display_type = HW_DISPLAY_LINE_TEXT;
|
||||
caps.display_can_set_brightness = 1;
|
||||
caps.has_HDMI = 1;
|
||||
strcpy(caps.boxvendor, "AX-Technologies");
|
||||
strcpy(caps.boxname, "HD51");
|
||||
strcpy(caps.boxarch, "BCM7251S");
|
||||
return ∩︀
|
||||
}
|
@@ -1,49 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "init_lib.h"
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "pwrmngr.h"
|
||||
#include <proc_tools.h>
|
||||
|
||||
#include "lt_debug.h"
|
||||
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_INIT, NULL, args)
|
||||
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_INIT, NULL, args)
|
||||
|
||||
static bool initialized = false;
|
||||
|
||||
void init_td_api()
|
||||
{
|
||||
if (!initialized)
|
||||
lt_debug_init();
|
||||
lt_info("%s begin, initialized=%d, debug=0x%02x\n", __FUNCTION__, (int)initialized, debuglevel);
|
||||
if (!initialized)
|
||||
{
|
||||
cCpuFreqManager f;
|
||||
f.SetCpuFreq(0); /* CPUFREQ == 0 is the trigger for leaving standby */
|
||||
char buffer[64];
|
||||
sprintf(buffer, "%x", 0);
|
||||
proc_put("/proc/stb/fb/dst_top", buffer, strlen(buffer));
|
||||
proc_put("/proc/stb/fb/dst_left", buffer, strlen(buffer));
|
||||
sprintf(buffer, "%x", 576);
|
||||
proc_put("/proc/stb/fb/dst_height", buffer, strlen(buffer));
|
||||
sprintf(buffer, "%x", 720);
|
||||
proc_put("/proc/stb/fb/dst_width", buffer, strlen(buffer));
|
||||
sprintf(buffer, "%x", 1);
|
||||
proc_put("/proc/stb/fb/dst_apply", buffer, strlen(buffer));
|
||||
}
|
||||
initialized = true;
|
||||
lt_info("%s end\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void shutdown_td_api()
|
||||
{
|
||||
lt_info("%s, initialized = %d\n", __FUNCTION__, (int)initialized);
|
||||
initialized = false;
|
||||
}
|
@@ -1,2 +0,0 @@
|
||||
#warning using init_cs.h from libspark
|
||||
#include "init_lib.h"
|
@@ -1,5 +0,0 @@
|
||||
#ifndef __INIT_TD_H
|
||||
#define __INIT_TD_H
|
||||
void init_td_api();
|
||||
void shutdown_td_api();
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PLAYBACK_CS_H
|
||||
#define __PLAYBACK_CS_H
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STATE_STOP,
|
||||
STATE_PLAY,
|
||||
STATE_PAUSE,
|
||||
STATE_FF,
|
||||
STATE_REW,
|
||||
STATE_SLOW
|
||||
} playstate_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PLAYMODE_TS = 0,
|
||||
PLAYMODE_FILE,
|
||||
} playmode_t;
|
||||
|
||||
struct AVFormatContext;
|
||||
|
||||
class cPlayback
|
||||
{
|
||||
private:
|
||||
bool playing, first;
|
||||
bool decoders_closed;
|
||||
|
||||
int mSpeed;
|
||||
int mAudioStream;
|
||||
int init_jump;
|
||||
|
||||
public:
|
||||
playstate_t playstate;
|
||||
|
||||
cPlayback(int);
|
||||
bool Open(playmode_t PlayMode);
|
||||
void Close(void);
|
||||
bool Start(char *filename, int vpid, int vtype, int apid, int ac3, int duration, std::string headers = "");
|
||||
bool Start(std::string filename, std::string headers = "");
|
||||
bool Play(void);
|
||||
bool SyncAV(void);
|
||||
|
||||
bool Stop(void);
|
||||
bool SetAPid(int pid, bool ac3);
|
||||
bool SetSubtitlePid(int pid);
|
||||
bool SetTeletextPid(int pid);
|
||||
|
||||
void trickSeek(int ratio);
|
||||
bool SetSpeed(int speed);
|
||||
bool SetSlow(int slow);
|
||||
bool GetSpeed(int &speed) const;
|
||||
bool GetPosition(int &position, int &duration);
|
||||
void GetPts(uint64_t &pts);
|
||||
int GetAPid(void);
|
||||
int GetVPid(void);
|
||||
int GetSubtitlePid(void);
|
||||
bool SetPosition(int position, bool absolute = false);
|
||||
void FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *numpida, std::string *language);
|
||||
void FindAllSubtitlePids(int *pids, unsigned int *numpids, std::string *language);
|
||||
void FindAllTeletextsubtitlePids(int *pids, unsigned int *numpidt, std::string *tlanguage, int *mags, int *pages);
|
||||
void RequestAbort(void);
|
||||
void FindAllSubs(uint16_t *pids, unsigned short *supported, uint16_t *numpida, std::string *language);
|
||||
bool SelectSubtitles(int pid);
|
||||
uint64_t GetReadCount(void);
|
||||
void GetChapters(std::vector<int> &positions, std::vector<std::string> &titles);
|
||||
void GetMetadata(std::vector<std::string> &keys, std::vector<std::string> &values);
|
||||
AVFormatContext *GetAVFormatContext();
|
||||
void ReleaseAVFormatContext();
|
||||
std::string extra_headers;
|
||||
std::string user_agent;
|
||||
|
||||
//
|
||||
~cPlayback();
|
||||
void getMeta();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -1,102 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "pwrmngr.h"
|
||||
#include "lt_debug.h"
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_PWRMNGR, this, args)
|
||||
void cCpuFreqManager::Up(void) { lt_debug("%s\n", __FUNCTION__); }
|
||||
void cCpuFreqManager::Down(void) { lt_debug("%s\n", __FUNCTION__); }
|
||||
void cCpuFreqManager::Reset(void) { lt_debug("%s\n", __FUNCTION__); }
|
||||
/* those function dummies return true or "harmless" values */
|
||||
bool cCpuFreqManager::SetDelta(unsigned long) { lt_debug("%s\n", __FUNCTION__); return true; }
|
||||
#if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE
|
||||
unsigned long cCpuFreqManager::GetCpuFreq(void) {
|
||||
int freq = 0;
|
||||
if (FILE *pll0 = fopen("/proc/cpu_frequ/pll0_ndiv_mdiv", "r")) {
|
||||
char buffer[120];
|
||||
while(fgets(buffer, sizeof(buffer), pll0)) {
|
||||
if (1 == sscanf(buffer, "SH4 = %d MHZ", &freq))
|
||||
break;
|
||||
}
|
||||
fclose(pll0);
|
||||
return 1000 * 1000 * (unsigned long) freq;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
unsigned long cCpuFreqManager::GetCpuFreq(void) { lt_debug("%s\n", __FUNCTION__); return 0; }
|
||||
#endif
|
||||
unsigned long cCpuFreqManager::GetDelta(void) { lt_debug("%s\n", __FUNCTION__); return 0; }
|
||||
//
|
||||
cCpuFreqManager::cCpuFreqManager(void) { lt_debug("%s\n", __FUNCTION__); }
|
||||
|
||||
bool cPowerManager::SetState(PWR_STATE) { lt_debug("%s\n", __FUNCTION__); return true; }
|
||||
|
||||
bool cPowerManager::Open(void) { lt_debug("%s\n", __FUNCTION__); return true; }
|
||||
void cPowerManager::Close(void) { lt_debug("%s\n", __FUNCTION__); }
|
||||
//
|
||||
bool cPowerManager::SetStandby(bool Active, bool Passive)
|
||||
{
|
||||
lt_debug("%s(%d, %d)\n", __FUNCTION__, Active, Passive);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cCpuFreqManager::SetCpuFreq(unsigned long f)
|
||||
{
|
||||
#if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE
|
||||
if (f) {
|
||||
FILE *pll0 = fopen ("/proc/cpu_frequ/pll0_ndiv_mdiv", "w");
|
||||
if (pll0) {
|
||||
f /= 1000000;
|
||||
fprintf(pll0, "%lu\n", (f/10 << 8) | 3);
|
||||
fclose (pll0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* actually SetCpuFreq is used to determine if the system is in standby
|
||||
this is an "elegant" hack, because:
|
||||
* during a recording, cpu freq is kept "high", even if the box is sent to standby
|
||||
* the "SetStandby" call is made even if a recording is running
|
||||
On the TD, setting standby disables the frontend, so we must not do it
|
||||
if a recording is running.
|
||||
For now, the values in neutrino are hardcoded:
|
||||
* f == 0 => max => not standby
|
||||
* f == 50000000 => min => standby
|
||||
*/
|
||||
lt_debug("%s(%lu) => set standby = %s\n", __FUNCTION__, f, f?"true":"false");
|
||||
#if 0
|
||||
int fd = open("/dev/stb/tdsystem", O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
perror("open tdsystem");
|
||||
return false;
|
||||
}
|
||||
if (f)
|
||||
{
|
||||
ioctl(fd, IOC_AVS_SET_VOLUME, 31); /* mute AVS to avoid ugly noise */
|
||||
ioctl(fd, IOC_AVS_STANDBY_ENTER);
|
||||
}
|
||||
else
|
||||
{
|
||||
ioctl(fd, IOC_AVS_SET_VOLUME, 31); /* mute AVS to avoid ugly noise */
|
||||
ioctl(fd, IOC_AVS_STANDBY_LEAVE);
|
||||
/* unmute will be done by cAudio::do_mute(). Ugly, but prevents pops */
|
||||
// ioctl(fd, IOC_AVS_SET_VOLUME, 0); /* max gain */
|
||||
}
|
||||
|
||||
close(fd);
|
||||
#endif
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
cPowerManager::cPowerManager(void) { lt_debug("%s\n", __FUNCTION__); }
|
||||
cPowerManager::~cPowerManager() { lt_debug("%s\n", __FUNCTION__); }
|
||||
|
@@ -1,53 +0,0 @@
|
||||
#ifndef __PWRMNGR_H__
|
||||
#define __PWRMNGR_H__
|
||||
|
||||
// -- cCpuFreqManager ----------------------------------------------------------
|
||||
|
||||
class cCpuFreqManager {
|
||||
private:
|
||||
unsigned long startCpuFreq;
|
||||
unsigned long delta;
|
||||
public:
|
||||
void Up(void);
|
||||
void Down(void);
|
||||
void Reset(void);
|
||||
//
|
||||
bool SetCpuFreq(unsigned long CpuFreq);
|
||||
bool SetDelta(unsigned long Delta);
|
||||
unsigned long GetCpuFreq(void);
|
||||
unsigned long GetDelta(void);
|
||||
//
|
||||
cCpuFreqManager(void);
|
||||
|
||||
};
|
||||
|
||||
// -- cPowerManageger ----------------------------------------------------------
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PWR_INIT = 1,
|
||||
PWR_FULL_ACTIVE, /* all devices/clocks up */
|
||||
PWR_ACTIVE_STANDBY,
|
||||
PWR_PASSIVE_STANDBY,
|
||||
PWR_INVALID
|
||||
} PWR_STATE;
|
||||
|
||||
class cPowerManager {
|
||||
private:
|
||||
bool init;
|
||||
bool opened;
|
||||
PWR_STATE powerState;
|
||||
//
|
||||
static void ApplicationCallback(void *, void *, signed long, void *, void *) {}
|
||||
bool SetState(PWR_STATE PowerState);
|
||||
public:
|
||||
bool Open(void);
|
||||
void Close(void);
|
||||
//
|
||||
bool SetStandby(bool Active, bool Passive);
|
||||
//
|
||||
cPowerManager(void);
|
||||
virtual ~cPowerManager();
|
||||
};
|
||||
|
||||
#endif // __PWRMNGR_H__
|
@@ -1,383 +0,0 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <malloc.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <inttypes.h>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include <aio.h>
|
||||
|
||||
#include "record_lib.h"
|
||||
#include "lt_debug.h"
|
||||
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_RECORD, this, args)
|
||||
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_RECORD, this, args)
|
||||
|
||||
/* helper functions to call the cpp thread loops */
|
||||
void *execute_record_thread(void *c)
|
||||
{
|
||||
cRecord *obj = (cRecord *)c;
|
||||
obj->RecordThread();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *execute_writer_thread(void *c)
|
||||
{
|
||||
cRecord *obj = (cRecord *)c;
|
||||
obj->WriterThread();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cRecord::cRecord(int num, int bs_dmx, int bs)
|
||||
{
|
||||
lt_info("%s %d\n", __func__, num);
|
||||
dmx = NULL;
|
||||
record_thread_running = false;
|
||||
file_fd = -1;
|
||||
exit_flag = RECORD_STOPPED;
|
||||
dmx_num = num;
|
||||
bufsize = bs;
|
||||
bufsize_dmx = bs_dmx;
|
||||
failureCallback = NULL;
|
||||
failureData = NULL;
|
||||
}
|
||||
|
||||
cRecord::~cRecord()
|
||||
{
|
||||
lt_info("%s: calling ::Stop()\n", __func__);
|
||||
Stop();
|
||||
lt_info("%s: end\n", __func__);
|
||||
}
|
||||
|
||||
bool cRecord::Open(void)
|
||||
{
|
||||
lt_info("%s\n", __func__);
|
||||
exit_flag = RECORD_STOPPED;
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// unused
|
||||
void cRecord::Close(void)
|
||||
{
|
||||
lt_info("%s: \n", __func__);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool cRecord::Start(int fd, unsigned short vpid, unsigned short *apids, int numpids, uint64_t)
|
||||
{
|
||||
lt_info("%s: fd %d, vpid 0x%03x\n", __func__, fd, vpid);
|
||||
int i;
|
||||
|
||||
if (!dmx)
|
||||
dmx = new cDemux(dmx_num);
|
||||
|
||||
dmx->Open(DMX_TP_CHANNEL, NULL, bufsize_dmx);
|
||||
dmx->pesFilter(vpid);
|
||||
|
||||
for (i = 0; i < numpids; i++)
|
||||
dmx->addPid(apids[i]);
|
||||
|
||||
file_fd = fd;
|
||||
exit_flag = RECORD_RUNNING;
|
||||
if (posix_fadvise(file_fd, 0, 0, POSIX_FADV_DONTNEED))
|
||||
perror("posix_fadvise");
|
||||
|
||||
i = pthread_create(&record_thread, 0, execute_record_thread, this);
|
||||
if (i != 0)
|
||||
{
|
||||
exit_flag = RECORD_FAILED_READ;
|
||||
errno = i;
|
||||
lt_info("%s: error creating thread! (%m)\n", __func__);
|
||||
delete dmx;
|
||||
dmx = NULL;
|
||||
return false;
|
||||
}
|
||||
record_thread_running = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cRecord::Stop(void)
|
||||
{
|
||||
lt_info("%s\n", __func__);
|
||||
|
||||
if (exit_flag != RECORD_RUNNING)
|
||||
lt_info("%s: status not RUNNING? (%d)\n", __func__, exit_flag);
|
||||
|
||||
exit_flag = RECORD_STOPPED;
|
||||
if (record_thread_running)
|
||||
pthread_join(record_thread, NULL);
|
||||
record_thread_running = false;
|
||||
|
||||
/* We should probably do that from the destructor... */
|
||||
if (!dmx)
|
||||
lt_info("%s: dmx == NULL?\n", __func__);
|
||||
else
|
||||
delete dmx;
|
||||
dmx = NULL;
|
||||
|
||||
if (file_fd != -1)
|
||||
close(file_fd);
|
||||
else
|
||||
lt_info("%s: file_fd not open??\n", __func__);
|
||||
file_fd = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cRecord::ChangePids(unsigned short /*vpid*/, unsigned short *apids, int numapids)
|
||||
{
|
||||
std::vector<pes_pids> pids;
|
||||
int j;
|
||||
bool found;
|
||||
unsigned short pid;
|
||||
lt_info("%s\n", __func__);
|
||||
if (!dmx) {
|
||||
lt_info("%s: DMX = NULL\n", __func__);
|
||||
return false;
|
||||
}
|
||||
pids = dmx->getPesPids();
|
||||
/* the first PID is the video pid, so start with the second PID... */
|
||||
for (std::vector<pes_pids>::const_iterator i = pids.begin() + 1; i != pids.end(); ++i) {
|
||||
found = false;
|
||||
pid = (*i).pid;
|
||||
for (j = 0; j < numapids; j++) {
|
||||
if (pid == apids[j]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
dmx->removePid(pid);
|
||||
}
|
||||
for (j = 0; j < numapids; j++) {
|
||||
found = false;
|
||||
for (std::vector<pes_pids>::const_iterator i = pids.begin() + 1; i != pids.end(); ++i) {
|
||||
if ((*i).pid == apids[j]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
dmx->addPid(apids[j]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cRecord::AddPid(unsigned short pid)
|
||||
{
|
||||
std::vector<pes_pids> pids;
|
||||
lt_info("%s: \n", __func__);
|
||||
if (!dmx) {
|
||||
lt_info("%s: DMX = NULL\n", __func__);
|
||||
return false;
|
||||
}
|
||||
pids = dmx->getPesPids();
|
||||
for (std::vector<pes_pids>::const_iterator i = pids.begin(); i != pids.end(); ++i) {
|
||||
if ((*i).pid == pid)
|
||||
return true; /* or is it an error to try to add the same PID twice? */
|
||||
}
|
||||
return dmx->addPid(pid);
|
||||
}
|
||||
|
||||
void cRecord::WriterThread()
|
||||
{
|
||||
char threadname[17];
|
||||
strncpy(threadname, "WriterThread", sizeof(threadname));
|
||||
threadname[16] = 0;
|
||||
prctl (PR_SET_NAME, (unsigned long)&threadname);
|
||||
unsigned int chunk = 0;
|
||||
while (!sem_wait(&sem)) {
|
||||
if (!io_len[chunk]) // empty, assume end of recording
|
||||
return;
|
||||
unsigned char *p_buf = io_buf[chunk];
|
||||
size_t p_len = io_len[chunk];
|
||||
while (p_len) {
|
||||
ssize_t written = write(file_fd, p_buf, p_len);
|
||||
if (written < 0)
|
||||
break;
|
||||
p_len -= written;
|
||||
p_buf += written;
|
||||
}
|
||||
if (posix_fadvise(file_fd, 0, 0, POSIX_FADV_DONTNEED))
|
||||
perror("posix_fadvise");
|
||||
chunk++;
|
||||
chunk %= RECORD_WRITER_CHUNKS;
|
||||
}
|
||||
}
|
||||
|
||||
void cRecord::RecordThread()
|
||||
{
|
||||
lt_info("%s: begin\n", __func__);
|
||||
char threadname[17];
|
||||
strncpy(threadname, "RecordThread", sizeof(threadname));
|
||||
threadname[16] = 0;
|
||||
prctl (PR_SET_NAME, (unsigned long)&threadname);
|
||||
int readsize = bufsize/16;
|
||||
int buf_pos = 0;
|
||||
int count = 0;
|
||||
int queued = 0;
|
||||
uint8_t *buf;
|
||||
struct aiocb a;
|
||||
|
||||
buf = (uint8_t *)malloc(bufsize);
|
||||
lt_info("BUFSIZE=0x%x READSIZE=0x%x\n", bufsize, readsize);
|
||||
if (!buf)
|
||||
{
|
||||
exit_flag = RECORD_FAILED_MEMORY;
|
||||
lt_info("%s: unable to allocate buffer! (out of memory)\n", __func__);
|
||||
if (failureCallback)
|
||||
failureCallback(failureData);
|
||||
lt_info("%s: end\n", __func__);
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
int val = fcntl(file_fd, F_GETFL);
|
||||
if (fcntl(file_fd, F_SETFL, val|O_APPEND))
|
||||
lt_info("%s: O_APPEND? (%m)\n", __func__);
|
||||
|
||||
memset(&a, 0, sizeof(a));
|
||||
a.aio_fildes = file_fd;
|
||||
a.aio_sigevent.sigev_notify = SIGEV_NONE;
|
||||
|
||||
dmx->Start();
|
||||
int overflow_count = 0;
|
||||
bool overflow = false;
|
||||
int r = 0;
|
||||
while (exit_flag == RECORD_RUNNING)
|
||||
{
|
||||
if (buf_pos < bufsize)
|
||||
{
|
||||
if (overflow_count) {
|
||||
lt_info("%s: Overflow cleared after %d iterations\n", __func__, overflow_count);
|
||||
overflow_count = 0;
|
||||
}
|
||||
int toread = bufsize - buf_pos;
|
||||
if (toread > readsize)
|
||||
toread = readsize;
|
||||
ssize_t s = dmx->Read(buf + buf_pos, toread, 50);
|
||||
lt_debug("%s: buf_pos %6d s %6d / %6d\n", __func__, buf_pos, (int)s, bufsize - buf_pos);
|
||||
if (s < 0)
|
||||
{
|
||||
if (errno != EAGAIN && (errno != EOVERFLOW || !overflow))
|
||||
{
|
||||
lt_info("%s: read failed: %m\n", __func__);
|
||||
exit_flag = RECORD_FAILED_READ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
overflow = false;
|
||||
buf_pos += s;
|
||||
if (count > 100)
|
||||
{
|
||||
if (buf_pos < bufsize / 2)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!overflow)
|
||||
overflow_count = 0;
|
||||
overflow = true;
|
||||
if (!(overflow_count % 10))
|
||||
lt_info("%s: buffer full! Overflow? (%d)\n", __func__, ++overflow_count);
|
||||
}
|
||||
r = aio_error(&a);
|
||||
if (r == EINPROGRESS)
|
||||
{
|
||||
lt_debug("%s: aio in progress, free: %d\n", __func__, bufsize - buf_pos);
|
||||
continue;
|
||||
}
|
||||
// not calling aio_return causes a memory leak --martii
|
||||
r = aio_return(&a);
|
||||
if (r < 0)
|
||||
{
|
||||
exit_flag = RECORD_FAILED_FILE;
|
||||
lt_debug("%s: aio_return = %d (%m)\n", __func__, r);
|
||||
break;
|
||||
}
|
||||
else
|
||||
lt_debug("%s: aio_return = %d, free: %d\n", __func__, r, bufsize - buf_pos);
|
||||
if (posix_fadvise(file_fd, 0, 0, POSIX_FADV_DONTNEED))
|
||||
perror("posix_fadvise");
|
||||
if (queued)
|
||||
{
|
||||
memmove(buf, buf + queued, buf_pos - queued);
|
||||
buf_pos -= queued;
|
||||
}
|
||||
queued = buf_pos;
|
||||
a.aio_buf = buf;
|
||||
a.aio_nbytes = queued;
|
||||
r = aio_write(&a);
|
||||
if (r)
|
||||
{
|
||||
lt_info("%s: aio_write %d (%m)\n", __func__, r);
|
||||
exit_flag = RECORD_FAILED_FILE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dmx->Stop();
|
||||
while (true) /* write out the unwritten buffer content */
|
||||
{
|
||||
lt_debug("%s: run-out write, buf_pos %d\n", __func__, buf_pos);
|
||||
r = aio_error(&a);
|
||||
if (r == EINPROGRESS)
|
||||
{
|
||||
usleep(50000);
|
||||
continue;
|
||||
}
|
||||
r = aio_return(&a);
|
||||
if (r < 0)
|
||||
{
|
||||
exit_flag = RECORD_FAILED_FILE;
|
||||
lt_info("%s: aio_result: %d (%m)\n", __func__, r);
|
||||
break;
|
||||
}
|
||||
if (!queued)
|
||||
break;
|
||||
memmove(buf, buf + queued, buf_pos - queued);
|
||||
buf_pos -= queued;
|
||||
queued = buf_pos;
|
||||
a.aio_buf = buf;
|
||||
a.aio_nbytes = queued;
|
||||
r = aio_write(&a);
|
||||
}
|
||||
free(buf);
|
||||
|
||||
#if 0
|
||||
// TODO: do we need to notify neutrino about failing recording?
|
||||
CEventServer eventServer;
|
||||
eventServer.registerEvent2(NeutrinoMessages::EVT_RECORDING_ENDED, CEventServer::INITID_NEUTRINO, "/tmp/neutrino.sock");
|
||||
stream2file_status2_t s;
|
||||
s.status = exit_flag;
|
||||
strncpy(s.filename,basename(myfilename),512);
|
||||
s.filename[511] = '\0';
|
||||
strncpy(s.dir,dirname(myfilename),100);
|
||||
s.dir[99] = '\0';
|
||||
eventServer.sendEvent(NeutrinoMessages::EVT_RECORDING_ENDED, CEventServer::INITID_NEUTRINO, &s, sizeof(s));
|
||||
printf("[stream2file]: pthreads exit code: %i, dir: '%s', filename: '%s' myfilename: '%s'\n", exit_flag, s.dir, s.filename, myfilename);
|
||||
#endif
|
||||
|
||||
if ((exit_flag != RECORD_STOPPED) && failureCallback)
|
||||
failureCallback(failureData);
|
||||
lt_info("%s: end\n", __func__);
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
int cRecord::GetStatus()
|
||||
{
|
||||
return (exit_flag == RECORD_STOPPED) ? REC_STATUS_STOPPED : REC_STATUS_OK;
|
||||
}
|
||||
|
||||
void cRecord::ResetStatus()
|
||||
{
|
||||
return;
|
||||
}
|
@@ -1,57 +0,0 @@
|
||||
#ifndef __RECORD_TD_H
|
||||
#define __RECORD_TD_H
|
||||
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include "dmx_lib.h"
|
||||
|
||||
#define REC_STATUS_OK 0
|
||||
#define REC_STATUS_SLOW 1
|
||||
#define REC_STATUS_OVERFLOW 2
|
||||
#define REC_STATUS_STOPPED 4
|
||||
|
||||
typedef enum {
|
||||
RECORD_RUNNING,
|
||||
RECORD_STOPPED,
|
||||
RECORD_FAILED_READ, /* failed to read from DMX */
|
||||
RECORD_FAILED_OVERFLOW, /* cannot write fast enough */
|
||||
RECORD_FAILED_FILE, /* cannot write to file */
|
||||
RECORD_FAILED_MEMORY /* out of memory */
|
||||
} record_state_t;
|
||||
|
||||
class cRecord
|
||||
{
|
||||
private:
|
||||
int file_fd;
|
||||
int dmx_num;
|
||||
cDemux *dmx;
|
||||
pthread_t record_thread;
|
||||
bool record_thread_running;
|
||||
record_state_t exit_flag;
|
||||
int state;
|
||||
int bufsize;
|
||||
int bufsize_dmx;
|
||||
void (*failureCallback)(void *);
|
||||
void *failureData;
|
||||
|
||||
sem_t sem;
|
||||
#define RECORD_WRITER_CHUNKS 16
|
||||
unsigned char *io_buf[RECORD_WRITER_CHUNKS];
|
||||
size_t io_len[RECORD_WRITER_CHUNKS];
|
||||
public:
|
||||
cRecord(int num = 0, int bs_dmx = 2048 * 1024, int bs = 4096 * 1024);
|
||||
void setFailureCallback(void (*f)(void *), void *d) { failureCallback = f; failureData = d; }
|
||||
~cRecord();
|
||||
|
||||
bool Open();
|
||||
bool Start(int fd, unsigned short vpid, unsigned short *apids, int numapids, uint64_t ch = 0);
|
||||
bool Stop(void);
|
||||
bool AddPid(unsigned short pid);
|
||||
int GetStatus();
|
||||
void ResetStatus();
|
||||
bool ChangePids(unsigned short vpid, unsigned short *apids, int numapids);
|
||||
|
||||
void RecordThread();
|
||||
void WriterThread();
|
||||
};
|
||||
#endif
|
1005
libarmbox/video.cpp
1005
libarmbox/video.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,254 +0,0 @@
|
||||
#ifndef _VIDEO_TD_H
|
||||
#define _VIDEO_TD_H
|
||||
|
||||
#include <linux/dvb/video.h>
|
||||
#include "../common/cs_types.h"
|
||||
#include "dmx_lib.h"
|
||||
|
||||
typedef struct cs_vs_format_t
|
||||
{
|
||||
char format[16];
|
||||
} cs_vs_format_struct_t;
|
||||
|
||||
typedef enum {
|
||||
ANALOG_SD_RGB_CINCH = 0x00,
|
||||
ANALOG_SD_YPRPB_CINCH,
|
||||
ANALOG_HD_RGB_CINCH,
|
||||
ANALOG_HD_YPRPB_CINCH,
|
||||
ANALOG_SD_RGB_SCART = 0x10,
|
||||
ANALOG_SD_YPRPB_SCART,
|
||||
ANALOG_HD_RGB_SCART,
|
||||
ANALOG_HD_YPRPB_SCART,
|
||||
ANALOG_SCART_MASK = 0x10
|
||||
} analog_mode_t;
|
||||
|
||||
typedef enum {
|
||||
COLORFORMAT_RGB = 0x10, // keep compatible with analog_mode_t
|
||||
COLORFORMAT_YUV,
|
||||
COLORFORMAT_CVBS,
|
||||
COLORFORMAT_SVIDEO,
|
||||
COLORFORMAT_HDMI_RGB,
|
||||
COLORFORMAT_HDMI_YCBCR444,
|
||||
COLORFORMAT_HDMI_YCBCR422
|
||||
} COLOR_FORMAT;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_FORMAT_MPEG2 = 0,
|
||||
VIDEO_FORMAT_MPEG4_H264,
|
||||
VIDEO_FORMAT_VC1,
|
||||
VIDEO_FORMAT_JPEG,
|
||||
VIDEO_FORMAT_GIF,
|
||||
VIDEO_FORMAT_PNG,
|
||||
VIDEO_FORMAT_MPEG4_H265,
|
||||
VIDEO_FORMAT_AVS = 16
|
||||
} VIDEO_FORMAT;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_SD = 0,
|
||||
VIDEO_HD,
|
||||
VIDEO_120x60i,
|
||||
VIDEO_320x240i,
|
||||
VIDEO_1440x800i,
|
||||
VIDEO_360x288i
|
||||
} VIDEO_DEFINITION;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_FRAME_RATE_23_976 = 0,
|
||||
VIDEO_FRAME_RATE_24,
|
||||
VIDEO_FRAME_RATE_25,
|
||||
VIDEO_FRAME_RATE_29_97,
|
||||
VIDEO_FRAME_RATE_30,
|
||||
VIDEO_FRAME_RATE_50,
|
||||
VIDEO_FRAME_RATE_59_94,
|
||||
VIDEO_FRAME_RATE_60
|
||||
} VIDEO_FRAME_RATE;
|
||||
|
||||
typedef enum {
|
||||
DISPLAY_AR_1_1,
|
||||
DISPLAY_AR_4_3,
|
||||
DISPLAY_AR_14_9,
|
||||
DISPLAY_AR_16_9,
|
||||
DISPLAY_AR_20_9,
|
||||
DISPLAY_AR_RAW
|
||||
} DISPLAY_AR;
|
||||
|
||||
typedef enum {
|
||||
DISPLAY_AR_MODE_PANSCAN = 0,
|
||||
DISPLAY_AR_MODE_LETTERBOX,
|
||||
DISPLAY_AR_MODE_NONE,
|
||||
DISPLAY_AR_MODE_PANSCAN2
|
||||
} DISPLAY_AR_MODE;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_DB_DR_NEITHER = 0,
|
||||
VIDEO_DB_ON,
|
||||
VIDEO_DB_DR_BOTH
|
||||
} VIDEO_DB_DR;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_PLAY_STILL = 0,
|
||||
VIDEO_PLAY_CLIP,
|
||||
VIDEO_PLAY_TRICK,
|
||||
VIDEO_PLAY_MOTION,
|
||||
VIDEO_PLAY_MOTION_NO_SYNC
|
||||
} VIDEO_PLAY_MODE;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_STD_NTSC,
|
||||
VIDEO_STD_SECAM,
|
||||
VIDEO_STD_PAL,
|
||||
VIDEO_STD_480P,
|
||||
VIDEO_STD_576P,
|
||||
VIDEO_STD_720P60,
|
||||
VIDEO_STD_1080I60,
|
||||
VIDEO_STD_720P50,
|
||||
VIDEO_STD_1080I50,
|
||||
VIDEO_STD_1080P30,
|
||||
VIDEO_STD_1080P24,
|
||||
VIDEO_STD_1080P25,
|
||||
VIDEO_STD_1080P50,
|
||||
VIDEO_STD_1080P60,
|
||||
VIDEO_STD_1080P2397,
|
||||
VIDEO_STD_1080P2997,
|
||||
VIDEO_STD_2160P24,
|
||||
VIDEO_STD_2160P25,
|
||||
VIDEO_STD_2160P30,
|
||||
VIDEO_STD_2160P50,
|
||||
VIDEO_STD_AUTO,
|
||||
VIDEO_STD_MAX = VIDEO_STD_AUTO
|
||||
} VIDEO_STD;
|
||||
|
||||
typedef enum {
|
||||
VIDEO_HDMI_CEC_MODE_OFF = 0,
|
||||
VIDEO_HDMI_CEC_MODE_TUNER = 3,
|
||||
VIDEO_HDMI_CEC_MODE_RECORDER = 1
|
||||
} VIDEO_HDMI_CEC_MODE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VIDEO_CONTROL_BRIGHTNESS = 0,
|
||||
VIDEO_CONTROL_CONTRAST,
|
||||
VIDEO_CONTROL_SATURATION,
|
||||
VIDEO_CONTROL_HUE,
|
||||
VIDEO_CONTROL_SHARPNESS,
|
||||
VIDEO_CONTROL_MAX = VIDEO_CONTROL_SHARPNESS
|
||||
} VIDEO_CONTROL;
|
||||
|
||||
struct cec_message
|
||||
{
|
||||
unsigned char address;
|
||||
unsigned char length;
|
||||
unsigned char data[256];
|
||||
}__attribute__((packed));
|
||||
#define cec_rx_message cec_message
|
||||
struct addressinfo
|
||||
{
|
||||
unsigned char logical;
|
||||
unsigned char physical[2];
|
||||
unsigned char type;
|
||||
};
|
||||
|
||||
class cVideo
|
||||
{
|
||||
friend class cDemux;
|
||||
friend class cPlayback;
|
||||
private:
|
||||
/* video device */
|
||||
int fd;
|
||||
unsigned int devnum;
|
||||
/* apparently we cannot query the driver's state
|
||||
=> remember it */
|
||||
video_play_state_t playstate;
|
||||
int /*vidDispMode_t*/ croppingMode;
|
||||
int /*vidOutFmt_t*/ outputformat;
|
||||
|
||||
VIDEO_FORMAT StreamType;
|
||||
VIDEO_DEFINITION VideoDefinition;
|
||||
DISPLAY_AR DisplayAR;
|
||||
VIDEO_PLAY_MODE SyncMode;
|
||||
DISPLAY_AR_MODE ARMode;
|
||||
VIDEO_DB_DR eDbDr;
|
||||
DISPLAY_AR PictureAR;
|
||||
VIDEO_FRAME_RATE FrameRate;
|
||||
int video_standby;
|
||||
int brightness;
|
||||
int contrast;
|
||||
int saturation;
|
||||
int hue;
|
||||
|
||||
/* used internally by dmx */
|
||||
int64_t GetPTS(void);
|
||||
|
||||
unsigned char physicalAddress[2];
|
||||
bool standby_cec_activ,autoview_cec_activ;
|
||||
unsigned char deviceType, logicalAddress;
|
||||
int hdmiFd;
|
||||
|
||||
public:
|
||||
/* constructor & destructor */
|
||||
cVideo(int mode, void *, void *, unsigned int unit = 0);
|
||||
~cVideo(void);
|
||||
|
||||
/* used internally by playback */
|
||||
void openDevice(void);
|
||||
void closeDevice(void);
|
||||
|
||||
void * GetTVEnc() { return NULL; };
|
||||
void * GetTVEncSD() { return NULL; };
|
||||
|
||||
/* aspect ratio */
|
||||
int getAspectRatio(void);
|
||||
void getPictureInfo(int &width, int &height, int &rate);
|
||||
int setAspectRatio(int aspect, int mode);
|
||||
|
||||
/* cropping mode */
|
||||
int setCroppingMode(int x = 0 /*vidDispMode_t x = VID_DISPMODE_NORM*/);
|
||||
|
||||
/* get play state */
|
||||
int getPlayState(void);
|
||||
|
||||
/* blank on freeze */
|
||||
int getBlank(void);
|
||||
int setBlank(int enable);
|
||||
|
||||
/* change video play state. Parameters are all unused. */
|
||||
int Start(void *PcrChannel = NULL, unsigned short PcrPid = 0, unsigned short VideoPid = 0, void *x = NULL);
|
||||
int Stop(bool blank = true);
|
||||
bool Pause(void);
|
||||
|
||||
/* get video system infos */
|
||||
int GetVideoSystem(void);
|
||||
/* when system = -1 then use current video system */
|
||||
void GetVideoSystemFormatName(cs_vs_format_t* format, int system);
|
||||
|
||||
/* set video_system */
|
||||
int SetVideoSystem(int video_system, bool remember = true);
|
||||
int SetStreamType(VIDEO_FORMAT type);
|
||||
void SetSyncMode(AVSYNC_TYPE mode);
|
||||
bool SetCECMode(VIDEO_HDMI_CEC_MODE);
|
||||
void SetCECAutoView(bool);
|
||||
void SetCECAutoStandby(bool);
|
||||
void GetCECAddressInfo();
|
||||
void SendCECMessage(struct cec_message &message);
|
||||
void SetCECState(bool state);
|
||||
void ReportPhysicalAddress();
|
||||
void ShowPicture(const char * fname, const char *_destname = NULL);
|
||||
void StopPicture();
|
||||
void Standby(unsigned int bOn);
|
||||
void Pig(int x, int y, int w, int h, int osd_w = 1064, int osd_h = 600, int startx = 0, int starty = 0, int endx = 1279, int endy = 719);
|
||||
void SetControl(int, int);
|
||||
void setContrast(int val);
|
||||
void SetVideoMode(analog_mode_t mode);
|
||||
void SetDBDR(int) { return; };
|
||||
void SetAudioHandle(void *) { return; };
|
||||
void SetAutoModes(int [VIDEO_STD_MAX]) { return; };
|
||||
int OpenVBI(int) { return 0; };
|
||||
int CloseVBI(void) { return 0; };
|
||||
int StartVBI(unsigned short) { return 0; };
|
||||
int StopVBI(void) { return 0; };
|
||||
void SetDemux(cDemux *dmx);
|
||||
void SetColorFormat(COLOR_FORMAT color_format);
|
||||
bool GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video = true, bool get_osd = false, bool scale_to_video = false);
|
||||
};
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user