92 Commits

Author SHA1 Message Date
Thilo Graf
593c903846 update to version 1.4.0
- removed azbox, tripledragon
- hisilcon fixes
2020-10-04 17:06:37 +02:00
max_10
f2551c4866 - TRIPLEDRAGON: libtriple deleted 2020-10-04 16:19:49 +02:00
max_10
5a44386b34 - AZBOX: libazbox deleted 2020-10-04 16:19:07 +02:00
BPanther
a3e139776f vuduo4kse added 2020-10-04 16:17:30 +02:00
TangoCash
f74c04e03e - HD61 has ci 2020-10-04 16:17:27 +02:00
TangoCash
4a98c127e2 supplemental to last commit 2020-10-04 16:17:18 +02:00
TangoCash
3e49c20f4c use new define 2020-10-04 16:17:07 +02:00
TangoCash
3084287bd1 fix HD60/HD61 2020-10-04 16:17:02 +02:00
TangoCash
f6cf97a321 fix HD60/HD61 playback 2020-10-04 16:16:57 +02:00
TangoCash
e1c1c07b0d save cover if available, report avfc to streaminfo2 2020-10-03 16:36:13 +02:00
svenhoefer
ecb34f1cd1 - introduce can_cpufreq to control the cpu frequency
Signed-off-by: Thilo Graf <dbt@novatux.de>
2020-09-01 16:58:33 +02:00
DboxOldie
65aee42473 enable limit macros 2020-09-01 16:54:12 +02:00
GetAway
87b90f25ff introduce caps.display_has_colon 2020-07-16 14:44:13 +02:00
Markus Volk
e21785e7d0 playback_hisilicon: add some dummy functions to fix the build 2020-07-11 10:04:54 +02:00
Jacek Jendrzej
2ec2c1f97c libarmbox/playback_libeplayer3.cpp: try to fix box freeze after pause->fastforward 2020-07-05 18:19:08 +02:00
TangoCash
2d58382cdf hdmi cec reduce cpu load 2020-07-01 09:21:24 +02:00
max_10
cf9f93f459 - fix build hd60 2020-07-01 09:20:11 +02:00
max_10
2fbfd158df - hdmi_cec: fix warning: invalid suffix on literal; C++11 requires a space between literal and string macro 2020-07-01 09:20:07 +02:00
TangoCash
801f496c2d hdmi cec optimize timings 2020-07-01 09:19:59 +02:00
svenhoefer
ba934dd995 - rework VUPLUS defines
Signed-off-by: Thilo Graf <dbt@novatux.de>
2020-07-01 09:19:45 +02:00
TangoCash
6137874561 use hdmi_cec device only for VU 2020-07-01 09:19:29 +02:00
TangoCash
162be459ac fix CEC for all arm boxes #2 2020-07-01 09:19:25 +02:00
TangoCash
349cb2dbd4 fix CEC for all arm boxes 2020-07-01 09:19:21 +02:00
svenhoefer
aec6e74897 Revert "- libarmbox: try to fix cec"
This reverts commit bede15daa62c8896d9e43d19c4492cf3e2c26bd2.

Signed-off-by: Thilo Graf <dbt@novatux.de>
2020-07-01 09:18:44 +02:00
Jacek Jendrzej
e52a31f89c libeplayer3/manager/ fix other possible segfault 2020-05-24 15:13:15 +02:00
Jacek Jendrzej
731ed1ea89 libeplayer3/manager/audio.c: fix possible segfault 2020-04-05 07:50:12 +02:00
Jacek Jendrzej
aaf845a711 libgeneric-pc: fix compil - add missing VIDEO_STD enums 2020-03-07 19:52:48 +01:00
Markus Volk
bfc3b5f9d0 libarmbox/video.cpp: fix aspect settings for osmio 2020-03-05 10:03:20 +01:00
Jacek Jendrzej
89bc44dc26 libarmbox/playback_libeplayer3.cpp enable use headers with ffmpeg_av_dict_set 2020-03-03 08:04:28 +01:00
Jacek Jendrzej
cdf663d6b9 libeplayer3: disable mjpeg format,because hardware does not support and this kills PTS (mp3 with attached picture) 2020-03-02 18:50:21 +01:00
Frankenstone
f971434ab3 libarmbox/playback_libeplayer3.cpp: fix segfault when start webstream at first, thx DboxOldie 2020-02-26 10:14:54 +01:00
max_10
55839b5f87 - add osmio4k / osmio4kplus not yet ready
Conflicts:
	acinclude.m4
	libarmbox/hardware_caps.c

Signed-off-by: Thilo Graf <dbt@novatux.de>

osmio4k only
2020-02-26 10:12:36 +01:00
DboxOldie
67110fb054 sh4 eplayer prevent segfaults caused audio rework 2020-02-18 18:54:56 +01:00
TangoCash
480d23dc30 fix init jump 2020-02-18 18:54:42 +01:00
DboxOldie
566ccea279 libeplayer3-sh4: select audio at start 2020-02-18 18:54:27 +01:00
Markus Volk
a5fe472896 unify boxmodel name 2020-02-18 13:55:33 +01:00
Thilo Graf
6b15c22726 update version to 1.3.0 mpx
osmioplus4k added
2020-02-16 11:13:25 +01:00
Markus Volk
f9bb987a43 add osmioplus4k stb 2020-02-16 08:40:39 +01:00
DboxOldie
8f53e0d2d9 reduce arm ifndef warning 2020-02-13 22:00:18 +01:00
Frankenstone
64d853f245 ca_ci.cpp: fix -fpermissive error on aarch64 only arm/mips hardware, thx flk ;-) 2020-02-13 22:00:01 +01:00
Frankenstone
d0c12909c9 Revert "ca_ci.cpp: fix -fpermissive error on aarch64" 2020-02-13 09:56:15 +01:00
BPanther
1b4c5dc1f8 vuplus_arm: fix dmx_source 2020-02-13 09:55:52 +01:00
Markus Volk
f4bc510536 libarmbox/video.cpp: add missing defines
VIDEO_GET_FRAME_RATE was dropped in 4.19 kernel
2020-02-10 14:13:09 +01:00
Markus Volk
7cab06c525 linuxdvb_mipsel.c: add missing define AUDIO_GET_PTS has been removed from kernel 4.8 2020-02-10 10:43:44 +01:00
Markus Volk
a9251b30d1 dmx_hal.h: add needed defines DMX_SET_SOURCE and dmx_source enum removed on 4.14 kernel 2020-02-10 10:43:38 +01:00
BPanther
e22c3033af sh4 fix mp3 (thx DBoxOldie) 2020-02-07 17:44:21 +01:00
BPanther
83437c3656 patch for sh4 and actual ffmpeg versions (thx DBoxOldie) 2020-02-07 17:44:15 +01:00
MarkusVolk
5e3736a0a8 ca_ci.cpp: supplement to 9a9372931a 2020-02-07 10:12:25 +01:00
Markus Volk
9a9372931a ca_ci.cpp: fix -fpermissive error on aarch64
2020-02-06 19:43:08 +01:00
Jacek Jendrzej
0e82fc5325 playback_libeplayer3.cpp: fix compil warning 2020-02-04 17:15:06 +01:00
Thilo Graf
3c2ccc6fee libgeneric-pc: fix possible compiler warning Wunused-parameter 2020-01-28 09:58:41 +01:00
BPanther
34fc6368c4 arm/mips: more zappingmode options 2020-01-28 09:33:08 +01:00
BPanther
b6fe299ee6 fix vuuno4k 2020-01-22 20:32:20 +01:00
DboxOldie
3d6077b3af fix build for no ci stb 2020-01-22 20:32:04 +01:00
BPanther
660c99317c vuplus: relevant pids routing - fix 2020-01-19 13:49:25 +01:00
BPanther
1db0ffb694 vuplus: relevant pids routing - fix 2020-01-19 13:49:16 +01:00
BPanther
0875e2c853 vuplus: relevant pids routing - fix 2020-01-19 13:49:08 +01:00
BPanther
f14212783b vuplus: relevant pids routing 2020-01-19 13:49:05 +01:00
svenhoefer
c14601465a - fix defines
Signed-off-by: Thilo Graf <dbt@novatux.de>
2020-01-19 13:48:51 +01:00
TangoCash
1920c37be5 - libarmbox: try to fix cec 2020-01-19 13:48:34 +01:00
DboxOldie
8658177951 small fix dvbci 2020-01-19 13:48:22 +01:00
BPanther
6eb082c12a vuplus: dvb wait delay for ci response 2020-01-19 13:48:08 +01:00
BPanther
a76f914d9b ci "extra_high" for vuplus 2020-01-19 13:47:46 +01:00
BPanther
32361d734e arm/mips: eplayer3 binary disabled 2020-01-14 12:31:58 +01:00
BPanther
fd8cc781dd dmx.cpp: fix debug 2020-01-14 12:31:56 +01:00
Thilo Graf
52213f9a21 fix pick error, remove wrong package name 2020-01-14 12:31:52 +01:00
svenhoefer
9c422e5713 - Revert first try to fix hdmi-cec
Signed-off-by: Thilo Graf <dbt@novatux.de>
2020-01-14 12:31:48 +01:00
Jacek Jendrzej
84ad5a2019 exteplayer.c:fix heap buffer overflow 2020-01-14 10:31:40 +01:00
Jacek Jendrzej
8ff9d03679 fix compiler warnings 2020-01-09 16:54:07 +01:00
Jacek Jendrzej
5791880e4c libgeneric-pc/clutterfb.cpp: sync keys with glfb.cpp 2020-01-06 13:34:41 +01:00
Thilo Graf
60f6a1f4be lib cleanup and sync for mips vu support 2020-01-05 21:11:50 +01:00
Thilo Graf
ed84d0ac6e libspark: fix pick error 2020-01-05 21:11:50 +01:00
Thilo Graf
92f912e541 libraspi: add missing links to generic-pc 2020-01-05 21:11:50 +01:00
vanhofen
5802a2ed1e - acinclude: resort 2020-01-05 21:11:50 +01:00
BPanther
7f329670fc some more devices for vu 2020-01-05 21:11:50 +01:00
svenhoefer
7a650421bf - libarmbox: align modification of /proc/stb/frontend/fbc/fcc to the proc_put calls above
Signed-off-by: Thilo Graf <dbt@novatux.de>
2020-01-05 21:11:50 +01:00
svenhoefer
fb8bb36cf7 - libarmbox: remove still picture while zapping
Conflicts:
	libarmbox/init.cpp

Signed-off-by: Thilo Graf <dbt@novatux.de>
2020-01-05 21:11:50 +01:00
svenhoefer
15ed156bd3 - vuplus: fix volume 0
Signed-off-by: Thilo Graf <dbt@novatux.de>
2020-01-05 21:11:50 +01:00
max_10
6e45d7affa - hardware_caps: bre2ze4k disable display has statusline 2020-01-05 21:11:50 +01:00
max_10
0f85aa4f60 - libeplayer3: fix __inline is not at beginning of declaration [-Wold-style-declaration] 2020-01-05 21:11:50 +01:00
svenhoefer
69a371a709 - vuplus: allow to control led brightness for zero4k and uno4k
maybe this is also usefull for the other vuplus4k boxes

 Conflicts:
	libarmbox/hardware_caps.c

Signed-off-by: Thilo Graf <dbt@novatux.de>

TODO: 	Maybe this commit makes behavior broken on boxes with line display eg. hd51.
	Observed in relation with simple_display.cpp, see neutrino source.
2020-01-05 20:59:46 +01:00
max_10
f26097e1fc - add h7
Conflicts:
	acinclude.m4
2020-01-05 20:42:27 +01:00
Thilo Graf
5979389a2c libgeneric-pc: fix possible linker error
undefined reference to symbol 'aio_error@@GLIBC_2.2.5'
.../x86_64-linux-gnu/librt.so: error adding symbols: DSO missing ...
2020-01-05 20:41:32 +01:00
Jacek Jendrzej
c4e474a48e libarmbox/video.cpp: image_to_mpeg2 fix memleak 2020-01-05 17:45:32 +01:00
Jacek Jendrzej
db244f0b8a libeplayer3-arm:playback.c reduce log errors 2020-01-03 21:54:48 +01:00
Jacek Jendrzej
c25f68eda1 av_dict_free avio_opts; fix memleak 2020-01-03 20:09:42 +01:00
Jacek Jendrzej
68fa79b83f libeplayer3-arm: malloc player once on neutrino start 2020-01-01 19:02:41 +01:00
Jacek Jendrzej
3b0bad6f54 libeplayer3-arm:playback.c: avoid use after free 2020-01-01 18:58:30 +01:00
Jacek Jendrzej
4d6eef9433 libarmbox/playback_libeplayer3: fix audio track select, broken pointer size 2019-12-29 19:59:39 +01:00
Jacek Jendrzej
f0f1a282bf libarmbox: stop player before free it 2019-12-29 11:48:50 +01:00
Jacek Jendrzej
603fba2500 playback arm: add option to play szSecondFile (audio) 2019-11-03 18:30:13 +01:00
Jacek Jendrzej
639762e1b3 subtitle: fix debug compil 2019-11-03 18:27:06 +01:00
206 changed files with 1730 additions and 8617 deletions

View File

@@ -12,18 +12,6 @@ libstb_hal_la_LIBADD = \
#libstb_hal_test_LDADD = libstb-hal.la
# there has to be a better way to do this...
if BOXTYPE_TRIPLE
SUBDIRS += libtriple
libstb_hal_la_LIBADD += \
libtriple/libtriple.la
endif
if BOXTYPE_AZBOX
SUBDIRS += libazbox
libstb_hal_la_LIBADD += \
libazbox/libazbox.la
endif
if BOXTYPE_GENERIC
if BOXMODEL_RASPI
SUBDIRS += libraspi
@@ -59,15 +47,37 @@ SUBDIRS += libarmbox
libstb_hal_la_LIBADD += \
libarmbox/libarmbox.la
else
if BOXMODEL_OSMIO4K
SUBDIRS += libarmbox
libstb_hal_la_LIBADD += \
libarmbox/libarmbox.la
else
if BOXMODEL_OSMIO4KPLUS
SUBDIRS += libarmbox
libstb_hal_la_LIBADD += \
libarmbox/libarmbox.la
else
#libstb_hal_test_LDADD += -lasound
SUBDIRS += libarmbox libdvbci
libstb_hal_la_LIBADD += \
libarmbox/libarmbox.la \
libdvbci/libdvbci.la
endif
endif
endif
if !ENABLE_GSTREAMER_10
SUBDIRS += libeplayer3-arm
SUBDIRS += libeplayer3
libstb_hal_la_LIBADD += \
libeplayer3-arm/libeplayer3_arm.la
libeplayer3/libeplayer3.la
endif
endif
if BOXTYPE_MIPSBOX
SUBDIRS += libmipsbox libdvbci
libstb_hal_la_LIBADD += \
libmipsbox/libmipsbox.la \
libdvbci/libdvbci.la
SUBDIRS += libeplayer3
libstb_hal_la_LIBADD += \
libeplayer3/libeplayer3.la
endif

View File

@@ -75,9 +75,9 @@ AC_SYS_LARGEFILE
AC_DEFUN([TUXBOX_BOXTYPE], [
AC_ARG_WITH(boxtype,
AS_HELP_STRING([--with-boxtype], [valid values: generic, azbox, tripledragon, spark, duckbox, armbox, mipsbox]),
AS_HELP_STRING([--with-boxtype], [valid values: generic, spark, duckbox, armbox, mipsbox]),
[case "${withval}" in
generic|azbox|tripledragon|spark|duckbox|armbox|mipsbox)
generic|spark|duckbox|armbox|mipsbox)
BOXTYPE="$withval"
;;
*)
@@ -90,7 +90,7 @@ AC_ARG_WITH(boxmodel,
AS_HELP_STRING([--with-boxmodel], [valid for generic: generic, raspi])
AS_HELP_STRING([], [valid for spark: spark, spark7162])
AS_HELP_STRING([], [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])
AS_HELP_STRING([], [valid for armbox: hd51, hd60, bre2ze4k, vusolo4k, vuduo4k, vuzero4k, h7])
AS_HELP_STRING([], [valid for armbox: hd51, hd60, hd61, bre2ze4k, h7, osmio4k, osmio4kplus, vusolo4k, vuduo4k, vuduo4kse, vuultimo4k, vuuno4k, vuuno4kse, vuzero4k])
AS_HELP_STRING([], [valid for mipsbox: vuduo]),
[case "${withval}" in
generic|raspi)
@@ -114,7 +114,7 @@ AS_HELP_STRING([], [valid for mipsbox: vuduo]),
AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE])
fi
;;
hd51|hd60|bre2ze4k|vusolo4k|vuduo4k|vuzero4k|h7)
hd51|hd60|hd61|bre2ze4k|h7|osmio4k|osmio4kplus|vusolo4k|vuduo4k|vuduo4kse|vuultimo4k|vuuno4k|vuuno4kse|vuzero4k)
if test "$BOXTYPE" = "armbox"; then
BOXMODEL="$withval"
else
@@ -138,8 +138,6 @@ AC_SUBST(BOXTYPE)
AC_SUBST(BOXMODEL)
AM_CONDITIONAL(BOXTYPE_GENERIC, test "$BOXTYPE" = "generic")
AM_CONDITIONAL(BOXTYPE_AZBOX, test "$BOXTYPE" = "azbox")
AM_CONDITIONAL(BOXTYPE_TRIPLE, test "$BOXTYPE" = "tripledragon")
AM_CONDITIONAL(BOXTYPE_SPARK, test "$BOXTYPE" = "spark")
AM_CONDITIONAL(BOXTYPE_DUCKBOX, test "$BOXTYPE" = "duckbox")
AM_CONDITIONAL(BOXTYPE_ARMBOX, test "$BOXTYPE" = "armbox")
@@ -149,6 +147,11 @@ AM_CONDITIONAL(BOXTYPE_MIPSBOX, test "$BOXTYPE" = "mipsbox")
AM_CONDITIONAL(BOXMODEL_GENERIC, test "$BOXMODEL" = "generic")
AM_CONDITIONAL(BOXMODEL_RASPI, test "$BOXMODEL" = "raspi")
# spark
AM_CONDITIONAL(BOXMODEL_SPARK, test "$BOXMODEL" = "spark")
AM_CONDITIONAL(BOXMODEL_SPARK7162, test "$BOXMODEL" = "spark7162")
# duckbox
AM_CONDITIONAL(BOXMODEL_UFS910, test "$BOXMODEL" = "ufs910")
AM_CONDITIONAL(BOXMODEL_UFS912, test "$BOXMODEL" = "ufs912")
AM_CONDITIONAL(BOXMODEL_UFS913, test "$BOXMODEL" = "ufs913")
@@ -180,22 +183,24 @@ AM_CONDITIONAL(BOXMODEL_HL101, test "$BOXMODEL" = "hl101")
# armbox
AM_CONDITIONAL(BOXMODEL_HD51, test "$BOXMODEL" = "hd51")
AM_CONDITIONAL(BOXMODEL_HD60, test "$BOXMODEL" = "hd60")
AM_CONDITIONAL(BOXMODEL_HD61, test "$BOXMODEL" = "hd61")
AM_CONDITIONAL(BOXMODEL_BRE2ZE4K, test "$BOXMODEL" = "bre2ze4k")
AM_CONDITIONAL(BOXMODEL_H7, test "$BOXMODEL" = "h7")
AM_CONDITIONAL(BOXMODEL_OSMIO4K, test "$BOXMODEL" = "osmio4k")
AM_CONDITIONAL(BOXMODEL_OSMIO4KPLUS, test "$BOXMODEL" = "osmio4kplus")
AM_CONDITIONAL(BOXMODEL_VUSOLO4K, test "$BOXMODEL" = "vusolo4k")
AM_CONDITIONAL(BOXMODEL_VUDUO4K, test "$BOXMODEL" = "vuduo4k")
AM_CONDITIONAL(BOXMODEL_VUDUO4KSE, test "$BOXMODEL" = "vuduo4kse")
AM_CONDITIONAL(BOXMODEL_VUULTIMO4K, test "$BOXMODEL" = "vuultimo4k")
AM_CONDITIONAL(BOXMODEL_VUUNO4K, test "$BOXMODEL" = "vuuno4k")
AM_CONDITIONAL(BOXMODEL_VUUNO4KSE, test "$BOXMODEL" = "vuuno4kse")
AM_CONDITIONAL(BOXMODEL_VUZERO4K, test "$BOXMODEL" = "vuzero4k")
AM_CONDITIONAL(BOXMODEL_VUDUO, test "$BOXMODEL" = "vuduo")
AM_CONDITIONAL(BOXMODEL_H7, test "$BOXMODEL" = "h7")
# mipsbox
AM_CONDITIONAL(BOXMODEL_VUDUO, test "$BOXMODEL" = "vuduo")
if test "$BOXTYPE" = "generic"; then
AC_DEFINE(HAVE_GENERIC_HARDWARE, 1, [building for a generic device like a standard PC])
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_SH4_HARDWARE, 1, [building for a sh4 box])
@@ -269,23 +274,81 @@ elif test "$BOXMODEL" = "hd51"; then
AC_DEFINE(BOXMODEL_HD51, 1, [hd51])
elif test "$BOXMODEL" = "hd60"; then
AC_DEFINE(BOXMODEL_HD60, 1, [hd60])
elif test "$BOXMODEL" = "hd61"; then
AC_DEFINE(BOXMODEL_HD61, 1, [hd61])
elif test "$BOXMODEL" = "bre2ze4k"; then
AC_DEFINE(BOXMODEL_BRE2ZE4K, 1, [bre2ze4k])
elif test "$BOXMODEL" = "h7"; then
AC_DEFINE(BOXMODEL_H7, 1, [h7])
elif test "$BOXMODEL" = "osmio4k"; then
AC_DEFINE(BOXMODEL_OSMIO4K, 1, [osmio4k])
elif test "$BOXMODEL" = "osmio4kplus"; then
AC_DEFINE(BOXMODEL_OSMIO4KPLUS, 1, [osmio4kplus])
elif test "$BOXMODEL" = "vusolo4k"; then
AC_DEFINE(BOXMODEL_VUSOLO4K, 1, [vusolo4k])
elif test "$BOXMODEL" = "vuduo4k"; then
AC_DEFINE(BOXMODEL_VUDUO4K, 1, [vuduo4k])
elif test "$BOXMODEL" = "vuduo4kse"; then
AC_DEFINE(BOXMODEL_VUDUO4KSE, 1, [vuduo4kse])
elif test "$BOXMODEL" = "vuultimo4k"; then
AC_DEFINE(BOXMODEL_VUULTIMO4K, 1, [vuultimo4k])
elif test "$BOXMODEL" = "vuuno4k"; then
AC_DEFINE(BOXMODEL_VUUNO4K, 1, [vuuno4k])
elif test "$BOXMODEL" = "vuuno4kse"; then
AC_DEFINE(BOXMODEL_VUUNO4KSE, 1, [vuuno4kse])
elif test "$BOXMODEL" = "vuzero4k"; then
AC_DEFINE(BOXMODEL_VUZERO4K, 1, [vuzero4k])
elif test "$BOXMODEL" = "vuduo"; then
AC_DEFINE(BOXMODEL_VUDUO, 1, [vuduo])
elif test "$BOXMODEL" = "h7"; then
AC_DEFINE(BOXMODEL_H7, 1, [h7])
elif test "$BOXMODEL" = "generic"; then
AC_DEFINE(BOXMODEL_GENERIC, 1, [generic pc])
elif test "$BOXMODEL" = "raspi"; then
AC_DEFINE(BOXMODEL_RASPI, 1, [raspberry pi])
fi
# all vuplus BOXMODELs
case "$BOXMODEL" in
vusolo4k|vuduo4k|vuduo4kse|vuultimo4k|vuuno4k|vuuno4kse|vuzero4k|vuduo)
AC_DEFINE(BOXMODEL_VUPLUS_ALL, 1, [vuplus_all])
vuplus_all=true
;;
*)
vuplus_all=false
;;
esac
AM_CONDITIONAL(BOXMODEL_VUPLUS_ALL, test "$vuplus_all" = "true")
# all vuplus arm BOXMODELs
case "$BOXMODEL" in
vusolo4k|vuduo4k|vuduo4kse|vuultimo4k|vuuno4k|vuuno4kse|vuzero4k)
AC_DEFINE(BOXMODEL_VUPLUS_ARM, 1, [vuplus_arm])
vuplus_arm=true
;;
*)
vuplus_arm=false
;;
esac
AM_CONDITIONAL(BOXMODEL_VUPLUS_ARM, test "$vuplus_arm" = "true")
# all vuplus mips BOXMODELs
case "$BOXMODEL" in
vuduo)
AC_DEFINE(BOXMODEL_VUPLUS_MIPS, 1, [vuplus_mips])
vuplus_mips=true
;;
*)
vuplus_mips=false
;;
esac
AM_CONDITIONAL(BOXMODEL_VUPLUS_MIPS, test "$vuplus_mips" = "true")
# all hisilicon BOXMODELs
case "$BOXMODEL" in
hd60|hd61)
AC_DEFINE(BOXMODEL_HISILICON, 1, [hisilicon])
hisilicon=true
;;
*)
hisilicon=false
;;
esac
AM_CONDITIONAL(BOXMODEL_HISILICON, test "$hisilicon" = "true")
])
dnl backward compatiblity

View File

@@ -1,6 +1,13 @@
#!/bin/bash
#!/bin/sh
package="libstb-hal"
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
cd "$srcdir"
echo "Generating configuration files for $package, please wait ..."
cd $(dirname $0)
aclocal --force
libtoolize --force
autoconf --force

View File

@@ -17,6 +17,15 @@ AM_CXXFLAGS += \
-I $(top_srcdir)/libdvbci
endif
if BOXTYPE_MIPSBOX
AM_CXXFLAGS += \
-I $(top_srcdir)/libdvbci
endif
if BOXTYPE_MIPSBOX
libcommon_la_SOURCES = \
ca_ci.cpp
else
if BOXTYPE_DUCKBOX
libcommon_la_SOURCES = \
ca_ci.cpp
@@ -26,14 +35,24 @@ if BOXMODEL_HD60
libcommon_la_SOURCES = \
ca.cpp
else
if BOXMODEL_OSMIO4K
libcommon_la_SOURCES = \
ca.cpp
else
if BOXMODEL_OSMIO4KPLUS
libcommon_la_SOURCES = \
ca.cpp
else
libcommon_la_SOURCES = \
ca_ci.cpp
endif
endif
endif
else
libcommon_la_SOURCES = \
ca.cpp
endif
endif
endif
libcommon_la_SOURCES += \

View File

