mirror of
https://github.com/tuxbox-neutrino/libstb-hal.git
synced 2025-08-27 15:33:00 +02:00
Compare commits
92 Commits
v1.2.0-mpx
...
v1.4.0
Author | SHA1 | Date | |
---|---|---|---|
|
593c903846 | ||
|
f2551c4866 | ||
|
5a44386b34 | ||
|
a3e139776f | ||
|
f74c04e03e | ||
|
4a98c127e2 | ||
|
3e49c20f4c | ||
|
3084287bd1 | ||
|
f6cf97a321 | ||
|
e1c1c07b0d | ||
|
ecb34f1cd1 | ||
![]() |
65aee42473 | ||
|
87b90f25ff | ||
|
e21785e7d0 | ||
|
2ec2c1f97c | ||
|
2d58382cdf | ||
|
cf9f93f459 | ||
|
2fbfd158df | ||
|
801f496c2d | ||
|
ba934dd995 | ||
|
6137874561 | ||
|
162be459ac | ||
|
349cb2dbd4 | ||
|
aec6e74897 | ||
|
e52a31f89c | ||
|
731ed1ea89 | ||
|
aaf845a711 | ||
|
bfc3b5f9d0 | ||
|
89bc44dc26 | ||
|
cdf663d6b9 | ||
|
f971434ab3 | ||
|
55839b5f87 | ||
|
67110fb054 | ||
|
480d23dc30 | ||
![]() |
566ccea279 | ||
|
a5fe472896 | ||
|
6b15c22726 | ||
|
f9bb987a43 | ||
![]() |
8f53e0d2d9 | ||
|
64d853f245 | ||
|
d0c12909c9 | ||
|
1b4c5dc1f8 | ||
|
f4bc510536 | ||
|
7cab06c525 | ||
|
a9251b30d1 | ||
|
e22c3033af | ||
|
83437c3656 | ||
|
5e3736a0a8 | ||
|
9a9372931a | ||
|
0e82fc5325 | ||
|
3c2ccc6fee | ||
|
34fc6368c4 | ||
|
b6fe299ee6 | ||
![]() |
3d6077b3af | ||
|
660c99317c | ||
|
1db0ffb694 | ||
|
0875e2c853 | ||
|
f14212783b | ||
|
c14601465a | ||
|
1920c37be5 | ||
![]() |
8658177951 | ||
|
6eb082c12a | ||
|
a76f914d9b | ||
|
32361d734e | ||
|
fd8cc781dd | ||
|
52213f9a21 | ||
|
9c422e5713 | ||
|
84ad5a2019 | ||
|
8ff9d03679 | ||
|
5791880e4c | ||
|
60f6a1f4be | ||
|
ed84d0ac6e | ||
|
92f912e541 | ||
|
5802a2ed1e | ||
|
7f329670fc | ||
|
7a650421bf | ||
|
fb8bb36cf7 | ||
|
15ed156bd3 | ||
|
6e45d7affa | ||
|
0f85aa4f60 | ||
|
69a371a709 | ||
|
f26097e1fc | ||
|
5979389a2c | ||
|
c4e474a48e | ||
|
db244f0b8a | ||
|
c25f68eda1 | ||
|
68fa79b83f | ||
|
3b0bad6f54 | ||
|
4d6eef9433 | ||
|
f0f1a282bf | ||
|
603fba2500 | ||
|
639762e1b3 |
38
Makefile.am
38
Makefile.am
@@ -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
|
||||
|
99
acinclude.m4
99
acinclude.m4
@@ -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
|
||||
|
11
autogen.sh
11
autogen.sh
@@ -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
|
||||
|
@@ -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 += \
|
||||
|
146
common/ca_ci.cpp
146
common/ca_ci.cpp
@@ -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
|
||||
|
11
configure.ac
11
configure.ac
@@ -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
|
||||
])
|
||||
|
||||
|
@@ -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"
|
||||
|
@@ -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();
|
||||
|
@@ -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);
|
||||
|
@@ -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"
|
||||
|
@@ -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; };
|
||||
|
@@ -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
|
||||
{
|
||||
|
@@ -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];
|
||||
|
@@ -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"
|
||||
|
@@ -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"
|
||||
|
@@ -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"
|
||||
|
@@ -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 += \
|
||||
|
@@ -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);
|
||||
|
@@ -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)
|
||||
|
@@ -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 ∩︀
|
||||
}
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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 ¤t)
|
||||
{
|
||||
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;
|
||||
|
@@ -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 ¤t);
|
||||
void SetTitle(int title);
|
||||
};
|
||||
|
||||
class netlink_event : public OpenThreads::Thread
|
||||
|
@@ -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
|
||||
|
@@ -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 = "");
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
@@ -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__
|
519
libazbox/dmx.cpp
519
libazbox/dmx.cpp
@@ -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;
|
||||
}
|
@@ -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;
|
@@ -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;
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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__
|
@@ -1 +0,0 @@
|
||||
../libspark/record.cpp
|
@@ -1 +0,0 @@
|
||||
../libspark/record_lib.h
|
@@ -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__);
|
||||
}
|
@@ -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__
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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)
|
||||
|
@@ -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())
|
||||
|
@@ -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));
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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();
|
||||
};
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
|
@@ -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");
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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 */
|
||||
|
||||
|
@@ -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
|
@@ -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;
|
@@ -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);
|
@@ -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;
|
||||
|
@@ -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)
|
||||
{
|
@@ -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)
|
||||
{
|
@@ -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);
|
@@ -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
Reference in New Issue
Block a user