@@ -41,7 +41,7 @@ static const char * FILENAME = "[ca_ci]";
const char ci_path[] = "/dev/dvb/adapter0/ci%d";
ca_slot_info_t info;
#endif
#if HAVE_ARM_HARDWARE
#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE
const char ci_path[] = "/dev/ci%d";
static int last_source = -1;
#endif
@@ -56,7 +56,11 @@ static cCA* pcCAInstance = NULL;
/* nur diese Message wird vom CI aus neutrinoMessages.h benutzt */
/* für den CamMsgHandler, darum hier einfach mal definiert */
/* die Feinheiten werden ja in CA_MESSAGE verpackt */
#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE
uintptr_t EVT_CA_MESSAGE = 0x80000000 + 60;
#else
uint32_t EVT_CA_MESSAGE = 0x80000000 + 60;
#endif
static cs_messenger cam_messenger = NULL;
@@ -234,7 +238,7 @@ static bool transmitData(eDVBCISlot* slot, unsigned char* d, int len)
{
printf("%s -> %s len(%d)\n", FILENAME, __func__, len);
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUZERO4K
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE || BOXMODEL_VUULTIMO4K || BOXMODEL_VUZERO4K
#if y_debug
for (int i = 0; i < len; i++)
printf("%02x ", d[i]);
@@ -263,7 +267,7 @@ static bool transmitData(eDVBCISlot* slot, unsigned char* d, int len)
//send some data on an fd, for a special slot and connection_id
eData sendData(eDVBCISlot* slot, unsigned char* data, int len)
{
#if HAVE_ARM_HARDWARE
#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE
unsigned char *d = (unsigned char*) malloc(len);
memcpy(d, data, len);
transmitData(slot, d, len);
@@ -479,7 +483,12 @@ bool cCA::SendMessage(const CA_MESSAGE *msg)
{
hal_debug("%s\n", __func__);
if(cam_messenger)
#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE
cam_messenger(EVT_CA_MESSAGE, (uintptr_t) msg);
#else
cam_messenger(EVT_CA_MESSAGE, (uint32_t) msg);
#endif
#if z_debug
printf("*******Message\n");
printf("msg: %p\n", msg);
@@ -878,7 +887,7 @@ bool cCA::SendCAPMT(u64 tpid, u8 source, u8 camask, const unsigned char * cabuf,
(*It)->SID[0] = SID;
(*It)->ci_use_count = 1;
(*It)->TP = TP;
#if HAVE_ARM_HARDWARE
#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE
if(!checkLiveSlot && mode && (*It)->source != source)
setInputSource((eDVBCISlot*)(*It), false);
#endif
@@ -889,7 +898,7 @@ bool cCA::SendCAPMT(u64 tpid, u8 source, u8 camask, const unsigned char * cabuf,
(*It)->newCapmt = true;
}
#if HAVE_ARM_HARDWARE
#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE
if ((*It)->newCapmt)
extractPids((eDVBCISlot*)(*It));
#endif
@@ -917,7 +926,7 @@ bool cCA::SendCAPMT(u64 tpid, u8 source, u8 camask, const unsigned char * cabuf,
}
else
{
#if HAVE_ARM_HARDWARE
#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE
std::list<eDVBCISlot*>::iterator it;
recordUse_found = false;
for (it = slot_data.begin(); it != slot_data.end(); ++it)
@@ -958,7 +967,7 @@ bool cCA::SendCAPMT(u64 tpid, u8 source, u8 camask, const unsigned char * cabuf,
return true;
}
#if HAVE_ARM_HARDWARE
#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE
void cCA::extractPids(eDVBCISlot* slot)
{
u32 prg_info_len;
@@ -1017,7 +1026,7 @@ void cCA::setSource(eDVBCISlot* slot)
case TUNER_D:
fprintf(ci, "D");
break;
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE || BOXMODEL_VUULTIMO4K
case TUNER_E:
fprintf(ci, "E");
break;
@@ -1054,13 +1063,39 @@ void cCA::setSource(eDVBCISlot* slot)
case TUNER_P:
fprintf(ci, "P");
break;
#if BOXMODEL_VUULTIMO4K
case TUNER_Q:
fprintf(ci, "Q");
break;
case TUNER_R:
fprintf(ci, "R");
break;
case TUNER_S:
fprintf(ci, "S");
break;
case TUNER_T:
fprintf(ci, "T");
break;
case TUNER_U:
fprintf(ci, "U");
break;
case TUNER_V:
fprintf(ci, "V");
break;
case TUNER_W:
fprintf(ci, "W");
break;
case TUNER_X:
fprintf(ci, "X");
break;
#endif
#endif
}
fclose(ci);
}
}
#if HAVE_ARM_HARDWARE
#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE
static std::string getTunerLetter(int number) { return std::string(1, char(65 + number)); }
void cCA::setInputs()
@@ -1069,10 +1104,14 @@ void cCA::setInputs()
char choices[64];
FILE * fd = 0;
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K
#if BOXMODEL_VUULTIMO4K
for (int number = 0; number < 24; number++) // tuner A to X, input 0 to 23
#else
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE || BOXMODEL_VUUNO4KSE || BOXMODEL_VUUNO4K
for (int number = 0; number < 16; number++) // tuner A to P, input 0 to 15
#else
for (int number = 0; number < 4; number++) // tuner A to D, input 0 to 3
#endif
#endif
{
snprintf(choices, 64, "/proc/stb/tsmux/input%d_choices", number);
@@ -1134,7 +1173,7 @@ void cCA::setInputSource(eDVBCISlot* slot, bool ci)
case TUNER_D:
fprintf(input, "D");
break;
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE || BOXMODEL_VUULTIMO4K || BOXMODEL_VUUNO4KSE || BOXMODEL_VUUNO4K
case TUNER_E:
fprintf(input, "E");
break;
@@ -1171,6 +1210,32 @@ void cCA::setInputSource(eDVBCISlot* slot, bool ci)
case TUNER_P:
fprintf(input, "P");
break;
#if BOXMODEL_VUULTIMO4K
case TUNER_Q:
fprintf(input, "Q");
break;
case TUNER_R:
fprintf(input, "R");
break;
case TUNER_S:
fprintf(input, "S");
break;
case TUNER_T:
fprintf(input, "T");
break;
case TUNER_U:
fprintf(input, "U");
break;
case TUNER_V:
fprintf(input, "V");
break;
case TUNER_W:
fprintf(input, "W");
break;
case TUNER_X:
fprintf(input, "X");
break;
#endif
#endif
}
}
@@ -1184,7 +1249,7 @@ cCA::cCA(int Slots)
printf("%s -> %s %d\n", FILENAME, __func__, Slots);
num_slots = Slots;
#if HAVE_ARM_HARDWARE
#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE
setInputs();
#endif
@@ -1280,7 +1345,7 @@ void cCA::ModuleReset(enum CA_SLOT_TYPE, uint32_t slot)
{
(*it)->status = eStatusReset;
usleep(200000);
#if HAVE_ARM_HARDWARE
#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE
last_source = (int)(*it)->source;
setInputSource((eDVBCISlot*)(*it), false);
#endif
@@ -1373,7 +1438,7 @@ void cCA::ci_inserted(eDVBCISlot* slot)
void cCA::ci_removed(eDVBCISlot* slot)
{
printf("cam (%d) status changed ->cam now _not_ present\n", slot->slot);
#if HAVE_ARM_HARDWARE
#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE
last_source = (int)slot->source;
setInputSource(slot, false);
#endif
@@ -1444,7 +1509,7 @@ void cCA::slot_pollthread(void *c)
while (1)
{
#if HAVE_ARM_HARDWARE /* Armbox */
#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE /* Armbox/Mipsbox */
int len = 1024 *4;
eData status;
@@ -1685,7 +1750,7 @@ FROM_FIRST:
break;
} /* switch(slot->status) */
#endif /* end Duckbox */
#if HAVE_ARM_HARDWARE
#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE
if (!slot->init && slot->camIsReady && last_source > -1)
{
slot->source = (u8)last_source;
@@ -1740,7 +1805,7 @@ bool cCA::SendCaPMT(eDVBCISlot* slot)
printf("%s -> %s\n", FILENAME, __func__);
if (slot->fd > 0)
{
#if HAVE_ARM_HARDWARE
#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE
setInputSource(slot, true);
#endif
setSource(slot);
@@ -1850,7 +1915,7 @@ void cCA::setCheckLiveSlot(int check)
checkLiveSlot = false;
}
void cCA::SetTSClock(u32 Speed)
void cCA::SetTSClock(u32 Speed, int slot)
{
/* TODO:
* For now using the coolstream values from neutrino cam_menu
@@ -1862,20 +1927,47 @@ void cCA::SetTSClock(u32 Speed)
* and here too.
* On the other hand: or ci_clock will be set here for all ci slots ????
*/
char buf[64];
snprintf(buf, 64, "/proc/stb/tsmux/ci%d_tsclk", 0);
char buf[64];
snprintf(buf, 64, "/proc/stb/tsmux/ci%d_tsclk", slot);
FILE *ci = fopen(buf, "wb");
printf("%s -> %s to: %s\n", FILENAME, __func__, Speed > 6 * 1000000 ? "high" : "normal");
printf("%s -> %s to: %s\n", FILENAME, __func__, Speed > 9 * 1000000 ? "extra_high" : Speed > 6 * 1000000 ? "high" : "normal");
if (ci)
{
if (Speed > 6 * 1000000)
{
fprintf(ci, "high");
}
if (Speed > 9 * 1000000)
fprintf(ci, "extra_high");
else
if (Speed > 6 * 1000000)
fprintf(ci, "high");
else
{
fprintf(ci, "normal");
}
fclose(ci);
}
}
#if BOXMODEL_VUPLUS_ALL
void cCA::SetCIDelay(int Delay)
{
char buf[64];
snprintf(buf, 64, "/proc/stb/tsmux/rmx_delay");
FILE *ci = fopen(buf, "wb");
printf("%s -> %s to: %i\n", FILENAME, __func__, Delay);
if (ci)
{
fprintf(ci, "%i", Delay);
fclose(ci);
}
}
void cCA::SetCIRelevantPidsRouting(int RPR, int slot)
{
char buf[64];
snprintf(buf, 64, "/proc/stb/tsmux/ci%d_relevant_pids_routing", slot);
FILE *ci = fopen(buf, "wb");
printf("%s -> %s to: %i\n", FILENAME, __func__, RPR);
if (ci)
{
fprintf(ci, "%s", RPR == 1 ? "yes" : "no");
fclose(ci);
}
}
#endif

View File

@@ -1,6 +1,6 @@
# explicit defines for separate revision handling
define(ver_major, 1)
define(ver_minor, 2)
define(ver_minor, 4)
define(ver_micro, 0)
# sync with current git
@@ -95,27 +95,26 @@ if test x$BOXTYPE = xgeneric -a x$BOXMODEL != xraspi; then
fi
AC_ARG_ENABLE(flv2mpeg4,
AS_HELP_STRING(--enable-flv2mpeg4, use flv2mpeg4 libeplayer3-arm),
AS_HELP_STRING(--enable-flv2mpeg4, use flv2mpeg4 libeplayer3),
,[enable_flv2mpeg4=no])
AM_CONDITIONAL(ENABLE_FLV2MPEG4, test "$enable_flv2mpeg4" = "yes")
if test "$enable_flv2mpeg4" = "yes"; then
AC_DEFINE(ENABLE_FLV2MPEG4, 1, [use flv2mpeg4 libeplayer3-arm])
AC_DEFINE(ENABLE_FLV2MPEG4, 1, [use flv2mpeg4 libeplayer3])
fi
AC_CONFIG_FILES([
Makefile
common/Makefile
libmipsbox/Makefile
libarmbox/Makefile
libazbox/Makefile
libduckbox/Makefile
libdvbci/Makefile
libeplayer3-arm/Makefile
libeplayer3/Makefile
libeplayer3-sh4/Makefile
libgeneric-pc/Makefile
libraspi/Makefile
libspark/Makefile
libtriple/Makefile
tools/Makefile
])

View File

@@ -1,7 +1,5 @@
#include <config.h>
#if HAVE_TRIPLEDRAGON
#include "../libtriple/audio_td.h"
#elif HAVE_DUCKBOX_HARDWARE
#if HAVE_DUCKBOX_HARDWARE
#include "../libduckbox/audio_lib.h"
#include "../libduckbox/audio_mixer.h"
#elif HAVE_SPARK_HARDWARE
@@ -9,8 +7,8 @@
#include "../libspark/audio_mixer.h"
#elif HAVE_ARM_HARDWARE
#include "../libarmbox/audio_lib.h"
#elif HAVE_AZBOX_HARDWARE
#include "../libazbox/audio_lib.h"
#elif HAVE_MIPS_HARDWARE
#include "../libmipsbox/audio_lib.h"
#elif HAVE_GENERIC_HARDWARE
#if BOXMODEL_RASPI
#include "../libraspi/audio_lib.h"

View File

@@ -110,7 +110,7 @@ public:
void MenuAnswer(enum CA_SLOT_TYPE, uint32_t Slot, uint32_t choice);
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; };
void SetTSClock(u32 /*Speed*/, int /*slot*/) { return; };
bool checkChannelID(u64 /*chanID*/) { return false; };
void setCheckLiveSlot(int /*check*/) { return; };
virtual ~cCA();

View File

@@ -127,7 +127,7 @@ typedef enum {
TUNER_B,
TUNER_C,
TUNER_D
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE || BOXMODEL_VUULTIMO4K || BOXMODEL_VUUNO4KSE || BOXMODEL_VUUNO4K
, TUNER_E
, TUNER_F
, TUNER_G
@@ -140,6 +140,16 @@ typedef enum {
, TUNER_N
, TUNER_O
, TUNER_P
#if BOXMODEL_VUULTIMO4K
, TUNER_Q
, TUNER_R
, TUNER_S
, TUNER_T
, TUNER_U
, TUNER_V
, TUNER_W
, TUNER_X
#endif
#endif
} source_t;
@@ -317,7 +327,15 @@ public:
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);
void SetTSClock(u32 Speed, int slot = 0);
#if BOXMODEL_VUPLUS_ALL
/// dvb wait delay for ci response
void SetCIDelay(int Delay);
/// relevant pids routing
void SetCIRelevantPidsRouting(int RPR, int slot = 0);
#endif
/// Start the CA module
/// sh4 unused
bool Start(void);

View File

@@ -1,4 +1,10 @@
#if HAVE_DUCKBOX_HARDWARE || (HAVE_ARM_HARDWARE && !BOXMODEL_HD60)
#if HAVE_DUCKBOX_HARDWARE \
|| HAVE_MIPS_HARDWARE \
|| (HAVE_ARM_HARDWARE \
&& !BOXMODEL_HD60 \
&& !BOXMODEL_OSMIO4K \
&& !BOXMODEL_OSMIO4KPLUS \
)
#include "ca_ci.h"
#else
#include "ca.h"

View File

@@ -23,7 +23,13 @@ inline void cs_api_exit()
#define cs_free_uncached free
// Callback function helpers
#if HAVE_DUCKBOX_HARDWARE || (HAVE_ARM_HARDWARE && !BOXMODEL_HD60)
#if HAVE_DUCKBOX_HARDWARE \
|| HAVE_MIPS_HARDWARE \
|| (HAVE_ARM_HARDWARE \
&& !BOXMODEL_HD60 \
&& !BOXMODEL_OSMIO4K \
&& !BOXMODEL_OSMIO4KPLUS \
)
void cs_register_messenger(cs_messenger messenger);
#else
static inline void cs_register_messenger(cs_messenger) { return; };

View File

@@ -37,11 +37,38 @@ extern "C" {
#include <cs_types.h>
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K
#if BOXMODEL_VUULTIMO4K
#define MAX_DMX_UNITS 24
#else
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE || BOXMODEL_VUUNO4KSE || BOXMODEL_VUUNO4K
#define MAX_DMX_UNITS 16
#else
#define MAX_DMX_UNITS 4
#endif
#endif
#ifndef DMX_SET_SOURCE
/**
* DMX_SET_SOURCE and dmx_source enum removed on 4.14 kernel
* From Github.com/OpenPLI/enigma2 commit 7996dbb
**/
enum dmx_source
{
DMX_SOURCE_FRONT0 = 0,
DMX_SOURCE_FRONT1,
DMX_SOURCE_FRONT2,
DMX_SOURCE_FRONT3,
#if BOXMODEL_VUPLUS_ARM
DMX_SOURCE_DVR0 = 32,
#else
DMX_SOURCE_DVR0 = 16,
#endif
DMX_SOURCE_DVR1,
DMX_SOURCE_DVR2,
DMX_SOURCE_DVR3
};
#define DMX_SET_SOURCE _IOW('o', 49, enum dmx_source)
#endif
typedef enum
{

View File

@@ -15,6 +15,7 @@ extern "C" {
typedef enum
{
HW_DISPLAY_NONE,
HW_DISPLAY_LED_ONLY,
HW_DISPLAY_LED_NUM, /* simple 7 segment LED display */
HW_DISPLAY_LINE_TEXT, /* 1 line text display */
HW_DISPLAY_GFX
@@ -28,6 +29,7 @@ typedef struct hw_caps
int has_SCART;
int has_SCART_input;
int has_YUV_cinch;
int can_cpufreq;
int can_shutdown;
int can_cec;
int can_ar_14_9; /* video drivers have 14:9 aspect ratio mode */
@@ -39,6 +41,7 @@ typedef struct hw_caps
int display_can_set_brightness;
int display_can_deepstandby;
int display_has_statusline;
int display_has_colon;
int has_button_timer;
int has_button_vformat;
char boxvendor[64];

View File

@@ -1,7 +1,5 @@
#include <config.h>
#if HAVE_TRIPLEDRAGON
#include "../libtriple/playback_td.h"
#elif HAVE_DUCKBOX_HARDWARE
#if HAVE_DUCKBOX_HARDWARE
#include "../libduckbox/playback_libeplayer3.h"
#elif HAVE_SPARK_HARDWARE
#include "../libspark/playback_libeplayer3.h"
@@ -9,14 +7,14 @@
#if ENABLE_GSTREAMER_10
#include "../libarmbox/playback_gst.h"
#else
#if BOXMODEL_HD60
#if BOXMODEL_HISILICON
#include "../libarmbox/playback_hisilicon.h"
#else
#include "../libarmbox/playback_libeplayer3.h"
#endif
#endif
#elif HAVE_AZBOX_HARDWARE
#include "../libazbox/playback_lib.h"
#elif HAVE_MIPS_HARDWARE
#include "../libmipsbox/playback_libeplayer3.h"
#elif HAVE_GENERIC_HARDWARE
#if BOXMODEL_RASPI
#include "../libraspi/playback_lib.h"

View File

@@ -1,14 +1,12 @@
#include <config.h>
#if HAVE_TRIPLEDRAGON
#include "../libtriple/record_td.h"
#elif HAVE_DUCKBOX_HARDWARE
#if 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 "../libazbox/record_lib.h"
#elif HAVE_MIPS_HARDWARE
#include "../libmipsbox/record_lib.h"
#elif HAVE_GENERIC_HARDWARE
#if BOXMODEL_RASPI
#include "../libraspi/record_lib.h"

View File

@@ -1,15 +1,14 @@
#include <config.h>
#if HAVE_TRIPLEDRAGON
#include "../libtriple/video_td.h"
#elif HAVE_DUCKBOX_HARDWARE
#if 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"
#include "../libarmbox/hdmi_cec.h"
#elif HAVE_AZBOX_HARDWARE
#include "../libazbox/video_lib.h"
#elif HAVE_MIPS_HARDWARE
#include "../libmipsbox/video_lib.h"
#include "../libmipsbox/hdmi_cec.h"
#elif HAVE_GENERIC_HARDWARE
#if BOXMODEL_RASPI
#include "../libraspi/video_lib.h"

View File

@@ -32,7 +32,7 @@ AM_LDFLAGS += \
-lgsttag-1.0 \
-lgstmpegts-1.0
else
if BOXMODEL_HD60
if BOXMODEL_HISILICON
libarmbox_la_SOURCES += \
playback_hisilicon.cpp
else
@@ -40,7 +40,7 @@ libarmbox_la_SOURCES += \
playback_libeplayer3.cpp
AM_CPPFLAGS += \
-I$(top_srcdir)/libeplayer3-arm/include
-I$(top_srcdir)/libeplayer3/include
endif
AM_LDFLAGS += \

View File

@@ -92,7 +92,15 @@ int map_volume(const int volume)
if (vol > 100)
vol = 100;
// convert to -1dB steps
vol = 63 - vol * 63 / 100;
// now range is 63..0, where 0 is loudest
#if BOXMODEL_VUPLUS_ALL
if (vol == 63)
vol = 255;
#endif
return vol;
}
@@ -103,10 +111,8 @@ int cAudio::setVolume(unsigned int left, unsigned int right)
volume = (left + right) / 2;
int v = map_volume(volume);
// convert to -1dB steps
left = map_volume(volume);
right = map_volume(volume);
//now range is 63..0, where 0 is loudest
audio_mixer_t mixer;
@@ -131,6 +137,9 @@ int cAudio::Start(void)
{
int ret;
ret = ioctl(fd, AUDIO_PLAY);
#if BOXMODEL_HISILICON
ioctl(fd, AUDIO_CONTINUE);
#endif
return ret;
}
@@ -337,7 +346,7 @@ int cAudio::StopClip()
hal_info("%s: clipfd not yet opened\n", __FUNCTION__);
return -1;
}
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUZERO4K
#if BOXMODEL_VUPLUS_ARM
ioctl(clipfd, SNDCTL_DSP_RESET);
#endif
close(clipfd);

View File

@@ -71,24 +71,36 @@ static const char *DMX_T[] = {
/* this is the number of different cDemux() units, not the number of
* /dev/dvb/.../demuxX devices! */
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K
#if BOXMODEL_VUULTIMO4K
#define NUM_DEMUX 24
#else
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE || BOXMODEL_VUUNO4KSE || BOXMODEL_VUUNO4K
#define NUM_DEMUX 16
#else
#define NUM_DEMUX 4
#endif
#endif
/* the current source of each cDemux unit */
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K
#if BOXMODEL_VUULTIMO4K
static int dmx_source[NUM_DEMUX] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
#else
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE || BOXMODEL_VUUNO4KSE || BOXMODEL_VUUNO4K
static int dmx_source[NUM_DEMUX] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
#else
static int dmx_source[NUM_DEMUX] = { 0, 0, 0, 0 };
#endif
#endif
/* map the device numbers. */
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K
#if BOXMODEL_VUULTIMO4K
#define NUM_DEMUXDEV 24
#else
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE || BOXMODEL_VUUNO4KSE || BOXMODEL_VUUNO4K
#define NUM_DEMUXDEV 16
#else
#define NUM_DEMUXDEV 8
#endif
#endif
static const char *devname[NUM_DEMUXDEV] = {
"/dev/dvb/adapter0/demux0",
"/dev/dvb/adapter0/demux1",
@@ -98,7 +110,7 @@ static const char *devname[NUM_DEMUXDEV] = {
"/dev/dvb/adapter0/demux5",
"/dev/dvb/adapter0/demux6",
"/dev/dvb/adapter0/demux7"
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUULTIMO4K || BOXMODEL_VUUNO4KSE || BOXMODEL_VUUNO4K
, "/dev/dvb/adapter0/demux8"
, "/dev/dvb/adapter0/demux9"
, "/dev/dvb/adapter0/demux10"
@@ -107,14 +119,28 @@ static const char *devname[NUM_DEMUXDEV] = {
, "/dev/dvb/adapter0/demux13"
, "/dev/dvb/adapter0/demux14"
, "/dev/dvb/adapter0/demux15"
#if BOXMODEL_VUULTIMO4K
, "/dev/dvb/adapter0/demux16"
, "/dev/dvb/adapter0/demux17"
, "/dev/dvb/adapter0/demux18"
, "/dev/dvb/adapter0/demux19"
, "/dev/dvb/adapter0/demux20"
, "/dev/dvb/adapter0/demux21"
, "/dev/dvb/adapter0/demux22"
, "/dev/dvb/adapter0/demux23"
#endif
#endif
};
/* did we already DMX_SET_SOURCE on that demux device? */
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K
#if BOXMODEL_VUULTIMO4K
static bool init[NUM_DEMUXDEV] = { false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false };
#else
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE || BOXMODEL_VUUNO4KSE || BOXMODEL_VUUNO4K
static bool init[NUM_DEMUXDEV] = { false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false };
#else
static bool init[NUM_DEMUXDEV] = { false, false, false, false, false, false, false, false };
#endif
#endif
typedef struct dmx_pdata {
int last_source;
@@ -450,11 +476,11 @@ bool cDemux::sectionFilter(unsigned short _pid, const unsigned char * const filt
s_flt.timeout = to;
hal_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]);
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");
fprintf(stderr,"filt: "); for (int i = 0; i < len; i++) fprintf(stderr, "%02hhx ", s_flt.filter.filter[i]); fprintf(stderr, "\n");
fprintf(stderr,"mask: "); for (int i = 0; i < len; i++) fprintf(stderr, "%02hhx ", s_flt.filter.mask [i]); fprintf(stderr, "\n");
fprintf(stderr,"mode: "); for (int i = 0; i < len; i++) fprintf(stderr, "%02hhx ", s_flt.filter.mode [i]); fprintf(stderr, "\n");
#endif
ioctl (fd, DMX_STOP);
if (ioctl(fd, DMX_SET_FILTER, &s_flt) < 0)

View File

@@ -33,6 +33,7 @@ hw_caps_t *get_hwcaps(void)
initialized = 1;
caps.has_CI = 1;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 480;
caps.display_yres = 320;
@@ -40,6 +41,7 @@ hw_caps_t *get_hwcaps(void)
caps.display_can_deepstandby = 0; // 0 because we use graphlcd/lcd4linux
caps.display_can_set_brightness = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_statusline = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_colon = 0;
caps.has_button_timer = 1;
caps.has_button_vformat = 0;
caps.has_HDMI = 1;
@@ -51,6 +53,7 @@ hw_caps_t *get_hwcaps(void)
initialized = 1;
caps.has_CI = 2;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 480;
caps.display_yres = 320;
@@ -58,22 +61,63 @@ hw_caps_t *get_hwcaps(void)
caps.display_can_deepstandby = 0; // 0 because we use graphlcd/lcd4linux
caps.display_can_set_brightness = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_statusline = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_colon = 0;
caps.has_button_timer = 1;
caps.has_button_vformat = 0;
caps.has_HDMI = 1;
caps.has_HDMI = 2;
strcpy(caps.boxvendor, "VU+");
strcpy(caps.boxname, "DUO4K");
strcpy(caps.boxarch, "BCM7278");
#endif
#if BOXMODEL_VUDUO4KSE
initialized = 1;
caps.has_CI = 2;
caps.can_cec = 1;
caps.can_shutdown = 1;
caps.display_xres = 480;
caps.display_yres = 320;
caps.display_type = HW_DISPLAY_GFX;
caps.display_can_deepstandby = 0; // 0 because we use graphlcd/lcd4linux
caps.display_can_set_brightness = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_statusline = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_colon = 0;
caps.has_button_timer = 1;
caps.has_HDMI = 2;
strcpy(caps.boxvendor, "VU+");
strcpy(caps.boxname, "DUO4KSE");
strcpy(caps.boxarch, "BCM7444S");
#endif
#if BOXMODEL_VUULTIMO4K
initialized = 1;
caps.has_CI = 2;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 800;
caps.display_yres = 480;
caps.display_type = HW_DISPLAY_GFX;
caps.display_can_deepstandby = 0; // 0 because we use graphlcd/lcd4linux
caps.display_can_set_brightness = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_statusline = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_colon = 0;
caps.has_button_timer = 1;
caps.has_button_vformat = 0;
caps.has_HDMI = 2;
strcpy(caps.boxvendor, "VU+");
strcpy(caps.boxname, "ULTIMO4K");
strcpy(caps.boxarch, "BCM7444S");
#endif
#if BOXMODEL_VUZERO4K
initialized = 1;
caps.has_CI = 1;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_type = HW_DISPLAY_NONE;
caps.display_type = HW_DISPLAY_LED_ONLY;
caps.display_can_deepstandby = 0;
caps.display_can_set_brightness = 0;
caps.display_can_set_brightness = 1;
caps.display_has_statusline = 0;
caps.display_has_colon = 0;
caps.has_button_timer = 1;
caps.has_button_vformat = 0;
caps.has_HDMI = 1;
@@ -81,16 +125,56 @@ hw_caps_t *get_hwcaps(void)
strcpy(caps.boxname, "ZERO4K");
strcpy(caps.boxarch, "BCM72604");
#endif
#if BOXMODEL_VUUNO4KSE
initialized = 1;
caps.has_CI = 1;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 400;
caps.display_yres = 240;
caps.display_type = HW_DISPLAY_GFX;
caps.display_can_deepstandby = 0; // 0 because we use graphlcd/lcd4linux
caps.display_can_set_brightness = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_statusline = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_colon = 0;
caps.has_button_timer = 1;
caps.has_button_vformat = 0;
caps.has_HDMI = 2;
strcpy(caps.boxvendor, "VU+");
strcpy(caps.boxname, "UNO4KSE");
strcpy(caps.boxarch, "BCM7252S");
#endif
#if BOXMODEL_VUUNO4K
initialized = 1;
caps.has_CI = 1;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_type = HW_DISPLAY_LED_ONLY;
caps.display_can_deepstandby = 0;
caps.display_can_set_brightness = 1;
caps.display_has_statusline = 0;
caps.display_has_colon = 0;
caps.has_button_timer = 1;
caps.has_button_vformat = 0;
caps.has_HDMI = 1;
strcpy(caps.boxvendor, "VU+");
strcpy(caps.boxname, "UNO4K");
strcpy(caps.boxarch, "BCM7252S");
#endif
#if BOXMODEL_HD51
initialized = 1;
caps.has_CI = 1;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 16;
caps.display_type = HW_DISPLAY_LINE_TEXT;
caps.display_can_deepstandby = 0;
caps.display_can_set_brightness = 1;
caps.display_has_statusline = 0;
caps.display_has_colon = 0;
caps.has_button_timer = 1;
caps.has_button_vformat = 0;
caps.has_HDMI = 1;
@@ -102,12 +186,14 @@ hw_caps_t *get_hwcaps(void)
initialized = 1;
caps.has_CI = 0;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 4;
caps.display_type = HW_DISPLAY_LED_NUM;
caps.display_can_deepstandby = 0;
caps.display_can_set_brightness = 1;
caps.display_has_statusline = 0;
caps.display_has_colon = 1;
caps.has_button_timer = 1;
caps.has_button_vformat = 0;
caps.has_HDMI = 1;
@@ -115,16 +201,34 @@ hw_caps_t *get_hwcaps(void)
strcpy(caps.boxname, "HD60");
strcpy(caps.boxarch, "HI3798M");
#endif
#if BOXMODEL_HD61
initialized = 1;
caps.has_CI = 2;
caps.can_cec = 1;
caps.can_shutdown = 1;
caps.display_xres = 4;
caps.display_type = HW_DISPLAY_LED_NUM;
caps.display_can_deepstandby = 0;
caps.display_can_set_brightness = 1;
caps.display_has_statusline = 0;
caps.has_button_timer = 1;
caps.has_HDMI = 1;
strcpy(caps.boxvendor, "AX-Technologies");
strcpy(caps.boxname, "HD61");
strcpy(caps.boxarch, "HI3798M");
#endif
#if BOXMODEL_BRE2ZE4K
initialized = 1;
caps.has_CI = 1;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 5;
caps.display_type = HW_DISPLAY_LINE_TEXT;
caps.display_xres = 4;
caps.display_type = HW_DISPLAY_LED_NUM;
caps.display_can_deepstandby = 0;
caps.display_can_set_brightness = 1;
caps.display_has_statusline = 1;
caps.display_has_statusline = 0;
caps.display_has_colon = 1;
caps.has_button_timer = 1;
caps.has_button_vformat = 1;
caps.has_HDMI = 1;
@@ -136,18 +240,59 @@ hw_caps_t *get_hwcaps(void)
initialized = 1;
caps.has_CI = 1;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 5;
caps.display_type = HW_DISPLAY_LINE_TEXT;
caps.display_xres = 4;
caps.display_type = HW_DISPLAY_LED_NUM;
caps.display_can_deepstandby = 0;
caps.display_can_set_brightness = 1;
caps.display_has_statusline = 0;
caps.display_has_colon = 1;
caps.has_button_timer = 1;
caps.has_button_vformat = 0;
caps.has_HDMI = 1;
strcpy(caps.boxvendor, "AirDigital");
strcpy(caps.boxname, "Zgemma H7C/S");
strcpy(caps.boxarch, "BCM7251S");
#endif
#if BOXMODEL_OSMIO4K
initialized = 1;
caps.has_CI = 0;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 4;
caps.display_type = HW_DISPLAY_LED_NUM;
caps.display_can_deepstandby = 0;
caps.display_can_set_brightness = 1;
caps.display_has_statusline = 1;
caps.display_has_colon = 1;
caps.has_button_timer = 1;
caps.has_button_vformat = 1;
caps.has_HDMI = 1;
strcpy(caps.boxvendor, "ZGEMMA");
strcpy(caps.boxname, "H7");
strcpy(caps.boxarch, "BCM7251S");
strcpy(caps.boxvendor, "Edision");
strcpy(caps.boxname, "OS mio 4K");
strcpy(caps.boxarch, "BCM72604");
#endif
#if BOXMODEL_OSMIO4KPLUS
initialized = 1;
caps.has_CI = 0;
caps.can_cec = 1;
caps.can_cpufreq = 0;
caps.can_shutdown = 1;
caps.display_xres = 128;
caps.display_yres = 64;
caps.display_type = HW_DISPLAY_GFX;
caps.display_can_deepstandby = 0; // 0 because we use graphlcd/lcd4linux
caps.display_can_set_brightness = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_statusline = 0; // 0 because we use graphlcd/lcd4linux
caps.display_has_colon = 0;
caps.has_button_timer = 1;
caps.has_button_vformat = 1;
caps.has_HDMI = 1;
strcpy(caps.boxvendor, "Edision");
strcpy(caps.boxname, "OS mio+ 4K");
strcpy(caps.boxarch, "BCM72604");
#endif
return &caps;
}

View File

@@ -1,5 +1,5 @@
/*
Copyright (C) 2018 TangoCash
Copyright (C) 2018-2020 TangoCash
License: GPLv2
@@ -20,7 +20,7 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/poll.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -28,6 +28,7 @@
#include <errno.h>
#include <ctype.h>
#include <array>
#include <cstring>
#include <cstdio>
#include <cstdlib>
@@ -40,8 +41,12 @@
#include "hal_debug.h"
#define RED "\x1B[31m"
#define GREEN "\x1B[32m"
#define NORMAL "\x1B[0m"
#define EPOLL_WAIT_TIMEOUT (-1)
#define EPOLL_MAX_EVENTS (1)
#define hal_debug(args...) _hal_debug(HAL_DEBUG_INIT, this, args)
#define hal_info(args...) _hal_info(HAL_DEBUG_INIT, this, args)
#define hal_debug_c(args...) _hal_debug(HAL_DEBUG_INIT, NULL, args)
@@ -59,8 +64,13 @@
_r; \
})
#define CEC_DEVICE "/dev/cec0"
#define CEC_FALLBACK_DEVICE "/dev/cec0"
#define CEC_HDMIDEV "/dev/hdmi_cec"
#if BOXMODEL_H7
#define RC_DEVICE "/dev/input/event2"
#else
#define RC_DEVICE "/dev/input/event1"
#endif
hdmi_cec * hdmi_cec::hdmi_cec_instance = NULL;
@@ -72,6 +82,9 @@ hdmi_cec::hdmi_cec()
standby_cec_activ = autoview_cec_activ = standby = muted = false;
hdmiFd = -1;
volume = 0;
fallback = false;
tv_off = true;
deviceType = CEC_LOG_ADDR_TYPE_UNREGISTERED;
}
hdmi_cec::~hdmi_cec()
@@ -88,7 +101,7 @@ hdmi_cec* hdmi_cec::getInstance()
if (hdmi_cec_instance == NULL)
{
hdmi_cec_instance = new hdmi_cec();
hal_debug_c("[CEC] new instance created \n");
hal_info_c(GREEN "[CEC] new instance created \n" NORMAL);
}
return hdmi_cec_instance;
}
@@ -102,88 +115,108 @@ bool hdmi_cec::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType)
if (_deviceType == VIDEO_HDMI_CEC_MODE_OFF)
{
Stop();
hal_debug("[CEC] switch off %s\n", __func__);
hal_info(GREEN "[CEC] switch off %s\n" NORMAL, __func__);
return false;
}
else
deviceType = _deviceType;
hal_debug("[CEC] switch on %s\n", __func__);
hal_info(GREEN "[CEC] switch on %s\n" NORMAL, __func__);
#if BOXMODEL_VUPLUS_ALL
if (hdmiFd == -1)
{
hdmiFd = ::open(CEC_HDMIDEV, O_RDWR | O_NONBLOCK | O_CLOEXEC);
if (hdmiFd >= 0)
{
::ioctl(hdmiFd, 0); /* flush old messages */
}
}
#endif
if (hdmiFd == -1)
{
hdmiFd = open(CEC_DEVICE, O_RDWR | O_CLOEXEC);
hdmiFd = open(CEC_FALLBACK_DEVICE, O_RDWR | O_CLOEXEC);
if (hdmiFd >= 0)
{
fallback = true;
#if BOXMODEL_VUPLUS_ALL
hal_info(RED "[CEC] fallback on %s\n" NORMAL, __func__);
#endif
__u32 monitor = CEC_MODE_INITIATOR | CEC_MODE_FOLLOWER;
struct cec_caps caps = {};
if (ioctl(hdmiFd, CEC_ADAP_G_CAPS, &caps) < 0)
hal_info(RED "[CEC] %s: get caps failed (%m)\n" NORMAL, __func__);
if (caps.capabilities & CEC_CAP_LOG_ADDRS)
{
struct cec_log_addrs laddrs = {};
if (ioctl(hdmiFd, CEC_ADAP_S_LOG_ADDRS, &laddrs) < 0)
hal_info(RED "[CEC] %s: reset log addr failed (%m)\n" NORMAL, __func__);
memset(&laddrs, 0, sizeof(laddrs));
/*
* NOTE: cec_version, osd_name and deviceType should be made configurable,
* CEC_ADAP_S_LOG_ADDRS delayed till the desired values are available
* (saves us some startup speed as well, polling for a free logical address
* takes some time)
*/
laddrs.cec_version = CEC_OP_CEC_VERSION_2_0;
strcpy(laddrs.osd_name, "neutrino");
laddrs.vendor_id = CEC_VENDOR_ID_NONE;
switch (deviceType)
{
case CEC_LOG_ADDR_TV:
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_TV;
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_TV;
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_TV;
break;
case CEC_LOG_ADDR_RECORD_1:
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_RECORD;
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_RECORD;
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_RECORD;
break;
case CEC_LOG_ADDR_TUNER_1:
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_TUNER;
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_TUNER;
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_TUNER;
break;
case CEC_LOG_ADDR_PLAYBACK_1:
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_PLAYBACK;
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_PLAYBACK;
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_PLAYBACK;
break;
case CEC_LOG_ADDR_AUDIOSYSTEM:
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_AUDIOSYSTEM;
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM;
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM;
break;
default:
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_UNREGISTERED;
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_SWITCH;
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_SWITCH;
break;
}
laddrs.num_log_addrs++;
if (ioctl(hdmiFd, CEC_ADAP_S_LOG_ADDRS, &laddrs) < 0)
hal_info(RED "[CEC] %s: et log addr failed (%m)\n" NORMAL, __func__);
}
if (ioctl(hdmiFd, CEC_S_MODE, &monitor) < 0)
hal_info(RED "[CEC] %s: monitor failed (%m)\n" NORMAL, __func__);
}
}
if (hdmiFd >= 0)
{
__u32 monitor = CEC_MODE_INITIATOR | CEC_MODE_FOLLOWER;
struct cec_caps caps = {};
if (ioctl(hdmiFd, CEC_ADAP_G_CAPS, &caps) < 0)
hal_debug("[CEC] %s: get caps failed (%m)\n", __func__);
if (caps.capabilities & CEC_CAP_LOG_ADDRS)
{
struct cec_log_addrs laddrs = {};
if (ioctl(hdmiFd, CEC_ADAP_S_LOG_ADDRS, &laddrs) < 0)
hal_debug("[CEC] %s: reset log addr failed (%m)\n", __func__);
memset(&laddrs, 0, sizeof(laddrs));
/*
* NOTE: cec_version, osd_name and deviceType should be made configurable,
* CEC_ADAP_S_LOG_ADDRS delayed till the desired values are available
* (saves us some startup speed as well, polling for a free logical address
* takes some time)
*/
laddrs.cec_version = CEC_OP_CEC_VERSION_2_0;
strcpy(laddrs.osd_name, "neutrino");
laddrs.vendor_id = CEC_VENDOR_ID_NONE;
switch (deviceType)
{
case CEC_LOG_ADDR_TV:
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_TV;
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_TV;
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_TV;
break;
case CEC_LOG_ADDR_RECORD_1:
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_RECORD;
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_RECORD;
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_RECORD;
break;
case CEC_LOG_ADDR_TUNER_1:
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_TUNER;
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_TUNER;
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_TUNER;
break;
case CEC_LOG_ADDR_PLAYBACK_1:
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_PLAYBACK;
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_PLAYBACK;
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_PLAYBACK;
break;
case CEC_LOG_ADDR_AUDIOSYSTEM:
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_AUDIOSYSTEM;
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM;
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM;
break;
default:
laddrs.log_addr_type[laddrs.num_log_addrs] = CEC_LOG_ADDR_TYPE_UNREGISTERED;
laddrs.all_device_types[laddrs.num_log_addrs] = CEC_OP_ALL_DEVTYPE_SWITCH;
laddrs.primary_device_type[laddrs.num_log_addrs] = CEC_OP_PRIM_DEVTYPE_SWITCH;
break;
}
laddrs.num_log_addrs++;
if (ioctl(hdmiFd, CEC_ADAP_S_LOG_ADDRS, &laddrs) < 0)
hal_debug("[CEC] %s: et log addr failed (%m)\n", __func__);
}
if (ioctl(hdmiFd, CEC_S_MODE, &monitor) < 0)
hal_debug("[CEC] %s: monitor failed (%m)\n", __func__);
GetCECAddressInfo();
if(autoview_cec_activ)
@@ -200,48 +233,62 @@ void hdmi_cec::GetCECAddressInfo()
{
if (hdmiFd >= 0)
{
bool hasdata = false;
struct addressinfo addressinfo;
__u16 phys_addr;
struct cec_log_addrs laddrs = {};
::ioctl(hdmiFd, CEC_ADAP_G_PHYS_ADDR, &phys_addr);
addressinfo.physical[0] = (phys_addr >> 8) & 0xff;
addressinfo.physical[1] = phys_addr & 0xff;
::ioctl(hdmiFd, CEC_ADAP_G_LOG_ADDRS, &laddrs);
addressinfo.logical = laddrs.log_addr[0];
switch (laddrs.log_addr_type[0])
if (fallback)
{
case CEC_LOG_ADDR_TYPE_TV:
addressinfo.type = CEC_LOG_ADDR_TV;
break;
case CEC_LOG_ADDR_TYPE_RECORD:
addressinfo.type = CEC_LOG_ADDR_RECORD_1;
break;
case CEC_LOG_ADDR_TYPE_TUNER:
addressinfo.type = CEC_LOG_ADDR_TUNER_1;
break;
case CEC_LOG_ADDR_TYPE_PLAYBACK:
addressinfo.type = CEC_LOG_ADDR_PLAYBACK_1;
break;
case CEC_LOG_ADDR_TYPE_AUDIOSYSTEM:
addressinfo.type = CEC_LOG_ADDR_AUDIOSYSTEM;
break;
case CEC_LOG_ADDR_TYPE_UNREGISTERED:
default:
addressinfo.type = CEC_LOG_ADDR_UNREGISTERED;
break;
__u16 phys_addr;
struct cec_log_addrs laddrs = {};
::ioctl(hdmiFd, CEC_ADAP_G_PHYS_ADDR, &phys_addr);
addressinfo.physical[0] = (phys_addr >> 8) & 0xff;
addressinfo.physical[1] = phys_addr & 0xff;
::ioctl(hdmiFd, CEC_ADAP_G_LOG_ADDRS, &laddrs);
addressinfo.logical = laddrs.log_addr[0];
switch (laddrs.log_addr_type[0])
{
case CEC_LOG_ADDR_TYPE_TV:
addressinfo.type = CEC_LOG_ADDR_TV;
break;
case CEC_LOG_ADDR_TYPE_RECORD:
addressinfo.type = CEC_LOG_ADDR_RECORD_1;
break;
case CEC_LOG_ADDR_TYPE_TUNER:
addressinfo.type = CEC_LOG_ADDR_TUNER_1;
break;
case CEC_LOG_ADDR_TYPE_PLAYBACK:
addressinfo.type = CEC_LOG_ADDR_PLAYBACK_1;
break;
case CEC_LOG_ADDR_TYPE_AUDIOSYSTEM:
addressinfo.type = CEC_LOG_ADDR_AUDIOSYSTEM;
break;
case CEC_LOG_ADDR_TYPE_UNREGISTERED:
default:
addressinfo.type = CEC_LOG_ADDR_UNREGISTERED;
break;
}
hasdata = true;
}
deviceType = addressinfo.type;
logicalAddress = addressinfo.logical;
if (memcmp(physicalAddress, addressinfo.physical, sizeof(physicalAddress)))
else
{
hal_info("[CEC] %s: detected physical address change: %02X%02X --> %02X%02X\n", __func__, physicalAddress[0], physicalAddress[1], addressinfo.physical[0], addressinfo.physical[1]);
memcpy(physicalAddress, addressinfo.physical, sizeof(physicalAddress));
ReportPhysicalAddress();
if (::ioctl(hdmiFd, 1, &addressinfo) >= 0)
{
hasdata = true;
}
}
if (hasdata)
{
deviceType = addressinfo.type;
logicalAddress = addressinfo.logical;
if (memcmp(physicalAddress, addressinfo.physical, sizeof(physicalAddress)))
{
hal_info(GREEN "[CEC] %s: detected physical address change: %02X%02X --> %02X%02X\n" NORMAL, __func__, physicalAddress[0], physicalAddress[1], addressinfo.physical[0], addressinfo.physical[1]);
memcpy(physicalAddress, addressinfo.physical, sizeof(physicalAddress));
ReportPhysicalAddress();
}
}
}
}
@@ -259,21 +306,36 @@ void hdmi_cec::ReportPhysicalAddress()
SendCECMessage(txmessage);
}
void hdmi_cec::SendCECMessage(struct cec_message &txmessage)
void hdmi_cec::SendCECMessage(struct cec_message &txmessage, int sleeptime)
{
if (hdmiFd >= 0)
{
char str[txmessage.length*6];
for (int i = 0; i < txmessage.length; i++)
{
sprintf(str+(i*6),"[0x%02X]", txmessage.data[i]);
}
hal_info("[CEC] send message %s to %s (0x%02X>>0x%02X) '%s' (%s)\n",ToString((cec_logical_address)txmessage.initiator), txmessage.destination == 0xf ? "all" : ToString((cec_logical_address)txmessage.destination), txmessage.initiator, txmessage.destination, ToString((cec_opcode)txmessage.data[0]), str);
struct cec_msg msg;
cec_msg_init(&msg, txmessage.initiator, txmessage.destination);
memcpy(&msg.msg[1], txmessage.data, txmessage.length);
msg.len = txmessage.length + 1;
ioctl(hdmiFd, CEC_TRANSMIT, &msg);
hal_info(GREEN "[CEC] send message %s to %s (0x%02X>>0x%02X) '%s' (%s)\n" NORMAL,ToString((cec_logical_address)txmessage.initiator), txmessage.destination == 0xf ? "all" : ToString((cec_logical_address)txmessage.destination), txmessage.initiator, txmessage.destination, ToString((cec_opcode)txmessage.data[0]), str);
if (fallback)
{
struct cec_msg msg;
cec_msg_init(&msg, txmessage.initiator, txmessage.destination);
memcpy(&msg.msg[1], txmessage.data, txmessage.length);
msg.len = txmessage.length + 1;
ioctl(hdmiFd, CEC_TRANSMIT, &msg);
}
else
{
struct cec_message_fb message;
message.address = txmessage.destination;
message.length = txmessage.length;
memcpy(&message.data, txmessage.data, txmessage.length);
::write(hdmiFd, &message, 2 + message.length);
}
usleep(sleeptime * 10000);
}
}
@@ -300,23 +362,51 @@ void hdmi_cec::SetCECState(bool state)
message.data[0] = CEC_MSG_STANDBY;
message.length = 1;
SendCECMessage(message);
message.initiator = logicalAddress;
message.destination = CEC_OP_PRIM_DEVTYPE_TV;
message.data[0] = CEC_MSG_GIVE_DEVICE_POWER_STATUS;
message.length = 1;
SendCECMessage(message);
}
if ((autoview_cec_activ) && !state)
{
message.initiator = logicalAddress;
message.destination = CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM;
message.data[0] = CEC_MSG_GIVE_SYSTEM_AUDIO_MODE_STATUS;
message.destination = CEC_OP_PRIM_DEVTYPE_TV;
message.data[0] = CEC_MSG_GET_CEC_VERSION;
message.length = 1;
SendCECMessage(message);
usleep(10000);
message.initiator = logicalAddress;
message.destination = CEC_OP_PRIM_DEVTYPE_TV;
message.data[0] = CEC_MSG_IMAGE_VIEW_ON;
message.data[0] = CEC_MSG_GIVE_DEVICE_POWER_STATUS;
message.length = 1;
SendCECMessage(message);
usleep(10000);
#if BOXMODEL_VUPLUS_ALL
int cnt = 0;
while (tv_off && (cnt < 5))
{
#endif
message.initiator = logicalAddress;
message.destination = CEC_OP_PRIM_DEVTYPE_TV;
message.data[0] = CEC_MSG_IMAGE_VIEW_ON;
message.length = 1;
SendCECMessage(message);
message.initiator = logicalAddress;
message.destination = CEC_OP_PRIM_DEVTYPE_TV;
message.data[0] = CEC_MSG_GIVE_DEVICE_POWER_STATUS;
message.length = 1;
SendCECMessage(message);
#if BOXMODEL_VUPLUS_ALL
cnt++;
}
#endif
message.initiator = logicalAddress;
message.destination = CEC_LOG_ADDR_BROADCAST;
@@ -325,7 +415,20 @@ void hdmi_cec::SetCECState(bool state)
message.data[2] = physicalAddress[1];
message.length = 3;
SendCECMessage(message);
usleep(10000);
message.initiator = logicalAddress;
message.destination = CEC_LOG_ADDR_BROADCAST;
message.data[0] = CEC_OPCODE_SET_OSD_NAME;
message.data[1] = 0x6e; //n
message.data[2] = 0x65; //e
message.data[3] = 0x75; //u
message.data[4] = 0x74; //t
message.data[5] = 0x72; //r
message.data[6] = 0x69; //i
message.data[7] = 0x6e; //n
message.data[8] = 0x6f; //o
message.length = 9;
SendCECMessage(message);
request_audio_status();
}
@@ -458,6 +561,7 @@ bool hdmi_cec::Start()
return false;
running = true;
OpenThreads::Thread::setSchedulePriority(THREAD_PRIORITY_MIN);
return (OpenThreads::Thread::start() == 0);
}
@@ -467,7 +571,7 @@ bool hdmi_cec::Stop()
return false;
running = false;
OpenThreads::Thread::cancel();
if (hdmiFd >= 0)
@@ -482,90 +586,154 @@ bool hdmi_cec::Stop()
void hdmi_cec::run()
{
OpenThreads::Thread::setCancelModeAsynchronous();
struct pollfd pfd;
int n;
int epollfd = epoll_create1(0);
struct epoll_event event;
event.data.fd = hdmiFd;
event.events = EPOLLIN;
pfd.fd = hdmiFd;
pfd.events = (POLLIN | POLLPRI);
epoll_ctl(epollfd, EPOLL_CTL_ADD, hdmiFd, &event);
std::array<struct epoll_event, EPOLL_MAX_EVENTS> events;
while (running)
{
if (poll(&pfd, 1, 0) > 0)
Receive();
n = epoll_wait(epollfd, events.data(), EPOLL_MAX_EVENTS, EPOLL_WAIT_TIMEOUT);
for (int i = 0; i < n; ++i)
{
if (events[i].events & EPOLLIN)
Receive(events[i].events);
}
}
}
void hdmi_cec::Receive()
void hdmi_cec::Receive(int what)
{
bool hasdata = false;
struct cec_message rxmessage;
struct cec_message txmessage;
struct cec_msg msg;
if (::ioctl(hdmiFd, CEC_RECEIVE, &msg) >= 0)
if (what & EPOLLIN)
{
rxmessage.length = msg.len - 1;
rxmessage.initiator = cec_msg_initiator(&msg);
rxmessage.destination = cec_msg_destination(&msg);
rxmessage.opcode = cec_msg_opcode(&msg);
memcpy(&rxmessage.data, &msg.msg[1], rxmessage.length);
hasdata = true;
}
if (hasdata)
{
bool keypressed = false;
static unsigned char pressedkey = 0;
bool hasdata = false;
struct cec_message rxmessage;
struct cec_message txmessage;
char str[rxmessage.length*6];
for (int i = 0; i < rxmessage.length; i++)
if (fallback)
{
sprintf(str+(i*6),"[0x%02X]", rxmessage.data[i]);
struct cec_msg msg;
if (::ioctl(hdmiFd, CEC_RECEIVE, &msg) >= 0)
{
rxmessage.length = msg.len - 1;
rxmessage.initiator = cec_msg_initiator(&msg);
rxmessage.destination = cec_msg_destination(&msg);
rxmessage.opcode = cec_msg_opcode(&msg);
memcpy(&rxmessage.data, &msg.msg[1], rxmessage.length);
hasdata = true;
}
}
else
{
struct cec_message_fb rx_message;
if (::read(hdmiFd, &rx_message, 2) == 2)
{
if (::read(hdmiFd, &rx_message.data, rx_message.length) == rx_message.length)
{
rxmessage.length = rx_message.length;
rxmessage.initiator = rx_message.address;
rxmessage.destination = logicalAddress;
rxmessage.opcode = rx_message.data[0];
memcpy(&rxmessage.data, rx_message.data, rx_message.length);
hasdata = true;
}
}
}
hal_info("[CEC] received message %s to %s (0x%02X>>0x%02X) '%s' (%s)\n",ToString((cec_logical_address)rxmessage.initiator), rxmessage.destination == 0xf ? "all" : ToString((cec_logical_address)rxmessage.destination), rxmessage.initiator, rxmessage.destination, ToString((cec_opcode)rxmessage.opcode), str);
switch (rxmessage.opcode)
if (hasdata)
{
case CEC_OPCODE_REPORT_AUDIO_STATUS:
{
muted = ((rxmessage.data[1] & 0x80) == 0x80);
volume = ((rxmessage.data[1] & 0x7F) / 127.0) * 100.0;
if (muted)
hal_debug("[CEC] %s volume muted\n", ToString((cec_logical_address)rxmessage.initiator));
else
hal_debug("[CEC] %s volume %d \n", ToString((cec_logical_address)rxmessage.initiator), volume);
break;
}
case CEC_OPCODE_DEVICE_VENDOR_ID:
case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
{
uint64_t iVendorId = ((uint64_t)rxmessage.data[1] << 16) +
((uint64_t)rxmessage.data[2] << 8) +
(uint64_t)rxmessage.data[3];
hal_debug("[CEC] decoded message '%s' (%s)\n", ToString((cec_opcode)rxmessage.opcode), ToString((cec_vendor_id)iVendorId));
break;
}
case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
{
txmessage.destination = rxmessage.initiator;
txmessage.initiator = rxmessage.destination;
txmessage.data[0] = GetResponseOpcode((cec_opcode)rxmessage.opcode);
txmessage.data[1] = standby ? CEC_POWER_STATUS_STANDBY : CEC_POWER_STATUS_ON;
txmessage.length = 2;
SendCECMessage(txmessage);
break;
}
case CEC_OPCODE_USER_CONTROL_PRESSED: /* key pressed */
{
keypressed = true;
pressedkey = rxmessage.data[1];
} // fall through
case CEC_OPCODE_USER_CONTROL_RELEASE: /* key released */
{
long code = translateKey(pressedkey);
hal_debug("[CEC] decoded key %s (%ld)\n",ToString((cec_user_control_code)pressedkey), code);
handleCode(code,keypressed);
break;
}
bool keypressed = false;
static unsigned char pressedkey = 0;
char str[rxmessage.length*6];
for (int i = 0; i < rxmessage.length; i++)
{
sprintf(str+(i*6),"[0x%02X]", rxmessage.data[i]);
}
hal_info(GREEN "[CEC] received message %s to %s (0x%02X>>0x%02X) '%s' (%s)\n" NORMAL,ToString((cec_logical_address)rxmessage.initiator), rxmessage.destination == 0xf ? "all" : ToString((cec_logical_address)rxmessage.destination), rxmessage.initiator, rxmessage.destination, ToString((cec_opcode)rxmessage.opcode), str);
switch (rxmessage.opcode)
{
//case CEC_OPCODE_ACTIVE_SOURCE:
case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
{
txmessage.destination = CEC_LOG_ADDR_BROADCAST; //rxmessage.initiator;
txmessage.initiator = logicalAddress; //rxmessage.destination;
txmessage.data[0] = CEC_MSG_ACTIVE_SOURCE;
txmessage.data[1] = physicalAddress[0];
txmessage.data[2] = physicalAddress[1];
txmessage.length = 3;
if (!standby)
SendCECMessage(txmessage);
}
case CEC_OPCODE_REPORT_AUDIO_STATUS:
{
muted = ((rxmessage.data[1] & 0x80) == 0x80);
volume = ((rxmessage.data[1] & 0x7F) / 127.0) * 100.0;
if (muted)
hal_info(GREEN "[CEC] %s volume muted\n" NORMAL, ToString((cec_logical_address)rxmessage.initiator));
else
hal_info(GREEN "[CEC] %s volume %d \n" NORMAL, ToString((cec_logical_address)rxmessage.initiator), volume);
break;
}
case CEC_OPCODE_DEVICE_VENDOR_ID:
case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
{
uint64_t iVendorId = ((uint64_t)rxmessage.data[1] << 16) +
((uint64_t)rxmessage.data[2] << 8) +
(uint64_t)rxmessage.data[3];
hal_info(GREEN "[CEC] decoded message '%s' (%s)\n" NORMAL, ToString((cec_opcode)rxmessage.opcode), ToString((cec_vendor_id)iVendorId));
break;
}
case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
{
txmessage.destination = rxmessage.initiator;
txmessage.initiator = rxmessage.destination;
txmessage.data[0] = GetResponseOpcode((cec_opcode)rxmessage.opcode);
txmessage.data[1] = standby ? CEC_POWER_STATUS_STANDBY : CEC_POWER_STATUS_ON;
txmessage.length = 2;
SendCECMessage(txmessage);
break;
}
case CEC_OPCODE_REPORT_POWER_STATUS:
{
if ((rxmessage.data[1] == CEC_POWER_STATUS_ON) || (rxmessage.data[1] == CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON))
{
hal_info(GREEN "[CEC] %s reporting state on (%d)\n" NORMAL, ToString((cec_logical_address)rxmessage.initiator), rxmessage.data[1]);
if (rxmessage.initiator == CEC_OP_PRIM_DEVTYPE_TV)
tv_off = false;
} else {
hal_info(GREEN "[CEC] %s reporting state off (%d)\n" NORMAL, ToString((cec_logical_address)rxmessage.initiator), rxmessage.data[1]);
if (rxmessage.initiator == CEC_OP_PRIM_DEVTYPE_TV)
tv_off = true;
}
break;
}
case CEC_OPCODE_STANDBY:
{
if (rxmessage.initiator == CEC_OP_PRIM_DEVTYPE_TV)
tv_off = true;
break;
}
case CEC_OPCODE_USER_CONTROL_PRESSED: /* key pressed */
{
keypressed = true;
pressedkey = rxmessage.data[1];
} // fall through
case CEC_OPCODE_USER_CONTROL_RELEASE: /* key released */
{
long code = translateKey(pressedkey);
hal_info(GREEN "[CEC] decoded key %s (%ld)\n" NORMAL,ToString((cec_user_control_code)pressedkey), code);
handleCode(code,keypressed);
break;
}
}
}
}
}
@@ -575,14 +743,14 @@ void hdmi_cec::handleCode(long code, bool keypressed)
int evd = open(RC_DEVICE, O_RDWR);
if (evd < 0)
{
hal_debug("[CEC] opening " RC_DEVICE " failed");
hal_info(RED "[CEC] opening " RC_DEVICE " failed" NORMAL);
return;
}
if (keypressed)
{
if (rc_send(evd, code, CEC_KEY_PRESSED) < 0)
{
hal_debug("[CEC] writing 'KEY_PRESSED' event failed");
hal_info(RED "[CEC] writing 'KEY_PRESSED' event failed" NORMAL);
close(evd);
return;
}
@@ -592,7 +760,7 @@ void hdmi_cec::handleCode(long code, bool keypressed)
{
if (rc_send(evd, code, CEC_KEY_RELEASED) < 0)
{
hal_debug("[CEC] writing 'KEY_RELEASED' event failed");
hal_info(RED "[CEC] writing 'KEY_RELEASED' event failed" NORMAL);
close(evd);
return;
}
@@ -630,14 +798,13 @@ void hdmi_cec::send_key(unsigned char key, unsigned char destination)
txmessage.data[0] = CEC_OPCODE_USER_CONTROL_PRESSED;
txmessage.data[1] = key;
txmessage.length = 2;
SendCECMessage(txmessage);
usleep(10000);
SendCECMessage(txmessage, 1);
txmessage.destination = destination;
txmessage.initiator = logicalAddress;
txmessage.data[0] = CEC_OPCODE_USER_CONTROL_RELEASE;
txmessage.length = 1;
SendCECMessage(txmessage);
SendCECMessage(txmessage, 0);
}
void hdmi_cec::request_audio_status()
@@ -647,24 +814,21 @@ void hdmi_cec::request_audio_status()
txmessage.initiator = logicalAddress;
txmessage.data[0] = CEC_OPCODE_GIVE_AUDIO_STATUS;
txmessage.length = 1;
SendCECMessage(txmessage);
SendCECMessage(txmessage, 0);
}
void hdmi_cec::vol_up()
{
send_key(CEC_USER_CONTROL_CODE_VOLUME_UP, CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM);
usleep(50000);
request_audio_status();
}
void hdmi_cec::vol_down()
{
send_key(CEC_USER_CONTROL_CODE_VOLUME_DOWN, CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM);
usleep(50000);
request_audio_status();
}
void hdmi_cec::toggle_mute()
{
send_key(CEC_USER_CONTROL_CODE_MUTE, CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM);
usleep(50000);
request_audio_status();
}

View File

@@ -2,7 +2,7 @@
#define __HDMI_CEC_H__
/*
Copyright (C) 2018 TangoCash
Copyright (C) 2018-2020 TangoCash
License: GPLv2
@@ -34,6 +34,13 @@ struct cec_message
unsigned char length;
} __attribute__((packed));
struct cec_message_fb
{
unsigned char address;
unsigned char length;
unsigned char data[256];
} __attribute__((packed));
struct addressinfo
{
unsigned char logical;
@@ -56,7 +63,7 @@ private:
void run();
bool Start();
bool Stop();
void Receive();
void Receive(int what);
unsigned char physicalAddress[2];
bool autoview_cec_activ;
unsigned char deviceType, logicalAddress;
@@ -70,6 +77,8 @@ private:
void request_audio_status();
bool muted;
int volume;
bool fallback;
bool tv_off;
protected:
bool running;
public:
@@ -79,7 +88,7 @@ public:
void SetCECAutoView(bool);
void SetCECAutoStandby(bool);
void GetCECAddressInfo();
void SendCECMessage(struct cec_message &message);
void SendCECMessage(struct cec_message &message, int sleeptime = 10);
void SetCECState(bool state);
void ReportPhysicalAddress();
bool standby_cec_activ;

View File

@@ -38,9 +38,9 @@ void hal_api_init()
proc_put("/proc/stb/fb/dst_width", buffer, strlen(buffer));
sprintf(buffer, "%x", 1);
proc_put("/proc/stb/fb/dst_apply", buffer, strlen(buffer));
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K
const char mode_fcc[] = { "enable" };
proc_put("/proc/stb/frontend/fbc/fcc", mode_fcc, strlen(mode_fcc));
#if BOXMODEL_VUSOLO4K || BOXMODEL_VUDUO4K || BOXMODEL_VUDUO4KSE || BOXMODEL_VUULTIMO4K || BOXMODEL_VUUNO4KSE || BOXMODEL_VUUNO4K
sprintf(buffer, "%s", "enable");
proc_put("/proc/stb/frontend/fbc/fcc", buffer, strlen(buffer));
#endif
}
initialized = true;

View File

@@ -45,6 +45,28 @@
extern cAudio *audioDecoder;
extern cVideo *videoDecoder;
/* dummy functions */
bool cPlayback::SelectSubtitles(int /*pid*/, std::string /*charset*/)
{
return false;
}
void cPlayback::FindAllSubs(short unsigned int * /*pids*/, short unsigned int * /*supp*/, short unsigned int *num, std::string * /*lang*/)
{
*num = 0;
}
void cPlayback::SetTitle(int /*title*/)
{
}
void cPlayback::GetTitles(std::vector<int> &playlists, std::vector<std::string> &titles, int &current)
{
playlists.clear();
titles.clear();
current = 0;
}
//Used by Fileplay
bool cPlayback::Open(playmode_t PlayMode)
{
@@ -76,12 +98,12 @@ void cPlayback::Close(void)
}
bool cPlayback::Start(std::string filename, std::string headers)
bool cPlayback::Start(std::string filename, std::string headers, std::string filename2)
{
return Start((char *) filename.c_str(), 0, 0, 0, 0, 0, headers);
return Start((char *) filename.c_str(), 0, 0, 0, 0, 0, headers,filename2);
}
bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, int, std::string headers __attribute__((unused)))
bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, int, std::string headers __attribute__((unused)), std::string filename2 __attribute__((unused)))
{
bool ret = false;
@@ -417,7 +439,7 @@ bool cPlayback::SetPosition(int position, bool absolute)
return true;
}
void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *numpida, std::string *language)
void cPlayback::FindAllPids(short unsigned int *apids, short unsigned int *ac3flags, short unsigned int *numpida, std::string *language)
{
hal_info("%s\n", __func__);
int max_numpida = *numpida;

View File

@@ -77,8 +77,8 @@ public:
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 Start(char *filename, int vpid, int vtype, int apid, int ac3, int duration, std::string headers = "", std::string filename2 = "");
bool Start(std::string filename, std::string headers = "", std::string filename2 = "");
bool SetAPid(int pid, bool ac3 = false);
bool SetVPid(int /*pid*/);
bool SetSubtitlePid(int pid);
@@ -101,9 +101,11 @@ public:
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 FindAllPids(short unsigned int *apids, short unsigned int *ac3flags, short 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 FindAllSubs(short unsigned int *pids, short unsigned int *supported, short unsigned int *numpida, std::string *language);
bool SelectSubtitles(int pid, std::string charset = "");
void RequestAbort(void);
bool IsPlaying(void);
uint64_t GetReadCount(void);
@@ -113,6 +115,8 @@ public:
AVFormatContext *GetAVFormatContext();
void ReleaseAVFormatContext();
void GetTitles(std::vector<int> &playlists, std::vector<std::string> &titles, int &current);
void SetTitle(int title);
};
class netlink_event : public OpenThreads::Thread

View File

@@ -4,15 +4,19 @@
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sstream>
#include <audio_lib.h>
#include <video_lib.h>
extern "C" {
#include <common.h>
extern OutputHandler_t OutputHandler;
extern PlaybackHandler_t PlaybackHandler;
extern ContainerHandler_t ContainerHandler;
extern ManagerHandler_t ManagerHandler;
extern int32_t ffmpeg_av_dict_set( const char *key, const char *value, int32_t flags);
}
#include "playback_libeplayer3.h"
#include "hal_debug.h"
@@ -50,16 +54,12 @@ bool cPlayback::Open(playmode_t PlayMode)
last_size = 0;
nPlaybackSpeed = 0;
init_jump = -1;
avft = avformat_alloc_context();
mutex.lock();
if (player)
if (!player)
{
free(player);
player = NULL;
player = (Context_t *) malloc(sizeof(Context_t));
}
mutex.unlock();
player = (Context_t *) malloc(sizeof(Context_t));
if (player)
{
@@ -100,12 +100,12 @@ void cPlayback::Close(void)
}
}
bool cPlayback::Start(std::string filename, std::string headers)
bool cPlayback::Start(std::string filename, std::string headers, std::string filename2)
{
return Start((char *) filename.c_str(), 0, 0, 0, 0, 0, headers);
return Start((char *) filename.c_str(), 0, 0, 0, 0, 0, headers,filename2);
}
bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, int, std::string headers __attribute__((unused)))
bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, int, std::string headers, std::string filename2)
{
bool ret = false;
bool isHTTP = false;
@@ -118,7 +118,6 @@ bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, in
mAudioStream = 0;
mSubtitleStream = -1;
mTeletextStream = -1;
unlink("/tmp/.id3coverart");
std::string file;
if (*filename == '/')
@@ -141,7 +140,30 @@ bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, in
else
isHTTP = true;
PlayFiles_t playbackFiles = { (char *) file.c_str(), NULL, NULL, NULL, 0, 0, 0, 0};
if(isHTTP && headers.empty())
{
size_t pos = file.find('#');
if (pos != std::string::npos)
{
headers = file.substr(pos + 1);
pos = headers.find("User-Agent=");
if (pos != std::string::npos)
headers.replace(pos+10, 1, ": ");
}
}
if(!headers.empty()){
const char hkey[] = "headers";
ffmpeg_av_dict_set(hkey, headers.c_str(), 0);
}
std::string szSecondFile;
char *file2 = NULL;
if(!filename2.empty()){
szSecondFile = filename2;
file2 = (char *) szSecondFile.c_str();
}
PlayFiles_t playbackFiles = { (char *) file.c_str(), file2, NULL, NULL, 0, 0, 0, 0};
if (player->playback->Command(player, PLAYBACK_OPEN, &playbackFiles) == 0)
{
if (pm == PLAYMODE_TS)
@@ -342,6 +364,11 @@ bool cPlayback::SetSpeed(int speed)
if (player && player->playback)
{
int result = 0;
if(nPlaybackSpeed == 0 && speed > 1)
{
result = player->playback->Command(player, PLAYBACK_CONTINUE, NULL);
}
nPlaybackSpeed = speed;
if (speed > 1)
@@ -383,7 +410,7 @@ bool cPlayback::SetSpeed(int speed)
if (init_jump > -1)
{
SetPosition(init_jump);
SetPosition(init_jump, true);
init_jump = -1;
}
@@ -515,13 +542,13 @@ bool cPlayback::SetPosition(int position, bool absolute)
return true;
}
void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *numpida, std::string *language)
void cPlayback::FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t *numpida, std::string *language)
{
hal_info("%s\n", __func__);
int max_numpida = *numpida;
const int max_numpida = 40;//MAX_PLAYBACK_PIDS defined in neutrino movieplayer.h
*numpida = 0;
if (player && player->manager && player->manager->audio)
if (player && player->playback && player->playback->isPlaying && player->manager && player->manager->audio)
{
char **TrackList = NULL;
player->manager->audio->Command(player, MANAGER_LIST, &TrackList);
@@ -534,9 +561,12 @@ void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *nu
printf("\t%s - %s\n", TrackList[i], TrackList[i + 1]);
if (j < max_numpida)
{
int _pid;
char _lang[strlen(TrackList[i])];
if (2 == sscanf(TrackList[i], "%d %s\n", &_pid, _lang))
int _pid = 0;
std::string _lang ;
std::istringstream iss(TrackList[i]) ;
iss >> _pid;
iss >> _lang;
if (_pid && !_lang.empty())
{
apids[j] = _pid;
// atUnknown, atMPEG, atMP3, atAC3, atDTS, atAAC, atPCM, atOGG, atFLAC
@@ -561,7 +591,7 @@ void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *nu
else
ac3flags[j] = 0; //todo
std::string _language = "";
_language += std::string(_lang);
_language += _lang;
_language += " - ";
_language += "(";
_language += TrackList[i + 1];
@@ -598,12 +628,15 @@ void cPlayback::FindAllSubtitlePids(int *pids, unsigned int *numpids, std::strin
printf("\t%s - %s\n", TrackList[i], TrackList[i + 1]);
if (j < max_numpids)
{
int _pid;
char _lang[strlen(TrackList[i])];
if (2 == sscanf(TrackList[i], "%d %s\n", &_pid, _lang))
int _pid = 0;
std::string _lang ;
std::istringstream iss(TrackList[i]) ;
iss >> _pid;
iss >> _lang;
if (_pid && !_lang.empty())
{
pids[j] = _pid;
language[j] = std::string(_lang);
language[j] = _lang;
}
}
free(TrackList[i]);
@@ -766,12 +799,14 @@ cPlayback::cPlayback(int num __attribute__((unused)))
playing = false;
decoders_closed = false;
first = false;
player = NULL;
}
cPlayback::~cPlayback()
{
hal_info("%s\n", __func__);
RequestAbort();
mutex.lock();
if (player)
{
@@ -821,11 +856,17 @@ uint64_t cPlayback::GetReadCount()
AVFormatContext *cPlayback::GetAVFormatContext()
{
return NULL;
if (player && player->container && player->container->selectedContainer)
{
player->container->selectedContainer->Command(player, CONTAINER_GET_AVFCONTEXT, avft);
}
return avft;
}
void cPlayback::ReleaseAVFormatContext()
{
avft->streams = NULL;
avft->nb_streams = NULL;
}
#if 0

View File

@@ -35,14 +35,15 @@ class cPlayback
std::string fn_xml;
off64_t last_size;
int init_jump;
AVFormatContext *avft;
public:
cPlayback(int num = 0);
~cPlayback();
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 Start(char *filename, int vpid, int vtype, int apid, int ac3, int duration, std::string headers = "", std::string filename2 = "");
bool Start(std::string filename, std::string headers = "", std::string filename2 = "");
bool SetAPid(int pid, bool ac3 = false);
bool SetVPid(int /*pid*/);
bool SetSubtitlePid(int pid);
@@ -56,8 +57,7 @@ class cPlayback
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 FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t *numpida, std::string *language) { FindAllPids((int*) apids, (unsigned int*) ac3flags, (unsigned int*) numpida, language); };
void FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t *numpida, std::string *language);
void FindAllSubs(int *pids, unsigned int *supported, unsigned int *numpida, std::string *language);
void FindAllSubs(uint16_t *pids, unsigned short *supported, uint16_t *numpida, std::string *language) { FindAllSubs((int*) pids, (unsigned int*) supported, (unsigned int*) numpida, language); };
bool SelectSubtitles(int pid, std::string charset = "");

View File

@@ -65,6 +65,13 @@ extern "C"
_r; \
})
#ifndef VIDEO_GET_SIZE
#define VIDEO_GET_SIZE _IOR('o', 55, video_size_t)
#endif
#ifndef VIDEO_GET_FRAME_RATE
#define VIDEO_GET_FRAME_RATE _IOR('o', 56, unsigned int)
#endif
cVideo * videoDecoder = NULL;
cVideo * pipDecoder = NULL;
@@ -74,46 +81,64 @@ static bool stillpicture = false;
static const char *VDEV[] = {
"/dev/dvb/adapter0/video0",
"/dev/dvb/adapter0/video1"
"/dev/dvb/adapter0/video1",
"/dev/dvb/adapter0/video2",
"/dev/dvb/adapter0/video3"
};
static const char *VMPEG_aspect[] = {
"/proc/stb/vmpeg/0/aspect",
"/proc/stb/vmpeg/1/aspect"
"/proc/stb/vmpeg/1/aspect",
"/proc/stb/vmpeg/2/aspect",
"/proc/stb/vmpeg/3/aspect"
};
static const char *VMPEG_xres[] = {
"/proc/stb/vmpeg/0/xres",
"/proc/stb/vmpeg/1/xres"
"/proc/stb/vmpeg/1/xres",
"/proc/stb/vmpeg/2/xres",
"/proc/stb/vmpeg/3/xres"
};
static const char *VMPEG_yres[] = {
"/proc/stb/vmpeg/0/yres",
"/proc/stb/vmpeg/1/yres"
"/proc/stb/vmpeg/1/yres",
"/proc/stb/vmpeg/2/yres",
"/proc/stb/vmpeg/3/yres"
};
static const char *VMPEG_dst_height[] = {
"/proc/stb/vmpeg/0/dst_height",
"/proc/stb/vmpeg/1/dst_height"
"/proc/stb/vmpeg/1/dst_height",
"/proc/stb/vmpeg/2/dst_height",
"/proc/stb/vmpeg/3/dst_height"
};
static const char *VMPEG_dst_width[] = {
"/proc/stb/vmpeg/0/dst_width",
"/proc/stb/vmpeg/1/dst_width"
"/proc/stb/vmpeg/1/dst_width",
"/proc/stb/vmpeg/2/dst_width",
"/proc/stb/vmpeg/3/dst_width"
};
static const char *VMPEG_dst_top[] = {
"/proc/stb/vmpeg/0/dst_top",
"/proc/stb/vmpeg/1/dst_top"
"/proc/stb/vmpeg/1/dst_top",
"/proc/stb/vmpeg/2/dst_top",
"/proc/stb/vmpeg/3/dst_top"
};
static const char *VMPEG_dst_left[] = {
"/proc/stb/vmpeg/0/dst_left",
"/proc/stb/vmpeg/1/dst_left"
"/proc/stb/vmpeg/1/dst_left",
"/proc/stb/vmpeg/2/dst_left",
"/proc/stb/vmpeg/3/dst_left"
};
static const char *VMPEG_framerate[] = {
"/proc/stb/vmpeg/0/framerate",
"/proc/stb/vmpeg/1/framerate"
"/proc/stb/vmpeg/1/framerate",
"/proc/stb/vmpeg/2/framerate",
"/proc/stb/vmpeg/3/framerate"
};
static const char *vid_modes[] = {
@@ -346,6 +371,7 @@ int image_to_mpeg2(const char *image_name, int fd)
av_packet_unref(&packet);
}
avcodec_close(codecContext);
av_free(codecContext);
}
avformat_close_input(&formatContext);
}
@@ -429,7 +455,11 @@ int cVideo::setAspectRatio(int aspect, int mode)
{
static const char *a[] = { "n/a", "4:3", "14:9", "16:9" };
// static const char *m[] = { "panscan", "letterbox", "bestfit", "nonlinear", "(unset)" };
#if BOXMODEL_OSMIO4K || BOXMODEL_OSMIO4KPLUS
static const char *m[] = { "letterbox", "panscan", "scale", "(unset)", "(unset)" };
#else
static const char *m[] = { "letterbox", "panscan", "bestfit", "nonlinear", "(unset)" };
#endif
int n;
int mo = (mode < 0||mode > 3) ? 4 : mode;
@@ -447,9 +477,13 @@ int cVideo::setAspectRatio(int aspect, int mode)
if (mode == -1)
return 0;
#if BOXMODEL_OSMIO4K || BOXMODEL_OSMIO4KPLUS
hal_debug("%s: /proc/stb/video/policy2 -> %s\n", __func__, m[mo]);
n = proc_put("/proc/stb/video/policy2", m[mo], strlen(m[mo]));
#else
hal_debug("%s: /proc/stb/video/policy -> %s\n", __func__, m[mo]);
n = proc_put("/proc/stb/video/policy", m[mo], strlen(m[mo]));
#endif
if (n < 0)
return 1;
return 0;
@@ -507,6 +541,9 @@ int cVideo::Start(void * /*PcrChannel*/, unsigned short /*PcrPid*/, unsigned sho
playstate = VIDEO_PLAYING;
fop(ioctl, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX);
int res = fop(ioctl, VIDEO_PLAY);
#if BOXMODEL_HISILICON
fop(ioctl, VIDEO_CONTINUE);
#endif
if (brightness > -1) {
SetControl(VIDEO_CONTROL_BRIGHTNESS, brightness);
brightness = -1;
@@ -635,7 +672,7 @@ void cVideo::SetVideoMode(analog_mode_t mode)
bool cVideo::ShowPicture(const char * fname)
{
bool ret = false;
hal_info("%s(%s)\n", __func__, fname);
hal_debug("%s(%s)\n", __func__, fname);
if (video_standby)
{
/* does not work and the driver does not seem to like it */
@@ -926,7 +963,7 @@ void cVideo::SetControl(int control, int value)
break;
case VIDEO_CONTROL_ZAPPING_MODE:
zapping_mode = value;
const char *mode_zapping[] = { "hold", "mute" };
const char *mode_zapping[] = { "mute", "hold", "mutetilllock", "holdtilllock"};
proc_put("/proc/stb/video/zapmode", mode_zapping[zapping_mode], strlen(mode_zapping[zapping_mode]));
break;
}

View File

@@ -1,18 +0,0 @@
noinst_LTLIBRARIES = libazbox.la
AM_CPPFLAGS = \
-I$(top_srcdir)/common \
-I$(top_srcdir)/include
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
AM_LDFLAGS = -lpthread
libazbox_la_SOURCES = \
hardware_caps.c \
dmx.cpp \
video.cpp \
audio.cpp \
init.cpp \
playback.cpp \
record.cpp

View File

@@ -1,398 +0,0 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#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 "hal_debug.h"
#define AUDIO_DEVICE "/dev/dvb/adapter0/audio0"
#define hal_debug(args...) _hal_debug(HAL_DEBUG_AUDIO, this, args)
#define hal_info(args...) _hal_info(HAL_DEBUG_AUDIO, this, args)
#include <linux/soundcard.h>
cAudio * audioDecoder = NULL;
cAudio::cAudio(void *, void *, void *)
{
fd = -1;
clipfd = -1;
mixer_fd = -1;
openDevice();
Muted = false;
}
cAudio::~cAudio(void)
{
closeDevice();
}
void cAudio::openDevice(void)
{
hal_debug("%s\n", __func__);
if (fd < 0)
{
if ((fd = open(AUDIO_DEVICE, O_RDONLY|O_CLOEXEC)) < 0)
hal_info("openDevice: open failed (%m)\n");
do_mute(true, false);
}
else
hal_info("openDevice: already open (fd = %d)\n", fd);
}
void cAudio::closeDevice(void)
{
hal_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;
}
int cAudio::do_mute(bool enable, bool remember)
{
hal_debug("%s(%d, %d)\n", __func__, enable, remember);
if (remember)
Muted = enable;
#if 0
/* does not work? */
if (ioctl(fd, AUDIO_SET_MUTE, enable) < 0 )
hal_info("%s: AUDIO_SET_MUTE failed (%m)\n", __func__);
#else
char s[2] = { 0, 0 };
s[0] = '0' + (int)enable;
proc_put("/proc/stb/audio/j1_mute", s, 2);
#endif
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)
{
hal_debug("%s(%d, %d)\n", __func__, left, right);
volume = (left + right) / 2;
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)
hal_info("%s: MIXER_WRITE(%d),%04x: %m\n", __func__, mixer_num, tmp);
return ret;
}
audio_mixer_t mixer;
mixer.volume_left = map_volume(left);
mixer.volume_right = map_volume(right);
if (ioctl(fd, AUDIO_SET_MIXER, &mixer) < 0)
hal_info("%s: AUDIO_SET_MIXER failed (%m)\n", __func__);
return 0;
}
int cAudio::Start(void)
{
hal_debug("%s\n", __func__);
int ret;
ioctl(fd, AUDIO_CONTINUE);
ret = ioctl(fd, AUDIO_PLAY);
return ret;
}
int cAudio::Stop(void)
{
hal_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 */
return 0;
}
bool cAudio::Pause(bool /*Pcm*/)
{
return true;
};
void cAudio::SetSyncMode(AVSYNC_TYPE Mode)
{
hal_debug("%s %d\n", __func__, Mode);
ioctl(fd, AUDIO_SET_AV_SYNC, Mode);
};
//AUDIO_ENCODING_AC3
#define AUDIO_STREAMTYPE_AC3 0
//AUDIO_ENCODING_MPEG2
#define AUDIO_STREAMTYPE_MPEG 1
//AUDIO_ENCODING_DTS
#define AUDIO_STREAMTYPE_DTS 2
#define AUDIO_ENCODING_LPCM 2
#define AUDIO_ENCODING_LPCMA 11
void cAudio::SetStreamType(AUDIO_FORMAT type)
{
int bypass = AUDIO_STREAMTYPE_MPEG;
hal_debug("%s %d\n", __func__, type);
StreamType = type;
switch (type)
{
case AUDIO_FMT_DOLBY_DIGITAL:
bypass = AUDIO_STREAMTYPE_AC3;
break;
case AUDIO_FMT_DTS:
bypass = AUDIO_STREAMTYPE_DTS;
break;
case AUDIO_FMT_MPEG:
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)
hal_info("%s: AUDIO_SET_BYPASS_MODE failed (%m)\n", __func__);
};
int cAudio::setChannel(int 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");
hal_debug("%s ch %d srate %d bits %d le %d\n", __FUNCTION__, ch, srate, bits, little_endian);
if (clipfd >= 0) {
hal_info("%s: clipfd already opened (%d)\n", __FUNCTION__, clipfd);
return -1;
}
mixer_num = -1;
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:
* 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)
hal_info("%s: DSP_DEVICE is set (%s) but cannot be opened,"
" fall back to /dev/dsp1\n", __func__, dsp_dev);
dsp_dev = "/dev/dsp1";
}
hal_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) {
hal_info("%s open %s: %m\n", dsp_dev, __FUNCTION__);
return -1;
}
/* 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|O_CLOEXEC);
if (mixer_fd < 0) {
hal_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) {
hal_info("%s: SOUND_MIXER_READ_DEVMASK %m\n", __func__);
devmask = 0;
}
if (ioctl(mixer_fd, SOUND_MIXER_READ_STEREODEVS, &stereo) == -1) {
hal_info("%s: SOUND_MIXER_READ_STEREODEVS %m\n", __func__);
stereo = 0;
}
usable = devmask & stereo;
if (usable == 0) {
hal_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... */
hal_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);
hal_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;
// hal_debug("cAudio::%s\n", __FUNCTION__);
if (clipfd <= 0) {
hal_info("%s: clipfd not yet opened\n", __FUNCTION__);
return -1;
}
ret = write(clipfd, buffer, size);
if (ret < 0)
hal_info("%s: write error (%m)\n", __FUNCTION__);
return ret;
};
int cAudio::StopClip()
{
hal_debug("%s\n", __FUNCTION__);
if (clipfd <= 0) {
hal_info("%s: clipfd not yet opened\n", __FUNCTION__);
return -1;
}
close(clipfd);
clipfd = -1;
if (mixer_fd >= 0)
close(mixer_fd);
mixer_fd = -1;
setVolume(volume, volume);
return 0;
};
void cAudio::getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &mode)
{
hal_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*/)
{
hal_debug("%s\n", __FUNCTION__);
};
void cAudio::SetHdmiDD(bool enable)
{
hal_debug("%s %d\n", __func__, enable);
};
void cAudio::SetSpdifDD(bool enable)
{
hal_debug("%s %d\n", __func__, enable);
setBypassMode(!enable);
};
void cAudio::ScheduleMute(bool On)
{
hal_debug("%s %d\n", __FUNCTION__, On);
};
void cAudio::EnableAnalogOut(bool enable)
{
hal_debug("%s %d\n", __FUNCTION__, enable);
};
#define AUDIO_BYPASS_ON 0
#define AUDIO_BYPASS_OFF 1
void cAudio::setBypassMode(bool disable)
{
hal_debug("%s %d\n", __func__, disable);
int mode = disable ? AUDIO_BYPASS_OFF : AUDIO_BYPASS_ON;
if (ioctl(fd, AUDIO_SET_BYPASS_MODE, mode) < 0)
hal_info("%s AUDIO_SET_BYPASS_MODE %d: %m\n", __func__, mode);
return;
}

View File

@@ -1,97 +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 // __AUDIO_LIB_H__

View File

@@ -1,519 +0,0 @@
/*
* cDemux implementation for azbox receivers (tested on azbox me and minime)
*
* 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/>.
*/
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <poll.h>
#include <errno.h>
#include <inttypes.h>
#include <cstring>
#include <cstdio>
#include <string>
#include <sys/ioctl.h>
#include "dmx_hal.h"
#include "hal_debug.h"
#include "video_lib.h"
/* needed for getSTC... */
extern cVideo *videoDecoder;
#define hal_debug(args...) _hal_debug(HAL_DEBUG_DEMUX, this, args)
#define hal_info(args...) _hal_info(HAL_DEBUG_DEMUX, this, args)
#define hal_info_c(args...) _hal_info(HAL_DEBUG_DEMUX, NULL, args)
#define dmx_err(_errfmt, _errstr, _revents) do { \
hal_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, flt); \
} while(0);
cDemux *videoDemux = NULL;
cDemux *audioDemux = NULL;
//cDemux *pcrDemux = NULL;
static const char *DMX_T[] = {
"DMX_INVALID",
"DMX_VIDEO",
"DMX_AUDIO",
"DMX_PES",
"DMX_PSI",
"DMX_PIP",
"DMX_TP",
"DMX_PCR"
};
/* map the device numbers. for now only demux0 is used */
static const char *devname[] = {
"/dev/dvb/adapter0/demux0",
"/dev/dvb/adapter0/demux0",
"/dev/dvb/adapter0/demux0"
};
/* uuuugly */
static int dmx_tp_count = 0;
#define MAX_TS_COUNT 8
cDemux::cDemux(int n)
{
if (n < 0 || n > 2)
{
hal_info("%s ERROR: n invalid (%d)\n", __FUNCTION__, n);
num = 0;
}
else
num = n;
fd = -1;
}
cDemux::~cDemux()
{
hal_debug("%s #%d fd: %d\n", __FUNCTION__, num, fd);
Close();
/* in zapit.cpp, videoDemux is deleted after videoDecoder
* in the video watchdog, we access videoDecoder
* the thread still runs after videoDecoder has been deleted
* => set videoDecoder to NULL here to make the check in the
* watchdog thread pick this up.
* This is ugly, but it saves me from changing neutrino
*
* if the delete order in neutrino will ever be changed, this
* will blow up badly :-(
*/
if (dmx_type == DMX_VIDEO_CHANNEL)
videoDecoder = NULL;
}
bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBufferSize)
{
int devnum = num;
int flags = O_RDWR|O_CLOEXEC;
if (fd > -1)
hal_info("%s FD ALREADY OPENED? fd = %d\n", __FUNCTION__, fd);
if (pes_type != DMX_PSI_CHANNEL)
flags |= O_NONBLOCK;
fd = open(devname[devnum], flags);
if (fd < 0)
{
hal_info("%s %s: %m\n", __FUNCTION__, devname[devnum]);
return false;
}
hal_debug("%s #%d pes_type: %s(%d), uBufferSize: %d fd: %d\n", __func__,
num, DMX_T[pes_type], pes_type, uBufferSize, fd);
dmx_type = pes_type;
#if 0
if (!pesfds.empty())
{
hal_info("%s ERROR! pesfds not empty!\n", __FUNCTION__); /* TODO: error handling */
return false;
}
int n = DMX_SOURCE_FRONT0;
if (ioctl(fd, DMX_SET_SOURCE, &n) < 0)
hal_info("%s DMX_SET_SOURCE failed!\n", __func__);
#endif
if (uBufferSize > 0)
{
/* probably uBufferSize == 0 means "use default size". TODO: find a reasonable default */
if (ioctl(fd, DMX_SET_BUFFER_SIZE, uBufferSize) < 0)
hal_info("%s DMX_SET_BUFFER_SIZE failed (%m)\n", __func__);
}
buffersize = uBufferSize;
return true;
}
void cDemux::Close(void)
{
hal_debug("%s #%d, fd = %d\n", __FUNCTION__, num, fd);
if (fd < 0)
{
hal_info("%s #%d: not open!\n", __FUNCTION__, num);
return;
}
pesfds.clear();
ioctl(fd, DMX_STOP);
close(fd);
fd = -1;
if (dmx_type == DMX_TP_CHANNEL)
{
dmx_tp_count--;
if (dmx_tp_count < 0)
{
hal_info("%s dmx_tp_count < 0!!\n", __func__);
dmx_tp_count = 0;
}
}
}
bool cDemux::Start(bool)
{
hal_debug("%s #%d fd: %d type: %s\n", __func__, num, fd, DMX_T[dmx_type]);
if (fd < 0)
{
hal_info("%s #%d: not open!\n", __FUNCTION__, num);
return false;
}
ioctl(fd, DMX_START);
return true;
}
bool cDemux::Stop(void)
{
hal_debug("%s #%d fd: %d type: %s\n", __func__, num, fd, DMX_T[dmx_type]);
if (fd < 0)
{
hal_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 != 100)
fprintf(stderr, "cDemux::%s #%d fd: %d type: %s len: %d timeout: %d\n",
__FUNCTION__, num, fd, DMX_T[dmx_type], len, timeout);
#endif
int rc;
int to = timeout;
/* using a one-dimensional array seems to avoid strange segfaults / memory corruption?? */
struct pollfd ufds[1];
ufds[0].fd = fd;
ufds[0].events = POLLIN|POLLPRI|POLLERR;
ufds[0].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)
//hal_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[0].revents & POLLHUP) /* we get POLLHUP if e.g. a too big DMX_BUFFER_SIZE was set */
{
dmx_err("received %s,", "POLLHUP", ufds[0].revents);
return -1;
}
if (!(ufds[0].revents & POLLIN)) /* we requested POLLIN but did not get it? */
{
dmx_err("received %s, please report!", "POLLIN", ufds[0].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)
{
struct dmx_sct_filter_params s_flt;
memset(&s_flt, 0, sizeof(s_flt));
pid = _pid;
if (len > DMX_FILTER_SIZE)
{
hal_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;
flt = filter[0];
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;
hal_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<DMX_FILTER_SIZE;i++)fprintf(stderr,"%02hhx ",s_flt.filter.filter[i]);fprintf(stderr,"\n");
fprintf(stderr,"mask: ");for(int i=0;i<DMX_FILTER_SIZE;i++)fprintf(stderr,"%02hhx ",s_flt.filter.mask [i]);fprintf(stderr,"\n");
fprintf(stderr,"mode: ");for(int i=0;i<DMX_FILTER_SIZE;i++)fprintf(stderr,"%02hhx ",s_flt.filter.mode [i]);fprintf(stderr,"\n");
#endif
ioctl (fd, DMX_STOP);
if (ioctl(fd, DMX_SET_FILTER, &s_flt) < 0)
return false;
ioctl(fd, DMX_START);
return true;
}
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...
if (pid <= 0x0001 && dmx_type != DMX_PCR_ONLY_CHANNEL)
return false;
*/
if ((pid >= 0x0002 && pid <= 0x000f) || pid >= 0x1fff)
return false;
hal_debug("%s #%d pid: 0x%04hx fd: %d type: %s\n", __FUNCTION__, num, pid, fd, DMX_T[dmx_type]);
memset(&p_flt, 0, sizeof(p_flt));
p_flt.pid = pid;
p_flt.output = DMX_OUT_DECODER;
p_flt.input = DMX_IN_FRONTEND;
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_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:
hal_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*/)
{
hal_debug("%s #%d\n", __FUNCTION__, num);
}
void *cDemux::getBuffer()
{
hal_debug("%s #%d\n", __FUNCTION__, num);
return NULL;
}
void *cDemux::getChannel()
{
hal_debug("%s #%d\n", __FUNCTION__, num);
return NULL;
}
bool cDemux::addPid(unsigned short Pid)
{
hal_debug("%s: pid 0x%04hx\n", __func__, Pid);
pes_pids pfd;
int ret;
if (dmx_type != DMX_TP_CHANNEL)
{
hal_info("%s pes_type %s not implemented yet! pid=%hx\n", __FUNCTION__, DMX_T[dmx_type], Pid);
return false;
}
if (fd == -1)
hal_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)
hal_info("%s: DMX_ADD_PID (%m)\n", __func__);
return (ret != -1);
}
void cDemux::removePid(unsigned short Pid)
{
if (dmx_type != DMX_TP_CHANNEL)
{
hal_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) {
hal_debug("removePid: removing demux fd %d pid 0x%04x\n", fd, Pid);
if (ioctl(fd, DMX_REMOVE_PID, Pid) < 0)
hal_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 */
}
}
hal_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 */
hal_debug("%s #%d\n", __func__, num);
int64_t pts = 0;
if (videoDecoder)
pts = videoDecoder->GetPTS();
*STC = pts;
}
int cDemux::getUnit(void)
{
hal_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)
{
hal_info_c("%s(%d, %d): not implemented yet\n", __func__, unit, source);
return true;
}
int cDemux::GetSource(int unit)
{
hal_info_c("%s(%d): not implemented yet\n", __func__, unit);
return 0;
}

View File

@@ -1,83 +0,0 @@
//Additional Azbox
enum key_command {
KEY_COMMAND_QUIT_ALL = 100,
KEY_COMMAND_QUIT,
KEY_COMMAND_PLAY,
KEY_COMMAND_PAUSE,
KEY_COMMAND_RESUME,
KEY_COMMAND_STOP,
KEY_COMMAND_SEEK_TO_TIME,
KEY_COMMAND_SEEK_TO_PERCENT,
KEY_COMMAND_NEXT_PICT,
KEY_COMMAND_FAST_FWD_ALL_FRAMES,
KEY_COMMAND_SLOW_FWD_ALL_FRAMES,
KEY_COMMAND_IFRAMES_FWD,
KEY_COMMAND_IFRAMES_BWD,
KEY_COMMAND_SILENT_FWD,
KEY_COMMAND_SILENT_BWD,
KEY_COMMAND_SWITCH_VIDEO,
KEY_COMMAND_SWITCH_AUDIO,
KEY_COMMAND_SWITCH_PROGRAM,
KEY_COMMAND_SWITCH_SUBS,
KEY_COMMAND_SWITCH_MULTICAST,
KEY_COMMAND_APPLY_AV_DELAY,
KEY_COMMAND_SUBS_CHANGE_DELAY,
KEY_COMMAND_SUBS_INCREASE_FONT_SIZE,
KEY_COMMAND_SUBS_DECREASE_FONT_SIZE,
KEY_COMMAND_SUBS_INCREASE_POS_Y,
KEY_COMMAND_SUBS_DECREASE_POS_Y,
KEY_COMMAND_SUBS_SWITCH_ENCODING,
KEY_COMMAND_SUBS_RESET_ALL,
KEY_COMMAND_SUBS_CHANGE_COLOR,
KEY_COMMAND_DEBUG,
KEY_COMMAND_PRINT_INFO,
KEY_COMMAND_FULL_SCREEN,
KEY_COMMAND_HALF_SCREEN,
KEY_COMMAND_INCREASE_SIZE,
KEY_COMMAND_DECREASE_SIZE,
KEY_COMMAND_MOVE_LEFT,
KEY_COMMAND_MOVE_RIGHT,
KEY_COMMAND_MOVE_TOP,
KEY_COMMAND_MOVE_BOTTOM,
KEY_COMMAND_NONLINEAR_WIDTH,
KEY_COMMAND_NONLINEAR_LEVEL,
KEY_COMMAND_SWITCH_SCALER,
KEY_COMMAND_HELP,
KEY_COMMAND_FAST_FWD_WITH_AUDIO,
KEY_COMMAND_SLOW_FWD_WITH_AUDIO,
KEY_COMMAND_PRINT_TXT,
SPECIAL_KEY_COMMAND_IFRAMES_FWD,
SPECIAL_KEY_COMMAND_IFRAMES_BWD,
SPECIAL_KEY_COMMAND_NEXT_AUDIO,
SPECIAL_KEY_COMMAND_NEXT_SUBS,
};
enum custom_command {
CUSTOM_COMMAND_GETLENGTH = 200,
CUSTOM_COMMAND_GETPOSITION,
CUSTOM_COMMAND_AUDIOGETPOSITION,
CUSTOM_COMMAND_SEEK_RELATIVE_FWD,
CUSTOM_COMMAND_SEEK_RELATIVE_BWD,
CUSTOM_COMMAND_SUBS_COUNT,
CUSTOM_COMMAND_GET_SUB_BY_ID,
CUSTOM_COMMAND_AUDIO_COUNT,
CUSTOM_COMMAND_GET_AUDIO_BY_ID,
CUSTOM_COMMAND_AUDIO_CUR_STREAM,
CUSTOM_COMMAND_SUBS_CUR_STREAM,
CUSTOM_COMMAND_TRICK_SEEK,
CUSTOM_COMMAND_SET_SUB_SIZE,
CUSTOM_COMMAND_SET_SUB_ENCODING,
CUSTOM_COMMAND_SET_SUB_POS,
};
enum event_msg {
EVENT_MSG_FDOPEN = 300,
EVENT_MSG_PLAYBACK_STARTED,
EVENT_MSG_STOPPED,
EVENT_MSG_PAUSED,
EVENT_MSG_BUFFERING,
EVENT_MSG_EOS,
EVENT_MSG_SUB_CHANGED,
};
//int fd_cmd, fd_in, fd_out, fd_event, msg;

View File

@@ -1,23 +0,0 @@
#include <unistd.h>
#include "init.h"
#include "hal_debug.h"
#define hal_debug(args...) _hal_debug(HAL_DEBUG_INIT, NULL, args)
#define hal_info(args...) _hal_info(HAL_DEBUG_INIT, NULL, args)
static bool initialized = false;
void hal_api_init()
{
if (!initialized)
hal_debug_init();
hal_info("%s begin, initialized=%d, debug=0x%02x\n", __func__, (int)initialized, debuglevel);
initialized = true;
}
void hal_api_exit()
{
hal_info("%s, initialized = %d\n", __func__, (int)initialized);
initialized = false;
}

View File

@@ -1,521 +0,0 @@
/*
* cPlayback implementation for azbox
* this is actually just a wrapper around rmfp_player which does
* all the heavy listing
*
* based on the original aztrino implementation, but almost
* completely rewritten since then
*
* some of the methods and constants were found by stracing the
* AZPlay enigma2 plugin...
*
* (C) 2012 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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sstream>
#include <pty.h>
#include <sys/poll.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "hal_debug.h"
#define hal_debug(args...) _hal_debug(HAL_DEBUG_PLAYBACK, this, args)
#define hal_info(args...) _hal_info(HAL_DEBUG_PLAYBACK, this, args)
#define hal_info_c(args...) _hal_info(HAL_DEBUG_PLAYBACK, NULL, args)
#include <proc_tools.h>
/* the file-based commands work better than the FIFOs... */
#define CMD_FILE "/tmp/rmfp.cmd2"
#define IN_FILE "/tmp/rmfp.in2"
#define OUT_FILE "/tmp/rmfp.out2"
#include "playback_lib.h"
extern "C"{
#include "e2mruainclude.h"
}
#if 0
/* useful for debugging */
static time_t monotonic_ms(void)
{
struct timespec t;
time_t ret;
if (clock_gettime(CLOCK_MONOTONIC, &t))
{
perror("monotonic_ms clock_gettime");
return -1;
}
ret = ((t.tv_sec + 604800)& 0x01FFFFF) * 1000; /* avoid overflow */
ret += t.tv_nsec / 1000000;
return ret;
}
#endif
/* the mutex makes sure that commands are not interspersed */
bool cPlayback::rmfp_command(int cmd, int param, bool has_param, char *buf, int buflen)
{
hal_info("%s: %d %d %d %d\n", __func__, cmd, param, has_param, buflen);
bool ret = true;
int fd;
if (cmd == 222)
{
if (pthread_mutex_trylock(&rmfp_cmd_mutex))
return false;
}
else
pthread_mutex_lock(&rmfp_cmd_mutex);
unlink(OUT_FILE);
if (has_param)
{
fd = open(IN_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666);
dprintf(fd, "%i", param);
close(fd);
}
fd = open(CMD_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666);
dprintf(fd, "%i", cmd);
close(fd);
int n = 0, m = 0;
if (buflen > 0)
{
while ((fd = open(OUT_FILE, O_RDONLY)) == -1) {
if (++m > 500) { /* don't wait more than 5 seconds */
hal_info("%s: timed out waiting for %s (cmd %d par %d buflen %d\n",
__func__, OUT_FILE, cmd, param, buflen);
ret = false;
goto out;
}
usleep(10000);
}
unlink(OUT_FILE);
n = read(fd, buf, buflen);
close(fd);
/* some commands (CUSTOM_COMMAND_GET_AUDIO_BY_ID for example) actually
* return the answer in two successive writes, as we are not using the
* FIFO, we need to make sure that the file is deleted immediately, because
* rmfp_player will not overwrite it if it exists */
while ((fd = open(OUT_FILE, O_RDONLY)) == -1) {
if (++m > 10)
break;
usleep(1000);
}
if (fd > -1)
{
read(fd, buf + n, buflen - n);
unlink(OUT_FILE);
close(fd);
}
buf[buflen - 1] = '0';
}
out:
pthread_mutex_unlock(&rmfp_cmd_mutex);
if (cmd != 222) /* called tooo often :-) */
hal_info("%s: reply: '%s' ret: %d m:%d\n", __func__, buf?buf:"(none)", ret, m);
return ret;
}
/*
* runs the rmfp_player in a terminal
* just doing popen() or similar does not work because then
* the output will be buffered after starting up and we will only
* see "Playback has started..." after the player exits
*/
void cPlayback::run_rmfp()
{
hal_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 file = '"' + filename + '"';
std::string final = base + file;
if (playMode == PLAYMODE_TS && mduration != 0)
{
std::stringstream duration;
duration << (mduration /** 60000LL*/);
final = base + "-duration " + duration.str() + " " + file;
}
pid_t pid = 0;
int master;
pid = forkpty(&master, NULL, NULL, NULL);
if (! pid) {
execl("/bin/sh", "sh", "-c", final.c_str(), (char *)0);
hal_info("%s: execl returned: %m\n", __func__);
exit(0);
}
if (pid > 0) {
char *output=NULL;
size_t n = 0;
ssize_t len;
FILE *f = fdopen(master, "r");
while ((len = getline(&output, &n, f)) != -1)
{
while (len > 0)
{
len--;
if (!isspace(output[len]))
break;
output[len] = '\0';
}
hal_info("%s out: '%s'\n", __func__, output);
if (strstr(output, "Playback has started..."))
{
playing = 1;
hal_info("%s: ===================> playing = true\n", __func__);
}
else if (strstr(output, "End of file..."))
{
playing = 1; /* this can happen without "Playback has started..." */
eof_reached = true;
hal_info("%s: ===================> eof_reached = true\n", __func__);
}
}
fclose(f);
int s;
while (waitpid(pid, &s, WNOHANG) > 0) {};
if (output)
free(output);
}
hal_info("%s: terminating\n", __func__);
if (playing == 0) /* playback did not start */
playing = 2;
else
playing = 0;
eof_reached = true;
pthread_exit(NULL);
}
/* helper function to call the cpp thread loop */
void *execute_rua_thread(void *c)
{
cPlayback *obj = (cPlayback *)c;
hal_info_c("%s\n", __func__);
obj->run_rmfp();
/* free(obj); // this is most likely wrong */
return NULL;
}
//Used by Fileplay
bool cPlayback::Open(playmode_t PlayMode)
{
static const char *aPLAYMODE[] = {
"PLAYMODE_TS",
"PLAYMODE_FILE"
};
playMode = PlayMode;
if (playMode > 1)
{
hal_info("%s: PlayMode %d out of range!\n", __func__, PlayMode);
playMode = PLAYMODE_FILE;
}
hal_info("%s: mode %d (%s)\n", __func__, PlayMode, aPLAYMODE[PlayMode]);
#if 0
while (access("/tmp/continue", R_OK))
sleep(1);
#endif
char c[2] = "0";
int i = 0;
for(;;)
{
proc_get("/proc/player", c, 2);
if (c[0] != '0')
break;
i++;
if (i > 10)
{
hal_info("%s: ERROR - player is not idle after 10 seconds!\n", __func__);
open_success = false;
return false;
}
sleep(1);
}
proc_put("/proc/player", "2", 2);
hal_info("%s: /proc/player switched to '2'\n", __func__);
unlink(CMD_FILE);
unlink(IN_FILE);
unlink(OUT_FILE);
open_success = true;
return 0;
}
//Used by Fileplay
bool cPlayback::Start(char *filename, unsigned short vpid, int vtype, unsigned short _apid,
int ac3, unsigned int duration)
{
bool ret = true;
hal_info("%s: filename=%s\n", __func__, filename);
hal_info("%s: vpid=%u vtype=%d apid=%u ac3=%d duration=%i open_success=%d\n",
__func__, vpid, vtype, _apid, ac3, duration, open_success);
if (!open_success)
return false;
eof_reached = false;
//create playback path
apid = 0;
subpid = 0;
mfilename = filename;
mduration = duration;
if (pthread_create(&thread, 0, execute_rua_thread, this) != 0)
{
hal_info("%s: error creating rmfp_player thread! (out of memory?)\n", __func__);
ret = false;
}
while (! playing)
sleep(1);
if (playing == 2)
playing = 0;
return ret;
}
void cPlayback::Close(void)
{
hal_info("%s: playing %d thread_started %d\n", __func__, playing, thread_started);
if (thread_started)
{
rmfp_command(KEY_COMMAND_QUIT_ALL, 0, false, NULL, 0);
if (pthread_join(thread, NULL))
hal_info("%s: error joining rmfp thread (%m)\n", __func__);
playing = 0;
thread_started = false;
}
else
hal_info("%s: Warning: thread_started == false!\n", __func__);
if (open_success)
{
proc_put("/proc/player", "1", 2);
open_success = false;
hal_info("%s: /proc/player switched to '1'\n", __func__);
usleep(1000000);
}
}
bool cPlayback::SetAPid(unsigned short pid, int /*ac3*/)
{
hal_info("%s: pid %i\n", __func__, pid);
if (pid != apid) {
rmfp_command(KEY_COMMAND_SWITCH_AUDIO, pid, true, NULL, 0);
apid = pid;
}
return true;
}
bool cPlayback::SelectSubtitles(int pid)
{
hal_info("%s: pid %i\n", __func__, pid);
if (pid != subpid)
{
rmfp_command(KEY_COMMAND_SWITCH_SUBS, pid, true, NULL, 0);
subpid = pid;
}
return true;
}
bool cPlayback::SetSpeed(int speed)
{
hal_info("%s: playing %d speed %d\n", __func__, playing, speed);
if (!playing)
return false;
playback_speed = speed;
if (speed > 1 || speed < 0)
rmfp_command(CUSTOM_COMMAND_TRICK_SEEK, speed, true, NULL, 0);
else if (speed == 0)
rmfp_command(KEY_COMMAND_PAUSE, 0, false, NULL, 0);
else
rmfp_command(KEY_COMMAND_PLAY, 0, false, NULL, 0);
return true;
}
bool cPlayback::GetSpeed(int &/*speed*/) const
{
#if 0
hal_info("%s:\n", __func__);
speed = playback_speed;
#endif
return true;
}
// in milliseconds
bool cPlayback::GetPosition(int &position, int &duration)
{
hal_debug("%s: playing %d\n", __func__, playing);
if (eof_reached)
{
position = mduration;
duration = mduration;
return true;
}
if (!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))
return false;
duration = atoi(buf);
char *p = strchr(buf, '\n');
if (!p)
return false;
position = atoi(++p);
/* some mpegs return length 0... which would lead to "eof" after 10 seconds */
if (duration == 0)
duration = position + 1000;
if (playMode == PLAYMODE_TS)
{
if (position > mduration)
mduration = position + 1000;
duration = mduration;
return true;
}
return true;
}
bool cPlayback::SetPosition(int position, bool absolute)
{
hal_info("%s: pos %d abs %d playing %d\n", __func__, position, absolute, playing);
if (!playing)
return false;
int seconds = position / 1000;;
if (absolute)
{
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);
else if (position < 0)
rmfp_command(CUSTOM_COMMAND_SEEK_RELATIVE_BWD, seconds, true, NULL, 0);
return true;
}
void cPlayback::FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t *numpida, std::string *language)
{
hal_info("%s\n", __func__);
char buf[32];
rmfp_command(CUSTOM_COMMAND_AUDIO_COUNT, 0, false, buf, 3);
unsigned int audio_count = atoi(buf);
*numpida = audio_count;
if (audio_count > 0)
{
for (unsigned int aid = 0; aid < audio_count; aid++)
{
char streamidstring[11];
char audio_lang[21];
memset(buf, 0, sizeof(buf));
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);
audio_lang[20] = '\0';
apids[aid] = atoi(streamidstring);
ac3flags[aid] = 0;
language[aid] = audio_lang;
hal_info("%s: #%d apid:%d lang: %s\n", __func__, aid, apids[aid], audio_lang);
}
}
}
void cPlayback::FindAllSubs(uint16_t *spids, unsigned short *supported, uint16_t *numpids, std::string *language)
{
hal_info("%s\n", __func__);
char buf[32];
rmfp_command(CUSTOM_COMMAND_SUBS_COUNT, 0, false, buf, 3);
unsigned int spu_count = atoi(buf);
*numpids = spu_count;
if (spu_count > 0)
{
for (unsigned int sid = 0; sid < spu_count; sid++)
{
char streamidstring[11];
char spu_lang[21];
memset(buf, 0, sizeof(buf));
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);
spu_lang[20] = '\0';
spids[sid] = atoi(streamidstring);
language[sid] = spu_lang;
supported[sid] = 1;
hal_info("%s: #%d apid:%d lang: %s\n", __func__, sid, spids[sid], spu_lang);
}
}
//Add streamid -1 to be able to disable subtitles
*numpids = spu_count + 1;
spids[spu_count] = -1;
language[spu_count] = "Disable";
}
/* DVD support is not yet ready... */
void cPlayback::GetChapters(std::vector<int> &positions, std::vector<std::string> &titles)
{
positions.clear();
titles.clear();
}
cPlayback::cPlayback(int /*num*/)
{
hal_info("%s: constructor\n", __func__);
playing = 0;
thread_started = false;
eof_reached = false;
open_success = false;
pthread_mutex_init(&rmfp_cmd_mutex, NULL);
}
cPlayback::~cPlayback()
{
hal_info("%s\n", __func__);
pthread_mutex_destroy(&rmfp_cmd_mutex);
}

View File

@@ -1,62 +0,0 @@
#ifndef __PLAYBACK_LIB_H__
#define __PLAYBACK_LIB_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 // __PLAYBACK_LIB_H__

View File

@@ -1 +0,0 @@
../libspark/record.cpp

View File

@@ -1 +0,0 @@
../libspark/record_lib.h

View File

@@ -1,639 +0,0 @@
/*
* (C) 2002-2003 Andreas Oberritter <obi@tuxbox.org>
* (C) 2010-2012 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, write to the Free Software
* Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA
*/
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <utime.h>
#include <errno.h>
#include <ctype.h>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <pthread.h>
#include <linux/types.h>
#include <linux/dvb/video.h>
#include <proc_tools.h>
#include "video_lib.h"
#define VIDEO_DEVICE "/dev/dvb/adapter0/video0"
#include "hal_debug.h"
#define hal_debug(args...) _hal_debug(HAL_DEBUG_VIDEO, this, args)
#define hal_info(args...) _hal_info(HAL_DEBUG_VIDEO, this, args)
#define hal_debug_c(args...) _hal_debug(HAL_DEBUG_VIDEO, NULL, args)
#define hal_info_c(args...) _hal_info(HAL_DEBUG_VIDEO, NULL, args)
#define fop(cmd, args...) ({ \
int _r; \
if (fd >= 0) { \
if ((_r = ::cmd(fd, args)) < 0) \
hal_info(#cmd"(fd, "#args")\n"); \
else \
hal_debug(#cmd"(fd, "#args")\n");\
} \
else { _r = fd; } \
_r; \
})
cVideo * videoDecoder = NULL;
int system_rev = 0;
static bool stillpicture = false;
static unsigned char *blank_data;
static ssize_t blank_size;
static pthread_mutex_t stillp_mutex = PTHREAD_MUTEX_INITIALIZER;
/* prototype */
static void show_iframe(int fd, unsigned char *iframe, size_t st_size);
#define VIDEO_STREAMTYPE_MPEG2 0
#define VIDEO_STREAMTYPE_MPEG4_H264 1
#define VIDEO_STREAMTYPE_VC1 3
#define VIDEO_STREAMTYPE_MPEG4_Part2 4
#define VIDEO_STREAMTYPE_VC1_SM 5
#define VIDEO_STREAMTYPE_MPEG1 6
cVideo::cVideo(int, void *, void *, unsigned int)
{
hal_debug("%s\n", __FUNCTION__);
//croppingMode = VID_DISPMODE_NORM;
//outputformat = VID_OUTFMT_RGBC_SVIDEO;
scartvoltage = -1;
video_standby = 0;
fd = -1;
const char *blankname = "/share/tuxbox/blank_576.mpg";
int blankfd;
struct stat st;
blank_data = NULL; /* initialize */
blank_size = 0;
blankfd = open(blankname, O_RDONLY|O_CLOEXEC);
if (blankfd < 0)
hal_info("%s cannot open %s: %m", __func__, blankname);
else
{
if (fstat(blankfd, &st) != -1 && st.st_size > 0)
{
blank_size = st.st_size;
blank_data = (unsigned char *)malloc(blank_size);
if (! blank_data)
hal_info("%s malloc failed (%m)\n", __func__);
else if (read(blankfd, blank_data, blank_size) != blank_size)
{
hal_info("%s short read (%m)\n", __func__);
free(blank_data); /* don't leak... */
blank_data = NULL;
}
}
close(blankfd);
}
openDevice();
Pig(-1, -1, -1, -1);
}
cVideo::~cVideo(void)
{
closeDevice();
if (blank_data)
free(blank_data);
}
void cVideo::openDevice(void)
{
int n = 0;
hal_debug("%s\n", __func__);
/* todo: this fd checking is racy, should be protected by a lock */
if (fd != -1) /* already open */
return;
retry:
if ((fd = open(VIDEO_DEVICE, O_RDWR|O_CLOEXEC)) < 0)
{
if (errno == EBUSY)
{
/* sometimes we get busy quickly after close() */
usleep(50000);
if (++n < 10)
goto retry;
}
hal_info("%s cannot open %s: %m, retries %d\n", __func__, VIDEO_DEVICE, n);
}
playstate = VIDEO_STOPPED;
}
void cVideo::closeDevice(void)
{
hal_debug("%s\n", __func__);
if (fd >= 0)
close(fd);
fd = -1;
playstate = VIDEO_STOPPED;
}
int cVideo::setAspectRatio(int aspect, int mode)
{
static const char *a[] = { "n/a", "4:3", "14:9", "16:9" };
/* { "panscan", "letterbox", "fullscreen", "14:9", "(unset)" } */
static const char *m[] = { "1", "2", "0", "1", "(unset)" };
int n;
int mo = (mode < 0||mode > 3) ? 4 : mode;
hal_debug("%s: a:%d m:%d %s\n", __func__, aspect, mode, m[(mo)]);
if (aspect > 3 || aspect == 0)
hal_info("%s: invalid aspect: %d\n", __func__, aspect);
else if (aspect > 0) /* -1 == don't set */
{
hal_debug("%s: /proc/stb/video/aspect -> %s\n", __func__, a[aspect]);
n = proc_put("/proc/stb/video/aspect", a[aspect], strlen(a[aspect]));
if (n < 0)
hal_info("%s: proc_put /proc/stb/video/aspect (%m)\n", __func__);
}
if (mode == -1)
return 0;
hal_debug("%s: /proc/scalingmode -> %s\n", __func__, m[mo]);
n = proc_put("/proc/scalingmode", m[mo], strlen(m[mo]));
if (n < 0)
return 1;
return 0;
}
int cVideo::getAspectRatio(void)
{
video_size_t s;
if (fd == -1)
{
/* in movieplayer mode, fd is not opened -> fall back to procfs */
int n = proc_get_hex("/proc/stb/vmpeg/0/aspect");
return n * 2 + 1;
}
if (fop(ioctl, VIDEO_GET_SIZE, &s) < 0)
{
hal_info("%s: VIDEO_GET_SIZE %m\n", __func__);
return -1;
}
hal_debug("%s: %d\n", __func__, s.aspect_ratio);
return s.aspect_ratio * 2 + 1;
}
int cVideo::setCroppingMode(int /*vidDispMode_t format*/)
{
return 0;
#if 0
croppingMode = format;
const char *format_string[] = { "norm", "letterbox", "unknown", "mode_1_2", "mode_1_4", "mode_2x", "scale", "disexp" };
const char *f;
if (format >= VID_DISPMODE_NORM && format <= VID_DISPMODE_DISEXP)
f = format_string[format];
else
f = "ILLEGAL format!";
hal_debug("%s(%d) => %s\n", __FUNCTION__, format, f);
return fop(ioctl, MPEG_VID_SET_DISPMODE, format);
#endif
}
int cVideo::Start(void * /*PcrChannel*/, unsigned short /*PcrPid*/, unsigned short /*VideoPid*/, void * /*hChannel*/)
{
hal_debug("%s playstate=%d\n", __FUNCTION__, playstate);
#if 0
if (playstate == VIDEO_PLAYING)
return 0;
if (playstate == VIDEO_FREEZED) /* in theory better, but not in practice :-) */
fop(ioctl, MPEG_VID_CONTINUE);
#endif
playstate = VIDEO_PLAYING;
return fop(ioctl, VIDEO_PLAY);
}
int cVideo::Stop(bool blank)
{
hal_debug("%s(%d)\n", __FUNCTION__, blank);
if (stillpicture)
{
hal_debug("%s: stillpicture == true\n", __func__);
return -1;
}
/* blank parameter seems to not work on VIDEO_STOP */
if (blank)
setBlank(1);
playstate = blank ? VIDEO_STOPPED : VIDEO_FREEZED;
return fop(ioctl, VIDEO_STOP, blank ? 1 : 0);
}
int cVideo::setBlank(int)
{
pthread_mutex_lock(&stillp_mutex);
if (blank_data)
show_iframe(fd, blank_data, blank_size);
pthread_mutex_unlock(&stillp_mutex);
return 1;
}
int cVideo::SetVideoSystem(int video_system, bool remember)
{
hal_debug("%s(%d, %d)\n", __func__, video_system, remember);
char current[32];
static const char *modes[] = {
"480i", // VIDEO_STD_NTSC
"576i", // VIDEO_STD_SECAM
"576i", // VIDEO_STD_PAL
"480p", // VIDEO_STD_480P
"576p", // VIDEO_STD_576P
"720p60", // VIDEO_STD_720P60
"1080i60", // VIDEO_STD_1080I60
"720p50", // VIDEO_STD_720P50
"1080i50", // VIDEO_STD_1080I50
"1080p30", // VIDEO_STD_1080P30
"1080p24", // VIDEO_STD_1080P24
"1080p25", // VIDEO_STD_1080P25
"720p50", // VIDEO_STD_AUTO -> not implemented
"1080p50" // VIDEO_STD_1080P50 -> SPARK only
};
if (video_system > VIDEO_STD_MAX)
{
hal_info("%s: video_system (%d) > VIDEO_STD_MAX (%d)\n", __func__, video_system, VIDEO_STD_MAX);
return -1;
}
int ret = proc_get("/proc/stb/video/videomode", current, 32);
if (strcmp(current, modes[video_system]) == 0)
{
hal_info("%s: video_system %d (%s) already set, skipping\n", __func__, video_system, current);
return 0;
}
hal_info("%s: old: '%s' new: '%s'\n", __func__, current, modes[video_system]);
ret = proc_put("/proc/stb/video/videomode", modes[video_system],strlen(modes[video_system]));
return ret;
}
int cVideo::getPlayState(void)
{
return playstate;
}
void cVideo::SetVideoMode(analog_mode_t mode)
{
hal_debug("%s(%d)\n", __func__, mode);
if (!(mode & ANALOG_SCART_MASK))
{
hal_debug("%s: non-SCART mode ignored\n", __func__);
return;
}
const char *m;
switch(mode)
{
case ANALOG_SD_YPRPB_SCART:
m = "yuv";
break;
case ANALOG_SD_RGB_SCART:
m = "rgb";
break;
default:
hal_info("%s unknown mode %d\n", __func__, mode);
m = "rgb";
break; /* default to rgb */
}
proc_put("/proc/stb/avs/0/colorformat", m, strlen(m));
}
bool cVideo::ShowPicture(const char * fname)
{
bool ret = false;
hal_debug("%s(%s)\n", __func__, fname);
char destname[512];
char cmd[512];
char *p;
int mfd;
unsigned char *iframe;
struct stat st, st2;
if (video_standby)
{
/* does not work and the driver does not seem to like it */
hal_info("%s: video_standby == true\n", __func__);
return ret;
}
if (fd == -1)
{
hal_info("%s: decoder not opened\n", __func__);
return ret;
}
strcpy(destname, "/var/cache");
if (stat(fname, &st2))
{
hal_info("%s: could not stat %s (%m)\n", __func__, fname);
return ret;
}
mkdir(destname, 0755);
/* the cache filename is (example for /share/tuxbox/neutrino/icons/radiomode.jpg):
/var/cache/share.tuxbox.neutrino.icons.radiomode.jpg.m2v
build that filename first...
TODO: this could cause name clashes, use a hashing function instead... */
strcat(destname, fname);
p = &destname[strlen("/var/cache/")];
while ((p = strchr(p, '/')) != NULL)
*p = '.';
strcat(destname, ".m2v");
/* ...then check if it exists already... */
if (stat(destname, &st) || (st.st_mtime != st2.st_mtime) || (st.st_size == 0))
{
struct utimbuf u;
u.actime = time(NULL);
u.modtime = st2.st_mtime;
/* it does not exist or has a different date, so call ffmpeg... */
sprintf(cmd, "ffmpeg -y -f mjpeg -i '%s' -s 1280x720 '%s' </dev/null",
fname, destname);
system(cmd); /* TODO: use libavcodec to directly convert it */
utime(destname, &u);
}
/* the mutex is a workaround: setBlank is apparently called from
a differnt thread and takes slightly longer, so that the decoder
was blanked immediately after displaying the image, which is not
what we want. the mutex ensures proper ordering. */
pthread_mutex_lock(&stillp_mutex);
mfd = open(destname, O_RDONLY|O_CLOEXEC);
if (mfd < 0)
{
hal_info("%s cannot open %s: %m", __func__, destname);
goto out;
}
fstat(mfd, &st);
stillpicture = true;
iframe = (unsigned char *)malloc(st.st_size);
if (! iframe)
{
hal_info("%s: malloc failed (%m)\n", __func__);
goto out;
}
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 ret;
}
void cVideo::StopPicture()
{
hal_debug("%s\n", __func__);
stillpicture = false;
}
void cVideo::Standby(unsigned int bOn)
{
hal_debug("%s(%d)\n", __func__, bOn);
if (bOn)
{
closeDevice();
proc_put("/proc/stb/avs/0/input", "aux", 4);
}
else
{
proc_put("/proc/stb/avs/0/input", "encoder", 8);
openDevice();
}
video_standby = bOn;
}
int cVideo::getBlank(void)
{
int ret = proc_get_hex("/proc/stb/vmpeg/0/xres");
hal_debug("%s => %d\n", __func__, !ret);
return !ret;
}
/* this function is regularly called, checks if video parameters
changed and triggers appropriate actions */
void cVideo::VideoParamWatchdog(void)
{
#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)
{
hal_debug("%s params changed. old: %08x new: %08x\n", __FUNCTION__, _v_info, v_info);
setAspectRatio(-1, -1);
}
_v_info = v_info;
#endif
}
void cVideo::Pig(int x, int y, int w, int h, int osd_w, int osd_h)
{
char buffer[64];
int _x, _y, _w, _h;
/* the target "coordinates" seem to be in a PAL sized plane
* TODO: check this in the driver sources */
int xres = 720; /* proc_get_hex("/proc/stb/vmpeg/0/xres") */
int yres = 576; /* proc_get_hex("/proc/stb/vmpeg/0/yres") */
hal_debug("%s: x:%d y:%d w:%d h:%d ow:%d oh:%d\n", __func__, x, y, w, h, osd_w, osd_h);
if (x == -1 && y == -1 && w == -1 && h == -1)
{
_w = xres;
_h = yres;
_x = 0;
_y = 0;
}
else
{
_x = x * xres / osd_w;
_w = w * xres / osd_w;
_y = y * yres / osd_h;
_h = h * yres / osd_h;
}
hal_debug("%s: x:%d y:%d w:%d h:%d xr:%d yr:%d\n", __func__, _x, _y, _w, _h, xres, yres);
sprintf(buffer, "%x", _x);
proc_put("/proc/stb/vmpeg/0/dst_left", buffer, strlen(buffer));
sprintf(buffer, "%x", _y);
proc_put("/proc/stb/vmpeg/0/dst_top", buffer, strlen(buffer));
sprintf(buffer, "%x", _w);
proc_put("/proc/stb/vmpeg/0/dst_width", buffer, strlen(buffer));
sprintf(buffer, "%x", _h);
proc_put("/proc/stb/vmpeg/0/dst_height", buffer, strlen(buffer));
}
static inline int rate2csapi(int rate)
{
switch (rate)
{
/* no idea how the float values are represented by the driver */
case 23976:
return 0;
case 24:
return 1;
case 25:
return 2;
case 29976:
return 3;
case 30:
return 4;
case 50:
return 5;
case 50940:
return 6;
case 60:
return 7;
default:
break;
}
return -1;
}
void cVideo::getPictureInfo(int &width, int &height, int &rate)
{
video_size_t s;
int r;
if (fd == -1)
{
/* in movieplayer mode, fd is not opened -> fall back to procfs */
r = proc_get_hex("/proc/stb/vmpeg/0/framerate");
width = proc_get_hex("/proc/stb/vmpeg/0/xres");
height = proc_get_hex("/proc/stb/vmpeg/0/yres");
rate = rate2csapi(r);
return;
}
ioctl(fd, VIDEO_GET_SIZE, &s);
ioctl(fd, VIDEO_GET_FRAME_RATE, &r);
rate = rate2csapi(r);
height = s.h;
width = s.w;
hal_debug("%s: rate: %d, width: %d height: %d\n", __func__, rate, width, height);
}
void cVideo::SetSyncMode(AVSYNC_TYPE mode)
{
hal_debug("%s %d\n", __func__, mode);
/*
* { 0, LOCALE_OPTIONS_OFF },
* { 1, LOCALE_OPTIONS_ON },
* { 2, LOCALE_AUDIOMENU_AVSYNC_AM }
*/
#if 0
switch(Mode)
{
case 0:
ioctl(fd, MPEG_VID_SYNC_OFF);
break;
case 1:
ioctl(fd, MPEG_VID_SYNC_ON, VID_SYNC_VID);
break;
default:
ioctl(fd, MPEG_VID_SYNC_ON, VID_SYNC_AUD);
break;
}
#endif
};
int cVideo::SetStreamType(VIDEO_FORMAT type)
{
static const char *VF[] = {
"VIDEO_FORMAT_MPEG2",
"VIDEO_FORMAT_MPEG4",
"VIDEO_FORMAT_VC1",
"VIDEO_FORMAT_JPEG",
"VIDEO_FORMAT_GIF",
"VIDEO_FORMAT_PNG"
};
int t;
hal_debug("%s type=%s\n", __FUNCTION__, VF[type]);
switch (type)
{
case VIDEO_FORMAT_MPEG4:
t = VIDEO_STREAMTYPE_MPEG4_H264;
break;
case VIDEO_FORMAT_VC1:
t = VIDEO_STREAMTYPE_VC1;
break;
case VIDEO_FORMAT_MPEG2:
default:
t = VIDEO_STREAMTYPE_MPEG2;
break;
}
if (ioctl(fd, VIDEO_SET_STREAMTYPE, t) < 0)
hal_info("%s VIDEO_SET_STREAMTYPE(%d) failed: %m\n", __func__, t);
return 0;
}
int64_t cVideo::GetPTS(void)
{
int64_t pts = 0;
if (ioctl(fd, VIDEO_GET_PTS, &pts) < 0)
hal_info("%s: GET_PTS failed (%m)\n", __func__);
return pts;
}
static void show_iframe(int fd, unsigned char *iframe, size_t st_size)
{
static const unsigned char pes_header[] = { 0, 0, 1, 0xE0, 0, 0, 0x80, 0x80, 5, 0x21, 0, 1, 0, 1};
static const unsigned char seq_end[] = { 0x00, 0x00, 0x01, 0xB7 };
unsigned char stuffing[128];
bool seq_end_avail = false;
size_t pos = 0;
int count = 7;
if (ioctl(fd, VIDEO_SET_FORMAT, VIDEO_FORMAT_16_9) < 0)
hal_info_c("%s: VIDEO_SET_FORMAT failed (%m)\n", __func__);
ioctl(fd, VIDEO_SET_STREAMTYPE, VIDEO_FORMAT_MPEG2);
ioctl(fd, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY);
ioctl(fd, VIDEO_PLAY);
ioctl(fd, VIDEO_CONTINUE);
ioctl(fd, VIDEO_CLEAR_BUFFER);
while (pos <= (st_size-4) && !(seq_end_avail = (!iframe[pos] && !iframe[pos+1] && iframe[pos+2] == 1 && iframe[pos+3] == 0xB7)))
++pos;
while (count--)
{
if ((iframe[3] >> 4) != 0xE) // no pes header
write(fd, pes_header, sizeof(pes_header));
else
iframe[4] = iframe[5] = 0x00;
write(fd, iframe, st_size);
usleep(8000);
}
if (!seq_end_avail)
write(fd, seq_end, sizeof(seq_end));
memset(stuffing, 0, sizeof(stuffing));
for (count = 0; count < 8192 / (int)sizeof(stuffing); count++)
write(fd, stuffing, sizeof(stuffing));
ioctl(fd, VIDEO_STOP, 0);
ioctl(fd, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX);
}
void cVideo::SetDemux(cDemux *)
{
hal_debug("%s: not implemented yet\n", __func__);
}

View File

@@ -1,196 +0,0 @@
#ifndef __VIDEO_LIB_H__
#define __VIDEO_LIB_H__
#include <linux/dvb/video.h>
#include "cs_types.h"
#include "dmx_hal.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; };
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 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 // __VIDEO_LIB_H__

View File

@@ -24,4 +24,4 @@ libduckbox_la_SOURCES = \
playback_libeplayer3.cpp \
record.cpp
AM_CPPFLAGS += -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
AM_CPPFLAGS += -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS

View File

@@ -32,6 +32,7 @@ hw_caps_t *get_hwcaps(void)
caps.display_can_set_brightness = 0;
caps.display_can_deepstandby = 0;
caps.display_has_statusline = 0;
caps.can_cpufreq = 1;
if (fd != -1) {
len = read(fd, buf, sizeof(buf) - 1);
close(fd);

View File

@@ -142,7 +142,7 @@ int descrambler_set_key(int index, int parity, unsigned char *data)
int descrambler_set_pid(int index, int enable, int pid)
{
struct ca_pid p;
#if HAVE_ARM_HARDWARE
#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE
unsigned int flags = 0x80;
if (index)

View File

@@ -713,7 +713,7 @@ static int generate_akh(struct cc_ctrl_data *cc_data)
uint8_t akh[32];
SHA256_CTX sha;
printf("%s>%s\n", FILENAME, __FUNCTION__);
printf("%s -> %s\n", FILENAME, __FUNCTION__);
SHA256_Init(&sha);
SHA256_Update(&sha, element_get_ptr(cc_data, 6), element_get_buf(cc_data, NULL, 6));
@@ -926,9 +926,11 @@ static int data_get_handle_new(struct cc_ctrl_data *cc_data, unsigned int id)
/* SAC data messages */
case 6: //CICAM_id
case 12: //keyprecursor
check_new_key(cc_data);
break;
case 26: //programm number
case 25: //uri_message
generate_uri_confirm(cc_data, cc_data->sak);
break;
@@ -937,6 +939,7 @@ static int data_get_handle_new(struct cc_ctrl_data *cc_data, unsigned int id)
break;
default:
printf("%s -> %s unhandled ID (%d)\n", FILENAME, __FUNCTION__, id);
break;
}
@@ -1354,7 +1357,7 @@ void eDVBCIContentControlManagerSession::resendKey(eDVBCISlot *tslot)
if (!tslot->SidBlackListed && (tslot->recordUse[0] || tslot->liveUse[0]))
{
#if HAVE_ARM_HARDWARE
#if HAVE_ARM_HARDWARE || HAVE_MIPS_HARDWARE
if (slot->newPids)
{
if (slot->pids.size())

View File

@@ -80,10 +80,11 @@ int eDVBCIResourceManagerSession::doAction()
{0x00, 0x02, 0x00, 0x41}, // application V1
{0x00, 0x02, 0x00, 0x43}, // application V3
{0x00, 0x03, 0x00, 0x41}, // conditional access
// {0x00, 0x20, 0x00, 0x41}, // host control
{0x00, 0x20, 0x00, 0x41}, // host control (dummy)
{0x00, 0x40, 0x00, 0x41}, // mmi
{0x00, 0x24, 0x00, 0x41}, // date-time
{0x00, 0x8c, 0x10, 0x01} // content control
{0x00, 0x8c, 0x10, 0x01}, // content control
{0x00, 0x8e, 0x10, 0x01} // cam upgrade (dummy)
// {0x00, 0x10, 0x00, 0x41} // auth.
};
sendAPDU(tag, data, sizeof(data));

View File

@@ -14,6 +14,40 @@
eDVBCISession* eDVBCISession::sessions[SLMS];
eDVBCIHostControlSession::eDVBCIHostControlSession(eDVBCISlot *tslot)
{
slot = tslot;
}
eDVBCIHostControlSession::~eDVBCIHostControlSession()
{
}
int eDVBCIHostControlSession::receivedAPDU(const unsigned char *tag,const void *data, int len)
{
printf("CI HC SESSION(%d)/TAG %02x %02x %02x: ", session_nb, tag[0], tag[1], tag[2]);
for (int i=0; i<len; i++)
printf("%02x ", ((const unsigned char*)data)[i]);
printf("\n");
return 0;
}
int eDVBCIHostControlSession::doAction()
{
switch (state)
{
case stateStarted:
{
const unsigned char tag[3] = {0x9F, 0x80, 0x20}; // application manager info
sendAPDU(tag);
state = stateFinal;
return 1;
}
default:
return 0;
}
}
int eDVBCISession::buildLengthField(unsigned char *pkt, int len)
{
if (len < 127)
@@ -180,12 +214,16 @@ eDVBCISession* eDVBCISession::createSession(eDVBCISlot *slot, const unsigned cha
sessions[session_nb - 1] = new eDVBCIContentControlManagerSession(slot);
break;
} // fall through
case 0x00200041:
sessions[session_nb - 1] = new eDVBCIHostControlSession(slot);
printf("[CI SESS] Host Control\n");
break;
case 0x00100041:
// session=new eDVBCIAuthSession;
printf("[CI SESS] AuthSession\n");
// break;
// fall through
case 0x00200041:
case 0x008e1001:
default:
printf("[CI SESS] unknown resource type %02x %02x %02x %02x\n", resource_identifier[0], resource_identifier[1], resource_identifier[2], resource_identifier[3]);
sessions[session_nb - 1] = 0;

View File

@@ -47,4 +47,18 @@ public:
static int pollAll();
};
class eDVBCIHostControlSession: public eDVBCISession
{
enum {
stateFinal=statePrivate
};
eDVBCISlot *slot;
int receivedAPDU(const unsigned char *tag,const void *data, int len);
int doAction();
public:
eDVBCIHostControlSession(eDVBCISlot *tslot);
~eDVBCIHostControlSession();
};
#endif

View File

@@ -38,6 +38,14 @@ extern "C" {
#include <libavutil/opt.h>
}
#if (LIBAVFORMAT_VERSION_INT > AV_VERSION_INT( 57,25,100 ))
#define EPLAYER_MAX_CODECS 16
struct CodecList
{
AVCodecContext *codec;
};
#endif
class Player;
class Track;
@@ -63,6 +71,9 @@ class Input
Player *player;
AVFormatContext *avfc;
#if (LIBAVFORMAT_VERSION_INT > AV_VERSION_INT( 57,25,100 ))
CodecList codecs[EPLAYER_MAX_CODECS];
#endif
uint64_t readCount;
int64_t calcPts(AVStream * stream, int64_t pts);
@@ -85,6 +96,7 @@ class Input
bool GetMetadata(std::vector<std::string> &keys, std::vector<std::string> &values);
bool GetReadCount(uint64_t &readcount);
AVFormatContext *GetAVFormatContext();
AVCodecContext *GetCodecContext(unsigned int index);
void ReleaseAVFormatContext();
};

View File

@@ -37,6 +37,26 @@ extern "C" {
#define AV_CODEC_ID_INJECTPCM AV_CODEC_ID_PCM_S16LE
/* wrapper */
#if (LIBAVFORMAT_VERSION_INT > AV_VERSION_INT( 57,25,100 ))
static AVCodecParameters __attribute__ ((unused)) *get_codecpar(AVStream *stream)
{
return stream->codecpar;
}
#else
static AVCodecContext __attribute__ ((unused)) *get_codecpar(AVStream *stream)
{
return stream->codec;
}
#endif
#if (LIBAVCODEC_VERSION_MAJOR > 55)
#define av_free_packet av_packet_unref
#else
#define av_packet_unref av_free_packet
#endif
/* end wrapper */
class Player;
class Writer

View File

@@ -54,6 +54,10 @@ Input::Input()
seek_avts_abs = INT64_MIN;
seek_avts_rel = 0;
abortPlayback = false;
#if (LIBAVFORMAT_VERSION_INT > AV_VERSION_INT( 57,25,100 ))
for (int n = 0;n < EPLAYER_MAX_CODECS;n++)
codecs[n].codec = NULL;
#endif
}
Input::~Input()
@@ -108,6 +112,43 @@ static void logprintf(const char *format, ...)
va_end(ap);
}
AVCodecContext *Input::GetCodecContext(unsigned int index)
{
#if (LIBAVFORMAT_VERSION_INT > AV_VERSION_INT( 57,25,100 ))
if (codecs[index].codec) {
return codecs[index].codec;
}
AVCodec *codec = avcodec_find_decoder(avfc->streams[index]->codecpar->codec_id);
codecs[index].codec = avcodec_alloc_context3(codec);
if (!codecs[index].codec) {
fprintf(stderr, "context3 alloc for stream %d failed\n", (int)index);
return NULL;
}
if (avcodec_parameters_to_context(codecs[index].codec, avfc->streams[index]->codecpar) < 0) {
fprintf(stderr, "copy parameters to codec context for stream %d failed\n", (int)index);
avcodec_free_context(&codecs[index].codec);
return NULL;
}
if (!codec) {
fprintf(stderr, "decoder for codec_id:(0x%X) stream:(%d) not found\n", avfc->streams[index]->codecpar->codec_id, (int)index);;
return codecs[index].codec;
}
else
{
fprintf(stderr, "decoder for codec_id:(0x%X) stream:(%d) found\n", avfc->streams[index]->codecpar->codec_id, (int)index);;
}
int err = avcodec_open2(codecs[index].codec, codec, NULL);
if (averror(err, avcodec_open2)) {
fprintf(stderr, "open codec context for stream:(%d) failed}n", (int)index);
avcodec_free_context(&codecs[index].codec);
return NULL;
}
return codecs[index].codec;
#else
return avfc->streams[index]->codec;
#endif
}
bool Input::Play()
{
hasPlayThreadStarted = 1;
@@ -182,9 +223,11 @@ bool Input::Play()
restart_audio_resampling = true;
// clear streams
for (unsigned int i = 0; i < avfc->nb_streams; i++)
if (avfc->streams[i]->codec && avfc->streams[i]->codec->codec)
avcodec_flush_buffers(avfc->streams[i]->codec);
for (unsigned int i = 0; i < avfc->nb_streams; i++) {
AVCodecContext *avcctx = GetCodecContext(i);
if (avcctx && avcctx->codec)
avcodec_flush_buffers(avcctx);
}
player->output.ClearAudio();
player->output.ClearVideo();
}
@@ -194,19 +237,18 @@ bool Input::Play()
int err = av_read_frame(avfc, &packet);
if (err == AVERROR(EAGAIN)) {
#if (LIBAVFORMAT_VERSION_MAJOR == 57 && LIBAVFORMAT_VERSION_MINOR == 25)
av_packet_unref(&packet);
#else
av_free_packet(&packet);
#endif
continue;
}
if (averror(err, av_read_frame)) // EOF?
if (averror(err, av_read_frame)) { // EOF?
av_packet_unref(&packet);
break; // while
}
player->readCount += packet.size;
AVStream *stream = avfc->streams[packet.stream_index];
AVCodecContext *avcctx = GetCodecContext((unsigned int)stream->index);
Track *_videoTrack = videoTrack;
Track *_audioTrack = audioTrack;
Track *_subtitleTrack = subtitleTrack;
@@ -223,24 +265,25 @@ bool Input::Play()
}
if (!player->isBackWard) {
int64_t pts = calcPts(stream, packet.pts);
if (!player->output.Write(stream, &packet, _videoTrack ? pts : 0))
logprintf("writing data to audio device failed\n");
//if (!player->output.Write(stream, &packet, _videoTrack ? pts : 0)) // DBO: why pts only at video tracks ?
if (!player->output.Write(stream, &packet, pts))
logprintf("writing data to audio device failed\n");
}
audioSeen = true;
} else if (_subtitleTrack && (_subtitleTrack->stream == stream)) {
if (stream->codec->codec) {
if (avcctx->codec) {
AVSubtitle sub;
memset(&sub, 0, sizeof(sub));
int got_sub_ptr = 0;
err = avcodec_decode_subtitle2(stream->codec, &sub, &got_sub_ptr, &packet);
err = avcodec_decode_subtitle2(avcctx, &sub, &got_sub_ptr, &packet);
averror(err, avcodec_decode_subtitle2);
if (got_sub_ptr && sub.num_rects > 0) {
switch (sub.rects[0]->type) {
case SUBTITLE_TEXT: // FIXME?
case SUBTITLE_ASS:
dvbsub_ass_write(stream->codec, &sub, _subtitleTrack->pid);
dvbsub_ass_write(avcctx, &sub, _subtitleTrack->pid);
break;
case SUBTITLE_BITMAP: {
int64_t pts = calcPts(stream, packet.pts);
@@ -258,11 +301,8 @@ bool Input::Play()
teletext_write(_teletextTrack->pid, packet.data + 1, packet.size - 1);
}
#if (LIBAVFORMAT_VERSION_MAJOR == 57 && LIBAVFORMAT_VERSION_MINOR == 25)
av_packet_unref(&packet);
#else
av_free_packet(&packet);
#endif
} /* while */
if (player->abortRequested)
@@ -286,6 +326,7 @@ bool Input::Play()
return res;
}
#if LIBAVCODEC_VERSION_MAJOR < 58
static int lock_callback(void **mutex, enum AVLockOp op)
{
switch (op) {
@@ -306,6 +347,7 @@ static int lock_callback(void **mutex, enum AVLockOp op)
return -1;
}
}
#endif
bool Input::ReadSubtitle(const char *filename, const char *format, int pid)
{
@@ -332,8 +374,20 @@ bool Input::ReadSubtitle(const char *filename, const char *format, int pid)
return false;
}
AVCodecContext *c = subavfc->streams[0]->codec;
AVCodec *codec = avcodec_find_decoder(c->codec_id);
AVCodecContext *c = NULL;
AVCodec *codec = NULL;
#if (LIBAVFORMAT_VERSION_INT < AV_VERSION_INT( 57,25,101 ))
c = subavfc->streams[0]->codec;
#else
c = avcodec_alloc_context3(codec);
if (avcodec_parameters_to_context(c, subavfc->streams[0]->codecpar) < 0) {
avcodec_free_context(&c);
avformat_close_input(&subavfc);
avformat_free_context(subavfc);
return false;
}
#endif
codec = avcodec_find_decoder(c->codec_id);
if (!codec) {
avformat_free_context(subavfc);
return false;
@@ -355,13 +409,12 @@ bool Input::ReadSubtitle(const char *filename, const char *format, int pid)
avcodec_decode_subtitle2(c, &sub, &got_sub, &packet);
if (got_sub)
dvbsub_ass_write(c, &sub, pid);
#if (LIBAVFORMAT_VERSION_MAJOR == 57 && LIBAVFORMAT_VERSION_MINOR == 25)
av_packet_unref(&packet);
#else
av_free_packet(&packet);
#endif
}
avcodec_close(c);
#if (LIBAVFORMAT_VERSION_INT > AV_VERSION_INT( 57,25,100 ))
avcodec_free_context(&c);
#endif
avformat_close_input(&subavfc);
avformat_free_context(subavfc);
@@ -388,7 +441,9 @@ bool Input::Init(const char *filename, std::string headers)
{
bool find_info = true;
abortPlayback = false;
#if LIBAVCODEC_VERSION_MAJOR < 58
av_lockmgr_register(lock_callback);
#endif
#if ENABLE_LOGGING
av_log_set_flags(AV_LOG_SKIP_REPEATED);
av_log_set_level(AV_LOG_INFO);
@@ -414,8 +469,10 @@ bool Input::Init(const char *filename, std::string headers)
fprintf(stderr, "%s %s %d: %s\n", FILENAME, __func__, __LINE__, filename);
}
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)
avcodec_register_all();
av_register_all();
#endif
avformat_network_init();
videoTrack = NULL;
@@ -452,10 +509,8 @@ again:
avfc->iformat->flags |= AVFMT_SEEK_TO_PTS;
avfc->flags = AVFMT_FLAG_GENPTS;
if (player->noprobe) {
#if (LIBAVFORMAT_VERSION_MAJOR < 55) || \
(LIBAVFORMAT_VERSION_MAJOR == 55 && LIBAVFORMAT_VERSION_MINOR < 43) || \
(LIBAVFORMAT_VERSION_MAJOR == 55 && LIBAVFORMAT_VERSION_MINOR == 43 && LIBAVFORMAT_VERSION_MICRO < 100) || \
(LIBAVFORMAT_VERSION_MAJOR == 57 && LIBAVFORMAT_VERSION_MINOR == 25)
#if (LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(55, 43, 100)) || \
(LIBAVFORMAT_VERSION_INT > AV_VERSION_INT(57, 25, 0))
avfc->max_analyze_duration = 1;
#else
avfc->max_analyze_duration2 = 1;
@@ -527,13 +582,15 @@ bool Input::UpdateTracks()
for (unsigned int n = 0; n < avfc->nb_streams; n++) {
AVStream *stream = avfc->streams[n];
AVCodecContext *avcctx = GetCodecContext(n);
Track track;
track.stream = stream;
AVDictionaryEntry *lang = av_dict_get(stream->metadata, "language", NULL, 0);
track.title = lang ? lang->value : "";
if (!use_index_as_pid)
switch (stream->codec->codec_type) {
switch (avcctx->codec_type) {
case AVMEDIA_TYPE_VIDEO:
case AVMEDIA_TYPE_AUDIO:
case AVMEDIA_TYPE_SUBTITLE:
@@ -546,14 +603,14 @@ bool Input::UpdateTracks()
track.pid = use_index_as_pid ? n + 1: stream->id;
track.ac3flags = 0;
switch (stream->codec->codec_type) {
switch (avcctx->codec_type) {
case AVMEDIA_TYPE_VIDEO:
player->manager.addVideoTrack(track);
if (!videoTrack)
videoTrack = player->manager.getVideoTrack(track.pid);
break;
case AVMEDIA_TYPE_AUDIO:
switch(stream->codec->codec_id) {
switch(avcctx->codec_id) {
case AV_CODEC_ID_MP2:
track.ac3flags = 1;
break;
@@ -567,10 +624,10 @@ bool Input::UpdateTracks()
track.ac3flags = 4;
break;
case AV_CODEC_ID_AAC: {
unsigned int extradata_size = stream->codec->extradata_size;
unsigned int extradata_size = avcctx->extradata_size;
unsigned int object_type = 2;
if(extradata_size >= 2)
object_type = stream->codec->extradata[0] >> 3;
object_type = avcctx->extradata[0] >> 3;
if (extradata_size <= 1 || object_type == 1 || object_type == 5) {
fprintf(stderr, "use resampling for AAC\n");
track.ac3flags = 6;
@@ -597,10 +654,10 @@ bool Input::UpdateTracks()
audioTrack = player->manager.getAudioTrack(track.pid);
break;
case AVMEDIA_TYPE_SUBTITLE:
if (stream->codec->codec_id == AV_CODEC_ID_DVB_TELETEXT) {
if (avcctx->codec_id == AV_CODEC_ID_DVB_TELETEXT) {
std::string l = lang ? lang->value : "";
uint8_t *data = stream->codec->extradata;
int size = stream->codec->extradata_size;
uint8_t *data = avcctx->extradata;
int size = avcctx->extradata_size;
if (size > 0 && 2 * size - 1 == (int) l.length())
for (int i = 0; i < size; i += 2) {
track.title = l.substr(i * 2, 3);
@@ -610,22 +667,22 @@ bool Input::UpdateTracks()
player->manager.addTeletextTrack(track);
}
} else {
if (!stream->codec->codec) {
stream->codec->codec = avcodec_find_decoder(stream->codec->codec_id);
if (!stream->codec->codec)
if (!avcctx->codec) {
avcctx->codec = avcodec_find_decoder(avcctx->codec_id);
if (!avcctx->codec)
fprintf(stderr, "avcodec_find_decoder failed for subtitle track %d\n", n);
else {
int err = avcodec_open2(stream->codec, stream->codec->codec, NULL);
int err = avcodec_open2(avcctx, avcctx->codec, NULL);
if (averror(err, avcodec_open2))
stream->codec->codec = NULL;
avcctx->codec = NULL;
}
}
if (stream->codec->codec)
if (avcctx->codec)
player->manager.addSubtitleTrack(track);
}
break;
default:
fprintf(stderr, "not handled or unknown codec_type %d\n", stream->codec->codec_type);
fprintf(stderr, "not handled or unknown codec_type %d\n", avcctx->codec_type);
break;
}
}
@@ -657,8 +714,14 @@ bool Input::Stop()
if (avfc) {
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mutex);
for (unsigned int i = 0; i < avfc->nb_streams; i++)
for (unsigned int i = 0; i < avfc->nb_streams; i++) {
#if (LIBAVFORMAT_VERSION_INT > AV_VERSION_INT( 57,25,100 ))
if (codecs[i].codec)
avcodec_free_context(&codecs[i].codec);
#else
avcodec_close(avfc->streams[i]->codec);
#endif
}
avformat_close_input(&avfc);
}
@@ -705,7 +768,7 @@ bool Input::SwitchAudio(Track *track)
{
audioTrack = track;
player->output.SwitchAudio(track ? track : NULL);
// player->Seek(-5000, false);
player->Seek((int64_t)(-8 * AV_TIME_BASE), false);
return true;
}
@@ -763,11 +826,7 @@ bool Input::GetMetadata(std::vector<std::string> &keys, std::vector<std::string>
fwrite(pkt->data, pkt->size, 1, cover_art);
fclose(cover_art);
}
#if (LIBAVFORMAT_VERSION_MAJOR == 57 && LIBAVFORMAT_VERSION_MINOR == 25)
av_packet_unref(pkt);
#else
av_free_packet(pkt);
#endif
break;
}
}

View File

@@ -127,22 +127,20 @@ bool Output::Play()
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
AVCodecContext *avcc;
if (videoTrack && videoTrack->stream && videofd > -1 && (avcc = videoTrack->stream->codec)) {
videoWriter = Writer::GetWriter(avcc->codec_id, avcc->codec_type, videoTrack->ac3flags);
if (videoTrack && videoTrack->stream && videofd > -1 && get_codecpar(videoTrack->stream)) {
videoWriter = Writer::GetWriter(get_codecpar(videoTrack->stream)->codec_id, get_codecpar(videoTrack->stream)->codec_type, videoTrack->ac3flags);
videoWriter->Init(videofd, videoTrack->stream, player);
if (dioctl(videofd, VIDEO_SET_ENCODING, videoWriter->GetVideoEncoding(avcc->codec_id))
if (dioctl(videofd, VIDEO_SET_ENCODING, videoWriter->GetVideoEncoding(get_codecpar(videoTrack->stream)->codec_id))
|| dioctl(videofd, VIDEO_PLAY, NULL))
ret = false;
}
if (audioTrack && audioTrack->stream && audiofd > -1 && (avcc = audioTrack->stream->codec)) {
audioWriter = Writer::GetWriter(avcc->codec_id, avcc->codec_type, audioTrack->ac3flags);
if (audioTrack && audioTrack->stream && audiofd > -1 && get_codecpar(audioTrack->stream)) {
audioWriter = Writer::GetWriter(get_codecpar(audioTrack->stream)->codec_id, get_codecpar(audioTrack->stream)->codec_type, audioTrack->ac3flags);
audioWriter->Init(audiofd, audioTrack->stream, player);
audio_encoding_t audioEncoding = AUDIO_ENCODING_LPCMA;
if (audioTrack->ac3flags != 6)
audioEncoding = audioWriter->GetAudioEncoding(avcc->codec_id);
audioEncoding = audioWriter->GetAudioEncoding(get_codecpar(audioTrack->stream)->codec_id);
if (dioctl(audiofd, AUDIO_SET_ENCODING, audioEncoding)
|| dioctl(audiofd, AUDIO_PLAY, NULL))
ret = false;
@@ -311,15 +309,14 @@ bool Output::SwitchAudio(Track *track)
}
audioTrack = track;
if (track->stream) {
AVCodecContext *avcc = track->stream->codec;
if (!avcc)
if (!get_codecpar(audioTrack->stream))
return false;
audioWriter = Writer::GetWriter(avcc->codec_id, avcc->codec_type, audioTrack->ac3flags);
audioWriter = Writer::GetWriter(get_codecpar(audioTrack->stream)->codec_id, get_codecpar(audioTrack->stream)->codec_type, audioTrack->ac3flags);
audioWriter->Init(audiofd, audioTrack->stream, player);
if (audiofd > -1) {
audio_encoding_t audioEncoding = AUDIO_ENCODING_LPCMA;
if (audioTrack->ac3flags != 6)
audioEncoding = Writer::GetAudioEncoding(avcc->codec_id);
audioEncoding = Writer::GetAudioEncoding(get_codecpar(audioTrack->stream)->codec_id);
dioctl(audiofd, AUDIO_SET_ENCODING, audioEncoding);
dioctl(audiofd, AUDIO_PLAY, NULL);
}
@@ -338,13 +335,12 @@ bool Output::SwitchVideo(Track *track)
}
videoTrack = track;
if (track->stream) {
AVCodecContext *avcc = track->stream->codec;
if (!avcc)
if (!get_codecpar(videoTrack->stream))
return false;
videoWriter = Writer::GetWriter(avcc->codec_id, avcc->codec_type, videoTrack->type);
videoWriter = Writer::GetWriter(get_codecpar(videoTrack->stream)->codec_id, get_codecpar(videoTrack->stream)->codec_type, videoTrack->type);
videoWriter->Init(videofd, videoTrack->stream, player);
if (videofd > -1) {
dioctl(videofd, VIDEO_SET_ENCODING, Writer::GetVideoEncoding(avcc->codec_id));
dioctl(videofd, VIDEO_SET_ENCODING, Writer::GetVideoEncoding(get_codecpar(videoTrack->stream)->codec_id));
dioctl(videofd, VIDEO_PLAY, NULL);
}
}
@@ -353,7 +349,7 @@ bool Output::SwitchVideo(Track *track)
bool Output::Write(AVStream *stream, AVPacket *packet, int64_t pts)
{
switch (stream->codec->codec_type) {
switch (get_codecpar(stream)->codec_type) {
case AVMEDIA_TYPE_VIDEO: {
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
return videofd > -1 && videoWriter && videoWriter->Write(packet, pts);

View File

@@ -317,7 +317,9 @@ bool Player::SlowMotion(int repeats)
bool Player::Seek(int64_t pos, bool absolute)
{
output.Clear();
if (GetVideoPid())
/* Don't Clear if no video track */
output.Clear();
return input.Seek(pos, absolute);
}
@@ -347,7 +349,7 @@ bool Player::SwitchVideo(int pid)
bool Player::SwitchAudio(int pid)
{
Track *track = manager.getAudioTrack(pid);
return input.SwitchAudio(track);
return track ? input.SwitchAudio(track) : false;
}
bool Player::SwitchSubtitle(int pid)

View File

@@ -89,8 +89,8 @@ bool WriterDIVX::Write(AVPacket *packet, int64_t pts)
iov[ic++].iov_len = FakeHeaderLength;
if (initialHeader) {
iov[ic].iov_base = stream->codec->extradata;
iov[ic++].iov_len = stream->codec->extradata_size;
iov[ic].iov_base = get_codecpar(stream)->extradata;
iov[ic++].iov_len = get_codecpar(stream)->extradata_size;
initialHeader = false;
}
iov[ic].iov_base = packet->data;

View File

@@ -83,9 +83,9 @@ bool WriterH264::Write(AVPacket *packet, int64_t pts)
unsigned int len = 0;
if (initialHeader) {
initialHeader = false;
iov[ic].iov_base = stream->codec->extradata;
iov[ic++].iov_len = stream->codec->extradata_size;
len += stream->codec->extradata_size;
iov[ic].iov_base = get_codecpar(stream)->extradata;
iov[ic++].iov_len = get_codecpar(stream)->extradata_size;
len += get_codecpar(stream)->extradata_size;
}
iov[ic].iov_base = packet->data;
iov[ic++].iov_len = packet->size;
@@ -104,7 +104,7 @@ bool WriterH264::Write(AVPacket *packet, int64_t pts)
// convert NAL units without sync byte sequence to byte-stream format
if (initialHeader) {
avcC_t *avcCHeader = (avcC_t *) stream->codec->extradata;
avcC_t *avcCHeader = (avcC_t *) get_codecpar(stream)->extradata;
if (!avcCHeader) {
fprintf(stderr, "stream->codec->extradata == NULL\n");

View File

@@ -236,7 +236,7 @@ bool WriterPCM::Write(AVPacket *packet, int64_t pts)
return true;
}
AVCodecContext *c = stream->codec;
AVCodecContext *c = player->input.GetCodecContext((unsigned int)stream->index);
if (restart_audio_resampling) {
restart_audio_resampling = false;
@@ -251,6 +251,7 @@ bool WriterPCM::Write(AVPacket *packet, int64_t pts)
decoded_frame = NULL;
}
#if (LIBAVFORMAT_VERSION_INT < AV_VERSION_INT( 57,25,101 ))
AVCodec *codec = avcodec_find_decoder(c->codec_id);
if (!codec) {
fprintf(stderr, "%s %d: avcodec_find_decoder(%llx)\n", __func__, __LINE__, (unsigned long long) c->codec_id);
@@ -261,6 +262,7 @@ bool WriterPCM::Write(AVPacket *packet, int64_t pts)
fprintf(stderr, "%s %d: avcodec_open2 failed\n", __func__, __LINE__);
return false;
}
#endif
}
if (!swr) {
@@ -313,7 +315,6 @@ bool WriterPCM::Write(AVPacket *packet, int64_t pts)
unsigned int packet_size = packet->size;
while (packet_size > 0 || (!packet_size && !packet->data)) {
int got_frame = 0;
if (!decoded_frame) {
if (!(decoded_frame = av_frame_alloc())) {
@@ -323,6 +324,9 @@ bool WriterPCM::Write(AVPacket *packet, int64_t pts)
} else
av_frame_unref(decoded_frame);
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57,37,100)
int got_frame = 0;
int len = avcodec_decode_audio4(c, decoded_frame, &got_frame, packet);
if (len < 0) {
restart_audio_resampling = true;
@@ -337,8 +341,37 @@ bool WriterPCM::Write(AVPacket *packet, int64_t pts)
break;
continue;
}
#else
int ret = avcodec_send_packet(c, packet);
if (ret < 0) {
if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) {
restart_audio_resampling = true;
break;
}
}
if (ret >= 0) {
packet_size = 0;
}
ret = avcodec_receive_frame(c, decoded_frame);
if (ret < 0) {
if (ret == AVERROR_EOF) {
restart_audio_resampling = true;
break;
}
if (ret != AVERROR(EAGAIN)) {
break;
}
else {
continue;
}
}
#endif
#if (LIBAVUTIL_VERSION_MAJOR < 54)
pts = player->input.calcPts(stream, av_frame_get_best_effort_timestamp(decoded_frame));
#else
pts = player->input.calcPts(stream, decoded_frame->best_effort_timestamp);
#endif
int in_samples = decoded_frame->nb_samples;
int out_samples = av_rescale_rnd(swr_get_delay(swr, c->sample_rate) + in_samples, out_sample_rate, c->sample_rate, AV_ROUND_UP);
@@ -360,6 +393,9 @@ bool WriterPCM::Write(AVPacket *packet, int64_t pts)
break;
}
}
av_frame_free(&decoded_frame);
return !packet_size;
}

View File

@@ -107,14 +107,14 @@ bool WriterVC1::Write(AVPacket *packet, int64_t pts)
PesPtr += WMV3_PRIVATE_DATA_LENGTH;
/* Metadata Header Struct A */
*PesPtr++ = (stream->codec->height >> 0) & 0xff;
*PesPtr++ = (stream->codec->height >> 8) & 0xff;
*PesPtr++ = (stream->codec->height >> 16) & 0xff;
*PesPtr++ = stream->codec->height >> 24;
*PesPtr++ = (stream->codec->width >> 0) & 0xff;
*PesPtr++ = (stream->codec->width >> 8) & 0xff;
*PesPtr++ = (stream->codec->width >> 16) & 0xff;
*PesPtr++ = stream->codec->width >> 24;
*PesPtr++ = (get_codecpar(stream)->height >> 0) & 0xff;
*PesPtr++ = (get_codecpar(stream)->height >> 8) & 0xff;
*PesPtr++ = (get_codecpar(stream)->height >> 16) & 0xff;
*PesPtr++ = get_codecpar(stream)->height >> 24;
*PesPtr++ = (get_codecpar(stream)->width >> 0) & 0xff;
*PesPtr++ = (get_codecpar(stream)->width >> 8) & 0xff;
*PesPtr++ = (get_codecpar(stream)->width >> 16) & 0xff;
*PesPtr++ = get_codecpar(stream)->width >> 24;
PesPtr += 12; /* Skip flag word and Struct B first 8 bytes */
@@ -132,8 +132,8 @@ bool WriterVC1::Write(AVPacket *packet, int64_t pts)
/* For VC1 the codec private data is a standard vc1 sequence header so we just copy it to the output */
iov[0].iov_base = PesHeader;
iov[1].iov_base = stream->codec->extradata;
iov[1].iov_len = stream->codec->extradata_size;
iov[1].iov_base = get_codecpar(stream)->extradata;
iov[1].iov_len = get_codecpar(stream)->extradata_size;
iov[0].iov_len = InsertPesHeader(PesHeader, iov[1].iov_len, VC1_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0);
if (writev(fd, iov, 2) < 0)
return false;

View File

@@ -88,20 +88,20 @@ bool WriterWMV::Write(AVPacket *packet, int64_t pts)
PesPtr += METADATA_STRUCT_C_START;
uint8_t privateData[WMV3_PRIVATE_DATA_LENGTH] = { 0 };
memcpy(privateData, stream->codec->extradata, stream->codec->extradata_size > WMV3_PRIVATE_DATA_LENGTH ? WMV3_PRIVATE_DATA_LENGTH : stream->codec->extradata_size);
memcpy(privateData, get_codecpar(stream)->extradata, get_codecpar(stream)->extradata_size > WMV3_PRIVATE_DATA_LENGTH ? WMV3_PRIVATE_DATA_LENGTH : get_codecpar(stream)->extradata_size);
memcpy(PesPtr, privateData, WMV3_PRIVATE_DATA_LENGTH);
PesPtr += WMV3_PRIVATE_DATA_LENGTH;
/* Metadata Header Struct A */
*PesPtr++ = (stream->codec->height >> 0) & 0xff;
*PesPtr++ = (stream->codec->height >> 8) & 0xff;
*PesPtr++ = (stream->codec->height >> 16) & 0xff;
*PesPtr++ = stream->codec->height >> 24;
*PesPtr++ = (stream->codec->width >> 0) & 0xff;
*PesPtr++ = (stream->codec->width >> 8) & 0xff;
*PesPtr++ = (stream->codec->width >> 16) & 0xff;
*PesPtr++ = stream->codec->width >> 24;
*PesPtr++ = (get_codecpar(stream)->height >> 0) & 0xff;
*PesPtr++ = (get_codecpar(stream)->height >> 8) & 0xff;
*PesPtr++ = (get_codecpar(stream)->height >> 16) & 0xff;
*PesPtr++ = get_codecpar(stream)->height >> 24;
*PesPtr++ = (get_codecpar(stream)->width >> 0) & 0xff;
*PesPtr++ = (get_codecpar(stream)->width >> 8) & 0xff;
*PesPtr++ = (get_codecpar(stream)->width >> 16) & 0xff;
*PesPtr++ = get_codecpar(stream)->width >> 24;
PesPtr += 12; /* Skip flag word and Struct B first 8 bytes */

View File

@@ -3,7 +3,7 @@ AM_CFLAGS = -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOUR
CXXFLAGS = -Wall
noinst_LTLIBRARIES = libeplayer3_arm.la
noinst_LTLIBRARIES = libeplayer3.la
AM_CPPFLAGS = -I$(srcdir)/include
AM_CPPFLAGS += -I$(top_srcdir)/include
@@ -59,11 +59,11 @@ SOURCE_FILES += \
output/writer/mipsel/wmv.c \
output/writer/mipsel/vc1.c
libeplayer3_arm_la_SOURCES = $(SOURCE_FILES)
libeplayer3_la_SOURCES = $(SOURCE_FILES)
LIBEPLAYER3_LIBS = libeplayer3_arm.la -lpthread -lavformat -lavcodec -lavutil -lswresample
LIBEPLAYER3_LIBS = libeplayer3.la -lpthread -lavformat -lavcodec -lavutil -lswresample
bin_PROGRAMS = eplayer3
eplayer3_SOURCES = main/exteplayer.c
eplayer3_LDADD = $(LIBEPLAYER3_LIBS)
eplayer3_DEPENDENCIES = libeplayer3_arm.la
#bin_PROGRAMS = eplayer3
#eplayer3_SOURCES = main/exteplayer.c
#eplayer3_LDADD = $(LIBEPLAYER3_LIBS)
#eplayer3_DEPENDENCIES = libeplayer3.la

View File

@@ -125,8 +125,8 @@ static int32_t container_ffmpeg_seek(Context_t *context, int64_t sec, uint8_t ab
//static int32_t container_ffmpeg_seek_rel(Context_t *context, off_t pos, int64_t pts, int64_t sec);
static int32_t container_ffmpeg_get_length(Context_t *context, int64_t *length);
static int64_t calcPts(uint32_t avContextIdx, AVStream *stream, int64_t pts);
static int32_t container_ffmpeg_stop(Context_t *context);
static int64_t doCalcPts(int64_t start_time, const AVRational time_base, int64_t pts);
static int32_t container_ffmpeg_stop(Context_t *context);
/* Progressive playback means that we play local file
* but this local file can grows up, for example
@@ -308,7 +308,7 @@ static char *Codec2Encoding(int32_t codec_id, int32_t media_type, uint8_t *extra
case AV_CODEC_ID_MPEG2VIDEO:
return "V_MPEG2";
case AV_CODEC_ID_MJPEG:
return "V_MJPEG";
return NULL;//"V_MJPEG";
case AV_CODEC_ID_H263:
case AV_CODEC_ID_H263P:
case AV_CODEC_ID_H263I:
@@ -1772,9 +1772,9 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, uin
if (2 == haveNativeProto)
{
filename = malloc(strlen(baseUri) + 2 + 1);
strncpy(filename, "ff", 2);
strcpy(filename + 2, baseUri);
int len = strlen(baseUri) + 2 + 1;
filename = malloc(len);
snprintf(filename,len,"ff%s",baseUri);
free(baseUri);
// memory leak, only once, so does not matter
}
@@ -1883,6 +1883,10 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, uin
avContextTab[AVIdx]->pb->read_packet = ffmpeg_read_wrapper;
}
}
if (avio_opts != NULL)
{
av_dict_free(&avio_opts);
}
//for buffered io (end)
return 0;
@@ -1999,7 +2003,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32
#endif
ffmpeg_printf(20, "dump format\n");
if((avContextTab[0] != NULL) && (FFMPEG_DEBUG_LEVEL > 0))
if ((avContextTab[0] != NULL) && (FFMPEG_DEBUG_LEVEL > 0))
av_dump_format(avContextTab[0], 0, filename, 0);
@@ -3136,7 +3140,7 @@ static int32_t container_ffmpeg_switch_audio(Context_t *context, int32_t *arg __
releaseMutex(__FILE__, __FUNCTION__, __LINE__);
/* Hellmaster1024: nothing to do here! */
int64_t sec = -1;
int64_t sec = -3;
context->playback->Command(context, PLAYBACK_SEEK, (void *)&sec);
return cERR_CONTAINER_FFMPEG_NO_ERROR;
}
@@ -3283,6 +3287,52 @@ static int container_ffmpeg_get_metadata(Context_t *context, char ***p)
*pp++ = NULL;
*pp = NULL;
// find the first attached picture, if available
unlink("/tmp/.id3coverart");
for(unsigned int i = 0; i < avContextTab[0]->nb_streams; i++) {
if (avContextTab[0]->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC) {
AVPacket *pkt = NULL;
pkt = av_packet_clone(&avContextTab[0]->streams[i]->attached_pic);
FILE *cover_art = fopen("/tmp/.id3coverart", "wb");
if (cover_art) {
fwrite(pkt->data, pkt->size, 1, cover_art);
fclose(cover_art);
}
av_packet_free(&pkt);
break;
}
}
return cERR_CONTAINER_FFMPEG_NO_ERROR;
}
static int container_ffmpeg_av_context(Context_t *context, AVFormatContext *ext_avContext)
{
if (!context)
{
fprintf(stderr, "BUG %s:%d\n", __func__, __LINE__);
return cERR_CONTAINER_FFMPEG_ERR;
}
if (avContextTab[0] != NULL)
{
getMutex(__FILE__, __FUNCTION__, __LINE__);
ext_avContext->streams = avContextTab[0]->streams;
ext_avContext->nb_streams = avContextTab[0]->nb_streams;
releaseMutex(__FILE__, __FUNCTION__, __LINE__);
}
else if ((avContextTab[0] == NULL) && (avContextTab[1] != NULL))
{
getMutex(__FILE__, __FUNCTION__, __LINE__);
ext_avContext->streams = avContextTab[1]->streams;
ext_avContext->nb_streams = avContextTab[1]->nb_streams;
releaseMutex(__FILE__, __FUNCTION__, __LINE__);
}
else
{
ext_avContext->streams = NULL;
ext_avContext->nb_streams = NULL;
}
return cERR_CONTAINER_FFMPEG_NO_ERROR;
}
@@ -3379,6 +3429,11 @@ static int32_t Command(Context_t *context, ContainerCmd_t command, void *argumen
ret = container_ffmpeg_get_metadata(context, (char ***)argument);
break;
}
case CONTAINER_GET_AVFCONTEXT:
{
ret = container_ffmpeg_av_context(context, (AVFormatContext *)argument);
break;
}
default:
ffmpeg_err("ContainerCmd %d not supported!\n", command);
ret = cERR_CONTAINER_FFMPEG_ERR;

View File

@@ -139,7 +139,7 @@ static void align_bits(BR *p)
}
}
static int __inline get_br_pos(BR *p)
static inline int get_br_pos(BR *p)
{
return (p->read << 3) + p->bitoffset;
}
@@ -150,7 +150,7 @@ typedef struct _VLCtab
int n;
} VLCtab;
static int __inline get_vlc(BR *br, const VLCtab *table, int bits, int max_depth)
static inline int get_vlc(BR *br, const VLCtab *table, int bits, int max_depth)
{
int n, index, nb_bits, code;
index = show_bits(br, bits);
@@ -171,7 +171,7 @@ static int __inline get_vlc(BR *br, const VLCtab *table, int bits, int max_depth
return code;
}
static int __inline get_vlcdec(BR *p, const VLCtab *table, int bits, int max_depth, VLCDEC *vlcdec)
static inline int get_vlcdec(BR *p, const VLCtab *table, int bits, int max_depth, VLCDEC *vlcdec)
{
int pos = get_br_pos(p);
uint32 show = show_bits(p, 24);

View File

@@ -40,21 +40,21 @@ typedef struct _BW
} BW;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void __inline clear_bw(BW *p)
static inline void clear_bw(BW *p)
{
p->pos = 0;
p->bitoffset = 0;
p->tmp = 0;
}
static void __inline init_bw(BW *p, uint8 *buf, uint32 size)
static inline void init_bw(BW *p, uint8 *buf, uint32 size)
{
p->buf = buf;
p->size = size;
clear_bw(p);
}
static void __inline forword_bits(BW *p, uint32 bits)
static inline void forword_bits(BW *p, uint32 bits)
{
p->bitoffset += bits;
@@ -70,7 +70,7 @@ static void __inline forword_bits(BW *p, uint32 bits)
}
}
static void __inline put_bits(BW *p, uint32 bits, uint32 value)
static inline void put_bits(BW *p, uint32 bits, uint32 value)
{
uint32 shift = 32 - p->bitoffset - bits;
@@ -90,7 +90,7 @@ static void __inline put_bits(BW *p, uint32 bits, uint32 value)
}
}
static void __inline pad_to_boundary(BW *p)
static inline void pad_to_boundary(BW *p)
{
uint32 bits = 8 - (p->bitoffset % 8);
if (bits < 8)
@@ -99,7 +99,7 @@ static void __inline pad_to_boundary(BW *p)
}
}
static void __inline flash_bw(BW *p)
static inline void flash_bw(BW *p)
{
pad_to_boundary(p);
@@ -120,7 +120,6 @@ static void __inline flash_bw(BW *p)
p->buf[p->pos++] = (p->tmp >> 8) & 0xff;
break;
default:
// fprintf(stderr, "flash_bw error!(%d)\n", p->bitoffset);
break;
}
@@ -128,18 +127,18 @@ static void __inline flash_bw(BW *p)
p->bitoffset = 0;
}
static uint32 __inline get_bw_pos(BW *p)
static inline uint32 get_bw_pos(BW *p)
{
return p->pos * 8 + p->bitoffset;
}
static void __inline put_vlcdec(BW *bw, VLCDEC *vlcdec)
static inline void put_vlcdec(BW *bw, VLCDEC *vlcdec)
{
put_bits(bw, vlcdec->bits, vlcdec->value);
}
// M4V ADDED
static void __inline m4v_stuffing(BW *p)
static inline void m4v_stuffing(BW *p)
{
int length;

View File

@@ -40,7 +40,7 @@ static const uint8 mpeg4_c_dc_scale_table[32] =
0, 8, 8, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25
};
static int __inline get_pred(int *dc_cur, int stride, int scale)
static inline int get_pred(int *dc_cur, int stride, int scale)
{
/* B C
A X */
@@ -62,7 +62,7 @@ static int __inline get_pred(int *dc_cur, int stride, int scale)
return (pred + (scale >> 1)) / scale;
}
static void __inline set_dc_to_dc_cur(int *dc_cur, int level, int scale)
static inline void set_dc_to_dc_cur(int *dc_cur, int level, int scale)
{
level *= scale;
if (level & (~2047))
@@ -88,7 +88,7 @@ static int *get_dc_cur(M4V_DCPRED *pred, int mb_x, int mb_y, int n)
}
}
static int __inline get_scale(M4V_DCPRED *pred, int n)
static inline int get_scale(M4V_DCPRED *pred, int n)
{
if (n < 4)
{

View File

@@ -174,7 +174,7 @@ static const VLCtab vlc_table_mv[] = //mv_vlc: table_size=538 table_allocated=10
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int __inline decode_DC(BR *p)
static inline int decode_DC(BR *p)
{
int level = get_bits(p, 8);
if ((level & 0x7f) == 0)
@@ -188,7 +188,7 @@ static int __inline decode_DC(BR *p)
return level;
}
static int __inline decode_AC(BR *p, BLOCK *block, int escape_type, int i)
static inline int decode_AC(BR *p, BLOCK *block, int escape_type, int i)
{
int code, run, level, last, sign;
@@ -253,7 +253,7 @@ static int __inline decode_AC(BR *p, BLOCK *block, int escape_type, int i)
return 0;
}
static int __inline decode_intra_block(BR *p, BLOCK *block, int escape_type, int coded)
static inline int decode_intra_block(BR *p, BLOCK *block, int escape_type, int coded)
{
int level = decode_DC(p);
if (level < 0)
@@ -274,7 +274,7 @@ static int __inline decode_intra_block(BR *p, BLOCK *block, int escape_type, int
return 0;
}
static int __inline decode_inter_block(BR *p, BLOCK *block, int escape_type, int coded)
static inline int decode_inter_block(BR *p, BLOCK *block, int escape_type, int coded)
{
block->last_index = -1;
@@ -287,7 +287,7 @@ static int __inline decode_inter_block(BR *p, BLOCK *block, int escape_type, int
return 0;
}
static int __inline get_intra_MCBPC(BR *br)
static inline int get_intra_MCBPC(BR *br)
{
int cbpc;
do
@@ -299,7 +299,7 @@ static int __inline get_intra_MCBPC(BR *br)
return cbpc;
}
static int __inline get_inter_MCBPC(BR *br)
static inline int get_inter_MCBPC(BR *br)
{
int cbpc;
do
@@ -316,18 +316,18 @@ static int __inline get_inter_MCBPC(BR *br)
return cbpc;
}
static int __inline get_cbpy(BR *br)
static inline int get_cbpy(BR *br)
{
return get_vlc(br, vlc_table_cbpy, 6, 1);
}
static int __inline decode_dquant(BR *p)
static inline int decode_dquant(BR *p)
{
static const int table[4] = { -1, -2, 1, 2 };
return table[get_bits(p, 2)];
}
static int __inline decode_motion(BR *br, VLCDEC *vlcdec)
static inline int decode_motion(BR *br, VLCDEC *vlcdec)
{
int tmp;
int code = get_vlcdec(br, vlc_table_mv, 9, 2, vlcdec);
@@ -353,7 +353,7 @@ static int __inline decode_motion(BR *br, VLCDEC *vlcdec)
return 0;
}
static int __inline decode_intra_mb_internal(BR *p, MICROBLOCK *mb, int escape_type, int qscale, int cbpc, int dquant)
static inline int decode_intra_mb_internal(BR *p, MICROBLOCK *mb, int escape_type, int qscale, int cbpc, int dquant)
{
int cbpy, cbp;
int i;
@@ -382,7 +382,7 @@ static int __inline decode_intra_mb_internal(BR *p, MICROBLOCK *mb, int escape_t
return 0;
}
static int __inline decode_inter_mb_internal(BR *p, MICROBLOCK *mb, int escape_type, int qscale, int cbpc, int dquant)
static inline int decode_inter_mb_internal(BR *p, MICROBLOCK *mb, int escape_type, int qscale, int cbpc, int dquant)
{
int cbpy, cbp;
int i;
@@ -510,9 +510,6 @@ int decode_picture_header(BR *p, PICTURE *picture)
picture->escape_type = tmp;
picture->frame_number = get_bits(p, 8);
// printf("picture_format: %d\n", tmp);
// printf("picture_number: %d\n", get_bits(p, 8));
tmp = get_bits(p, 3);
switch (tmp)
{

View File

@@ -60,7 +60,7 @@ static const uint32 vlce_inter_MCBPC_bits[28] =
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void __inline encode_DC(BW *p, int level, int n)
static inline void encode_DC(BW *p, int level, int n)
{
if (level < -255 || level > 255) printf("dc overflow\n");
@@ -111,7 +111,7 @@ static void __inline encode_DC(BW *p, int level, int n)
}
static void __inline encode_escape_3(BW *p, int last, int run, int level)
static inline void encode_escape_3(BW *p, int last, int run, int level)
{
#if 0
put_bits(p,
@@ -130,7 +130,7 @@ static void __inline encode_escape_3(BW *p, int last, int run, int level)
#define UNI_MPEG4_ENC_INDEX(last, run, level) ((last)*128*64 + (run)*128 + (level))
static void __inline encode_AC(BW *p, M4V_BLOCK *block, int intra)
static inline void encode_AC(BW *p, M4V_BLOCK *block, int intra)
{
int i = intra;
int last_index = block->last_index;
@@ -277,50 +277,50 @@ esc3:
}
static void __inline encode_intra_block(BW *bw, M4V_BLOCK *block, int n)
static inline void encode_intra_block(BW *bw, M4V_BLOCK *block, int n)
{
encode_DC(bw, block->block[0], n);
encode_AC(bw, block, 1);
}
static void __inline encode_inter_block(BW *bw, M4V_BLOCK *block)
static inline void encode_inter_block(BW *bw, M4V_BLOCK *block)
{
encode_AC(bw, block, 0);
}
// same as H.263
static void __inline encode_intra_I_MCBPC(BW *bw, int cbpc)
static inline void encode_intra_I_MCBPC(BW *bw, int cbpc)
{
put_bits(bw, vlce_intra_MCBPC_bits[cbpc], vlce_intra_MCBPC_code[cbpc]);
}
// same as H.263
static void __inline encode_intra_P_MCBPC(BW *bw, int cbpc)
static inline void encode_intra_P_MCBPC(BW *bw, int cbpc)
{
put_bits(bw, vlce_inter_MCBPC_bits[cbpc + 4], vlce_inter_MCBPC_code[cbpc + 4]);
}
// same as H.263
static void __inline encode_inter_16x16_MCBPC(BW *bw, int cbpc)
static inline void encode_inter_16x16_MCBPC(BW *bw, int cbpc)
{
put_bits(bw, vlce_inter_MCBPC_bits[cbpc], vlce_inter_MCBPC_code[cbpc]);
}
// same as H.263
static void __inline encode_inter_8x8_MCBPC(BW *bw, int cbpc)
static inline void encode_inter_8x8_MCBPC(BW *bw, int cbpc)
{
put_bits(bw, vlce_inter_MCBPC_bits[cbpc + 16], vlce_inter_MCBPC_code[cbpc + 16]);
}
// same as H.263
static void __inline encode_cbpy(BW *bw, int cbpy)
static inline void encode_cbpy(BW *bw, int cbpy)
{
put_bits(bw, vlce_cbpy_bits[cbpy], vlce_cbpy_code[cbpy]);
}
// same as H.263
static void __inline encode_dquant(BW *bw, int dquant)
static inline void encode_dquant(BW *bw, int dquant)
{
const uint32 dquant_code[5] = {1, 0, -1, 2, 3};
if (dquant)
@@ -330,7 +330,7 @@ static void __inline encode_dquant(BW *bw, int dquant)
}
// same as FLV
static void __inline encode_motion(BW *bw, VLCDEC *mv_x, VLCDEC *mv_y)
static inline void encode_motion(BW *bw, VLCDEC *mv_x, VLCDEC *mv_y)
{
put_vlcdec(bw, mv_x);
if (mv_x->bits_ex)
@@ -354,7 +354,7 @@ static void __inline encode_motion(BW *bw, VLCDEC *mv_x, VLCDEC *mv_y)
}
// same as FLV
static void __inline encode_mb_inter_internal(BW *bw, M4V_MICROBLOCK *mb)
static inline void encode_mb_inter_internal(BW *bw, M4V_MICROBLOCK *mb)
{
int cbp = 0, cbpc, cbpy;
int i;
@@ -398,7 +398,7 @@ static void __inline encode_mb_inter_internal(BW *bw, M4V_MICROBLOCK *mb)
}
}
static void __inline encode_mb_intra_internal(BW *bw, M4V_MICROBLOCK *mb, int iframe)
static inline void encode_mb_intra_internal(BW *bw, M4V_MICROBLOCK *mb, int iframe)
{
int cbp = 0, cbpc, cbpy;
int i;
@@ -438,7 +438,7 @@ static void __inline encode_mb_intra_internal(BW *bw, M4V_MICROBLOCK *mb, int if
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int __inline encode_vo_header(BW *p)
static inline int encode_vo_header(BW *p)
{
put_bits(p, 16, 0);
put_bits(p, 16, VOS_STARTCODE);
@@ -459,7 +459,7 @@ static int __inline encode_vo_header(BW *p)
return 0;
}
static int __inline encode_vol_header(BW *p, M4V_VOL *vol)
static inline int encode_vol_header(BW *p, M4V_VOL *vol)
{
const int vo_number = 0;
const int vol_number = 0;
@@ -507,7 +507,7 @@ static int __inline encode_vol_header(BW *p, M4V_VOL *vol)
return 0;
}
static int __inline encode_vop_header(BW *p, M4V_VOP *vop, int time_bits, int vop_not_coded)
static inline int encode_vop_header(BW *p, M4V_VOP *vop, int time_bits, int vop_not_coded)
{
// static int time_old = 0;
@@ -572,7 +572,7 @@ static int __inline encode_vop_header(BW *p, M4V_VOP *vop, int time_bits, int vo
return 0;
}
static __inline int encode_gop_header(BW *bw, uint32 time_ms)
static inline int encode_gop_header(BW *bw, uint32 time_ms)
{
int sec, min, hour;
@@ -600,7 +600,7 @@ static __inline int encode_gop_header(BW *bw, uint32 time_ms)
return 0;
}
static int __inline encode_user_header(BW *p)
static inline int encode_user_header(BW *p)
{
put_bits(p, 16, 0);
put_bits(p, 16, USERDATA_STARTCODE);

View File

@@ -25,7 +25,8 @@ typedef enum
CONTAINER_GET_BUFFER_SIZE,
CONTAINER_GET_BUFFER_STATUS,
CONTAINER_STOP_BUFFER,
CONTAINER_GET_METADATA
CONTAINER_GET_METADATA,
CONTAINER_GET_AVFCONTEXT
} ContainerCmd_t;
struct Context_s;

Some files were not shown because too many files have changed in this diff Show More