mirror of
https://github.com/tuxbox-fork-migrations/recycled-ni-libstb-hal.git
synced 2025-08-26 15:02:43 +02:00
Merge remote-tracking branch 'seife/master'
Origin commit data
------------------
Branch: master
Commit: 6f4449e1c5
Author: martii <m4rtii@gmx.de>
Date: 2013-10-06 (Sun, 06 Oct 2013)
------------------
No further description and justification available within origin commit message!
------------------
This commit was generated by Migit
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -14,6 +14,7 @@
|
|||||||
/libtriple/Makefile.in
|
/libtriple/Makefile.in
|
||||||
/azbox/Makefile.in
|
/azbox/Makefile.in
|
||||||
/generic-pc/Makefile.in
|
/generic-pc/Makefile.in
|
||||||
|
/raspi/Makefile.in
|
||||||
/ltmain.sh
|
/ltmain.sh
|
||||||
/missing
|
/missing
|
||||||
/Makefile.in
|
/Makefile.in
|
||||||
|
@@ -23,10 +23,16 @@ libstb_hal_la_LIBADD += \
|
|||||||
azbox/libazbox.la
|
azbox/libazbox.la
|
||||||
endif
|
endif
|
||||||
if BOXTYPE_GENERIC
|
if BOXTYPE_GENERIC
|
||||||
|
if BOXMODEL_RASPI
|
||||||
|
SUBDIRS += raspi
|
||||||
|
libstb_hal_la_LIBADD += \
|
||||||
|
raspi/libraspi.la
|
||||||
|
else
|
||||||
SUBDIRS += generic-pc
|
SUBDIRS += generic-pc
|
||||||
libstb_hal_la_LIBADD += \
|
libstb_hal_la_LIBADD += \
|
||||||
generic-pc/libgeneric.la
|
generic-pc/libgeneric.la
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
if BOXTYPE_SPARK
|
if BOXTYPE_SPARK
|
||||||
libstb_hal_test_LDADD += -lasound
|
libstb_hal_test_LDADD += -lasound
|
||||||
SUBDIRS += libspark libeplayer3
|
SUBDIRS += libspark libeplayer3
|
||||||
|
11
acinclude.m4
11
acinclude.m4
@@ -309,6 +309,13 @@ AC_ARG_WITH(boxmodel,
|
|||||||
AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE])
|
AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE])
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
raspi)
|
||||||
|
if test "$BOXTYPE" = "generic"; then
|
||||||
|
BOXMODEL="$withval"
|
||||||
|
else
|
||||||
|
AC_MSG_ERROR([unknown model $withval for boxtype $BOXTYPE])
|
||||||
|
fi
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
AC_MSG_ERROR([unsupported value $withval for --with-boxmodel])
|
AC_MSG_ERROR([unsupported value $withval for --with-boxmodel])
|
||||||
;;
|
;;
|
||||||
@@ -340,6 +347,8 @@ AM_CONDITIONAL(BOXMODEL_IP250,test "$BOXMODEL" = "ip250")
|
|||||||
AM_CONDITIONAL(BOXMODEL_IP350,test "$BOXMODEL" = "ip350")
|
AM_CONDITIONAL(BOXMODEL_IP350,test "$BOXMODEL" = "ip350")
|
||||||
AM_CONDITIONAL(BOXMODEL_IP400,test "$BOXMODEL" = "ip400")
|
AM_CONDITIONAL(BOXMODEL_IP400,test "$BOXMODEL" = "ip400")
|
||||||
|
|
||||||
|
AM_CONDITIONAL(BOXMODEL_RASPI,test "$BOXMODEL" = "raspi")
|
||||||
|
|
||||||
if test "$BOXTYPE" = "dbox2"; then
|
if test "$BOXTYPE" = "dbox2"; then
|
||||||
AC_DEFINE(HAVE_DBOX_HARDWARE, 1, [building for a dbox2])
|
AC_DEFINE(HAVE_DBOX_HARDWARE, 1, [building for a dbox2])
|
||||||
elif test "$BOXTYPE" = "azbox"; then
|
elif test "$BOXTYPE" = "azbox"; then
|
||||||
@@ -369,6 +378,8 @@ elif test "$BOXMODEL" = "ip350"; then
|
|||||||
AC_DEFINE(BOXMODEL_IP350, 1, [ipbox 350])
|
AC_DEFINE(BOXMODEL_IP350, 1, [ipbox 350])
|
||||||
elif test "$BOXMODEL" = "ip400"; then
|
elif test "$BOXMODEL" = "ip400"; then
|
||||||
AC_DEFINE(BOXMODEL_IP400, 1, [ipbox 400])
|
AC_DEFINE(BOXMODEL_IP400, 1, [ipbox 400])
|
||||||
|
elif test "$BOXMODEL" = "raspi"; then
|
||||||
|
AC_DEFINE(BOXMODEL_RASPI, 1, [Raspberry pi])
|
||||||
fi
|
fi
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@@ -3,6 +3,10 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
int cnxt_debug = 0; /* compat, unused */
|
int cnxt_debug = 0; /* compat, unused */
|
||||||
|
|
||||||
@@ -76,3 +80,11 @@ void lt_debug_init(void)
|
|||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hal_set_threadname(const char *name)
|
||||||
|
{
|
||||||
|
char threadname[17];
|
||||||
|
strncpy(threadname, name, sizeof(threadname));
|
||||||
|
threadname[16] = 0;
|
||||||
|
prctl (PR_SET_NAME, (unsigned long)&threadname);
|
||||||
|
}
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
extern int debuglevel;
|
extern int debuglevel;
|
||||||
|
|
||||||
|
void hal_set_threadname(const char *name);
|
||||||
void _lt_debug(int facility, const void *, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
|
void _lt_debug(int facility, const void *, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
|
||||||
void _lt_info(int facility, const void *, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
|
void _lt_info(int facility, const void *, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
|
||||||
void lt_debug_init(void);
|
void lt_debug_init(void);
|
||||||
|
@@ -23,7 +23,7 @@ if test x"$BOXTYPE" = x"tripledragon"; then
|
|||||||
TUXBOX_APPS_LIB_PKGCONFIG(DIRECTFB, directfb)
|
TUXBOX_APPS_LIB_PKGCONFIG(DIRECTFB, directfb)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test x$BOXTYPE = xgeneric; then
|
if test x$BOXTYPE = xgeneric -a x$BOXMODEL != xraspi; then
|
||||||
PKG_CHECK_MODULES([AVFORMAT], [libavformat >= 53.21.1])
|
PKG_CHECK_MODULES([AVFORMAT], [libavformat >= 53.21.1])
|
||||||
PKG_CHECK_MODULES([AVCODEC], [libavcodec >= 54.28.0])
|
PKG_CHECK_MODULES([AVCODEC], [libavcodec >= 54.28.0])
|
||||||
# don't know which version is exactly needed here...
|
# don't know which version is exactly needed here...
|
||||||
@@ -39,6 +39,7 @@ azbox/Makefile
|
|||||||
generic-pc/Makefile
|
generic-pc/Makefile
|
||||||
libtriple/Makefile
|
libtriple/Makefile
|
||||||
libspark/Makefile
|
libspark/Makefile
|
||||||
|
raspi/Makefile
|
||||||
tools/Makefile
|
tools/Makefile
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@@ -7,7 +7,11 @@
|
|||||||
#elif HAVE_AZBOX_HARDWARE
|
#elif HAVE_AZBOX_HARDWARE
|
||||||
#include "../azbox/audio_lib.h"
|
#include "../azbox/audio_lib.h"
|
||||||
#elif HAVE_GENERIC_HARDWARE
|
#elif HAVE_GENERIC_HARDWARE
|
||||||
|
#if BOXMODEL_RASPI
|
||||||
|
#include "../raspi/audio_lib.h"
|
||||||
|
#else
|
||||||
#include "../generic-pc/audio_lib.h"
|
#include "../generic-pc/audio_lib.h"
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
||||||
#endif
|
#endif
|
||||||
|
@@ -6,7 +6,11 @@
|
|||||||
#elif HAVE_AZBOX_HARDWARE
|
#elif HAVE_AZBOX_HARDWARE
|
||||||
#include "../azbox/cs_api.h"
|
#include "../azbox/cs_api.h"
|
||||||
#elif HAVE_GENERIC_HARDWARE
|
#elif HAVE_GENERIC_HARDWARE
|
||||||
|
#if BOXMODEL_RASPI
|
||||||
|
#include "../raspi/cs_api.h"
|
||||||
|
#else
|
||||||
#include "../generic-pc/cs_api.h"
|
#include "../generic-pc/cs_api.h"
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
||||||
#endif
|
#endif
|
||||||
|
@@ -6,7 +6,11 @@
|
|||||||
#elif HAVE_AZBOX_HARDWARE
|
#elif HAVE_AZBOX_HARDWARE
|
||||||
#include "../azbox/dmx_lib.h"
|
#include "../azbox/dmx_lib.h"
|
||||||
#elif HAVE_GENERIC_HARDWARE
|
#elif HAVE_GENERIC_HARDWARE
|
||||||
|
#if BOXMODEL_RASPI
|
||||||
|
#include "../raspi/dmx_lib.h"
|
||||||
|
#else
|
||||||
#include "../generic-pc/dmx_lib.h"
|
#include "../generic-pc/dmx_lib.h"
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1,6 +1,10 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
#if HAVE_GENERIC_HARDWARE
|
#if HAVE_GENERIC_HARDWARE
|
||||||
|
#if BOXMODEL_RASPI
|
||||||
|
#include "../raspi/glfb.h"
|
||||||
|
#else
|
||||||
#include "../generic-pc/glfb.h"
|
#include "../generic-pc/glfb.h"
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#error glfb.h only works with HAVE_GENERIC_HARDWARE defined
|
#error glfb.h only works with HAVE_GENERIC_HARDWARE defined
|
||||||
#endif
|
#endif
|
||||||
|
@@ -6,7 +6,11 @@
|
|||||||
#elif HAVE_AZBOX_HARDWARE
|
#elif HAVE_AZBOX_HARDWARE
|
||||||
#include "../azbox/playback.h"
|
#include "../azbox/playback.h"
|
||||||
#elif HAVE_GENERIC_HARDWARE
|
#elif HAVE_GENERIC_HARDWARE
|
||||||
|
#if BOXMODEL_RASPI
|
||||||
|
#include "../raspi/playback.h"
|
||||||
|
#else
|
||||||
#include "../generic-pc/playback.h"
|
#include "../generic-pc/playback.h"
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
||||||
#endif
|
#endif
|
||||||
|
@@ -6,7 +6,11 @@
|
|||||||
#elif HAVE_AZBOX_HARDWARE
|
#elif HAVE_AZBOX_HARDWARE
|
||||||
#include "../azbox/pwrmngr.h"
|
#include "../azbox/pwrmngr.h"
|
||||||
#elif HAVE_GENERIC_HARDWARE
|
#elif HAVE_GENERIC_HARDWARE
|
||||||
|
#if BOXMODEL_RASPI
|
||||||
|
#include "../raspi/pwrmngr.h"
|
||||||
|
#else
|
||||||
#include "../generic-pc/pwrmngr.h"
|
#include "../generic-pc/pwrmngr.h"
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
||||||
#endif
|
#endif
|
||||||
|
@@ -6,7 +6,11 @@
|
|||||||
#elif HAVE_AZBOX_HARDWARE
|
#elif HAVE_AZBOX_HARDWARE
|
||||||
#include "../azbox/record_lib.h"
|
#include "../azbox/record_lib.h"
|
||||||
#elif HAVE_GENERIC_HARDWARE
|
#elif HAVE_GENERIC_HARDWARE
|
||||||
|
#if BOXMODEL_RASPI
|
||||||
|
#include "../raspi/record_lib.h"
|
||||||
|
#else
|
||||||
#include "../generic-pc/record_lib.h"
|
#include "../generic-pc/record_lib.h"
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
||||||
#endif
|
#endif
|
||||||
|
@@ -6,7 +6,11 @@
|
|||||||
#elif HAVE_AZBOX_HARDWARE
|
#elif HAVE_AZBOX_HARDWARE
|
||||||
#include "../azbox/video_lib.h"
|
#include "../azbox/video_lib.h"
|
||||||
#elif HAVE_GENERIC_HARDWARE
|
#elif HAVE_GENERIC_HARDWARE
|
||||||
|
#if BOXMODEL_RASPI
|
||||||
|
#include "../raspi/video_lib.h"
|
||||||
|
#else
|
||||||
#include "../generic-pc/video_lib.h"
|
#include "../generic-pc/video_lib.h"
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
#error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined
|
||||||
#endif
|
#endif
|
||||||
|
23
libtest.cpp
23
libtest.cpp
@@ -1,18 +1,39 @@
|
|||||||
/* minimal test program for libstb-hal
|
/* minimal test program for libstb-hal
|
||||||
* (C) 2012 Stefan Seyfried
|
* (C) 2012-2013 Stefan Seyfried
|
||||||
* License: GPL v2 or later
|
* License: GPL v2 or later
|
||||||
*
|
*
|
||||||
* this does just test the input converter thread for now...
|
* this does just test the input converter thread for now...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <include/init_td.h>
|
#include <include/init_td.h>
|
||||||
|
#if HAVE_GENERIC_HARDWARE
|
||||||
|
#include <include/glfb.h>
|
||||||
|
|
||||||
|
extern GLFramebuffer *glfb;
|
||||||
|
#define fb_pixel_t uint32_t
|
||||||
|
#endif
|
||||||
|
|
||||||
int main(int argc __attribute__((unused)), char ** argv __attribute__((unused)))
|
int main(int argc __attribute__((unused)), char ** argv __attribute__((unused)))
|
||||||
{
|
{
|
||||||
init_td_api();
|
init_td_api();
|
||||||
|
#if HAVE_GENERIC_HARDWARE
|
||||||
|
int available = glfb->getOSDBuffer()->size(); /* allocated in glfb constructor */
|
||||||
|
fb_pixel_t *lfb = reinterpret_cast<fb_pixel_t*>(glfb->getOSDBuffer()->data());
|
||||||
|
|
||||||
|
int x = 0;
|
||||||
|
#endif
|
||||||
while (1) {
|
while (1) {
|
||||||
|
#if HAVE_GENERIC_HARDWARE
|
||||||
|
fb_pixel_t c = (0xff << (8 * x))|0xff000000;
|
||||||
|
x++;
|
||||||
|
if (x > 3) x = 0;
|
||||||
|
for (int i = 0; i < available / 4; i++)
|
||||||
|
*(lfb + i) = c;
|
||||||
|
glfb->blit();
|
||||||
|
#endif
|
||||||
sleep(1);
|
sleep(1);
|
||||||
if (! access("/tmp/endtest", R_OK))
|
if (! access("/tmp/endtest", R_OK))
|
||||||
{
|
{
|
||||||
|
26
raspi/Makefile.am
Normal file
26
raspi/Makefile.am
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
noinst_LTLIBRARIES = libraspi.la
|
||||||
|
|
||||||
|
AM_CPPFLAGS = -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
|
||||||
|
AM_CPPFLAGS += \
|
||||||
|
-I/opt/vc/include \
|
||||||
|
-I/opt/vc/include/interface/vcos/pthreads/ \
|
||||||
|
-I/opt/vc/include/interface/vmcs_host/linux \
|
||||||
|
-I$(top_srcdir)/common
|
||||||
|
|
||||||
|
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
|
||||||
|
|
||||||
|
AM_LDFLAGS = \
|
||||||
|
-L/opt/vc/lib/ -lopenmaxil -lbcm_host -lvcos -lvchiq_arm -lpthread -lrt \
|
||||||
|
-lOpenThreads
|
||||||
|
|
||||||
|
libraspi_la_SOURCES = \
|
||||||
|
hardware_caps.c \
|
||||||
|
dmx.cpp \
|
||||||
|
video.cpp \
|
||||||
|
audio.cpp \
|
||||||
|
glfb.cpp \
|
||||||
|
init.cpp \
|
||||||
|
playback.cpp \
|
||||||
|
pwrmngr.cpp \
|
||||||
|
record.cpp
|
||||||
|
|
154
raspi/audio.cpp
Normal file
154
raspi/audio.cpp
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* (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/>.
|
||||||
|
*
|
||||||
|
* cAudio dummy implementation
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include "audio_lib.h"
|
||||||
|
#include "dmx_lib.h"
|
||||||
|
#include "lt_debug.h"
|
||||||
|
|
||||||
|
#define lt_debug(args...) _lt_debug(HAL_DEBUG_AUDIO, this, args)
|
||||||
|
#define lt_info(args...) _lt_info(HAL_DEBUG_AUDIO, this, args)
|
||||||
|
|
||||||
|
cAudio * audioDecoder = NULL;
|
||||||
|
|
||||||
|
cAudio::cAudio(void *, void *, void *)
|
||||||
|
{
|
||||||
|
lt_debug("%s\n", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
cAudio::~cAudio(void)
|
||||||
|
{
|
||||||
|
lt_debug("%s\n", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cAudio::openDevice(void)
|
||||||
|
{
|
||||||
|
lt_debug("%s\n", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cAudio::closeDevice(void)
|
||||||
|
{
|
||||||
|
lt_debug("%s\n", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cAudio::do_mute(bool enable, bool remember)
|
||||||
|
{
|
||||||
|
lt_debug("%s(%d, %d)\n", __func__, enable, remember);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cAudio::setVolume(unsigned int left, unsigned int right)
|
||||||
|
{
|
||||||
|
lt_debug("%s(%d, %d)\n", __func__, left, right);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cAudio::Start(void)
|
||||||
|
{
|
||||||
|
lt_debug("%s >\n", __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cAudio::Stop(void)
|
||||||
|
{
|
||||||
|
lt_debug("%s >\n", __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cAudio::Pause(bool /*Pcm*/)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
void cAudio::SetSyncMode(AVSYNC_TYPE Mode)
|
||||||
|
{
|
||||||
|
lt_debug("%s %d\n", __func__, Mode);
|
||||||
|
};
|
||||||
|
|
||||||
|
void cAudio::SetStreamType(AUDIO_FORMAT type)
|
||||||
|
{
|
||||||
|
lt_debug("%s %d\n", __func__, type);
|
||||||
|
};
|
||||||
|
|
||||||
|
int cAudio::setChannel(int /*channel*/)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cAudio::PrepareClipPlay(int ch, int srate, int bits, int le)
|
||||||
|
{
|
||||||
|
lt_debug("%s ch %d srate %d bits %d le %d\n", __func__, ch, srate, bits, le);;
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cAudio::WriteClip(unsigned char *buffer, int size)
|
||||||
|
{
|
||||||
|
lt_debug("cAudio::%s buf 0x%p size %d\n", __func__, buffer, size);
|
||||||
|
return size;
|
||||||
|
};
|
||||||
|
|
||||||
|
int cAudio::StopClip()
|
||||||
|
{
|
||||||
|
lt_debug("%s\n", __func__);
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void cAudio::getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &mode)
|
||||||
|
{
|
||||||
|
type = 0;
|
||||||
|
layer = 0; /* not used */
|
||||||
|
freq = 0;
|
||||||
|
bitrate = 0; /* not used, but easy to get :-) */
|
||||||
|
mode = 0; /* default: stereo */
|
||||||
|
lt_debug("%s t: %d l: %d f: %d b: %d m: %d\n",
|
||||||
|
__func__, type, layer, freq, bitrate, mode);
|
||||||
|
};
|
||||||
|
|
||||||
|
void cAudio::SetSRS(int /*iq_enable*/, int /*nmgr_enable*/, int /*iq_mode*/, int /*iq_level*/)
|
||||||
|
{
|
||||||
|
lt_debug("%s\n", __func__);
|
||||||
|
};
|
||||||
|
|
||||||
|
void cAudio::SetHdmiDD(bool enable)
|
||||||
|
{
|
||||||
|
lt_debug("%s %d\n", __func__, enable);
|
||||||
|
};
|
||||||
|
|
||||||
|
void cAudio::SetSpdifDD(bool enable)
|
||||||
|
{
|
||||||
|
lt_debug("%s %d\n", __func__, enable);
|
||||||
|
};
|
||||||
|
|
||||||
|
void cAudio::ScheduleMute(bool On)
|
||||||
|
{
|
||||||
|
lt_debug("%s %d\n", __func__, On);
|
||||||
|
};
|
||||||
|
|
||||||
|
void cAudio::EnableAnalogOut(bool enable)
|
||||||
|
{
|
||||||
|
lt_debug("%s %d\n", __func__, enable);
|
||||||
|
};
|
||||||
|
|
||||||
|
void cAudio::setBypassMode(bool disable)
|
||||||
|
{
|
||||||
|
lt_debug("%s %d\n", __func__, disable);
|
||||||
|
}
|
||||||
|
|
103
raspi/audio_lib.h
Normal file
103
raspi/audio_lib.h
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/* public header file */
|
||||||
|
|
||||||
|
#ifndef _AUDIO_LIB_H_
|
||||||
|
#define _AUDIO_LIB_H_
|
||||||
|
|
||||||
|
#include <stdint.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;
|
||||||
|
bool thread_started;
|
||||||
|
|
||||||
|
int volume;
|
||||||
|
int64_t curr_pts;
|
||||||
|
|
||||||
|
void openDevice(void);
|
||||||
|
void closeDevice(void);
|
||||||
|
|
||||||
|
int do_mute(bool enable, bool remember);
|
||||||
|
void setBypassMode(bool disable);
|
||||||
|
public:
|
||||||
|
/* construct & destruct */
|
||||||
|
cAudio(void *, void *, void *);
|
||||||
|
~cAudio(void);
|
||||||
|
int64_t getPts() { return curr_pts; }
|
||||||
|
|
||||||
|
void *GetHandle() { return NULL; };
|
||||||
|
/* shut up */
|
||||||
|
int mute(bool remember = true) { return do_mute(true, remember); };
|
||||||
|
int unmute(bool remember = true) { return do_mute(false, remember); };
|
||||||
|
|
||||||
|
/* volume, min = 0, max = 255 */
|
||||||
|
int setVolume(unsigned int left, unsigned int right);
|
||||||
|
int getVolume(void) { return volume;}
|
||||||
|
bool getMuteStatus(void) { return Muted; };
|
||||||
|
|
||||||
|
/* start and stop audio */
|
||||||
|
int Start(void);
|
||||||
|
int Stop(void);
|
||||||
|
bool Pause(bool Pcm = true);
|
||||||
|
void SetStreamType(AUDIO_FORMAT type);
|
||||||
|
void SetSyncMode(AVSYNC_TYPE Mode);
|
||||||
|
|
||||||
|
/* select channels */
|
||||||
|
int setChannel(int channel);
|
||||||
|
int PrepareClipPlay(int uNoOfChannels, int uSampleRate, int uBitsPerSample, int bLittleEndian);
|
||||||
|
int WriteClip(unsigned char * buffer, int size);
|
||||||
|
int StopClip();
|
||||||
|
void getAudioInfo(int &type, int &layer, int& freq, int &bitrate, int &mode);
|
||||||
|
void SetSRS(int iq_enable, int nmgr_enable, int iq_mode, int iq_level);
|
||||||
|
bool IsHdmiDDSupported();
|
||||||
|
void SetHdmiDD(bool enable);
|
||||||
|
void SetSpdifDD(bool enable);
|
||||||
|
void ScheduleMute(bool On);
|
||||||
|
void EnableAnalogOut(bool enable);
|
||||||
|
int my_read(uint8_t *buf, int buf_size);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
1
raspi/cs_api.h
Symbolic link
1
raspi/cs_api.h
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../libspark/cs_api.h
|
500
raspi/dmx.cpp
Normal file
500
raspi/dmx.cpp
Normal file
@@ -0,0 +1,500 @@
|
|||||||
|
/*
|
||||||
|
* cDemux implementation for generic dvbapi
|
||||||
|
*
|
||||||
|
* 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 <unistd.h>
|
||||||
|
#include "dmx_lib.h"
|
||||||
|
#include "lt_debug.h"
|
||||||
|
|
||||||
|
/* needed for getSTC :-( */
|
||||||
|
#include "video_lib.h"
|
||||||
|
extern cVideo *videoDecoder;
|
||||||
|
|
||||||
|
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_DEMUX, this, args)
|
||||||
|
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_DEMUX, this, args)
|
||||||
|
#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_DEMUX, NULL, args)
|
||||||
|
|
||||||
|
#define dmx_err(_errfmt, _errstr, _revents) do { \
|
||||||
|
uint16_t _pid = (uint16_t)-1; uint16_t _f = 0;\
|
||||||
|
if (dmx_type == DMX_PSI_CHANNEL) { \
|
||||||
|
_pid = s_flt.pid; _f = s_flt.filter.filter[0]; \
|
||||||
|
} else { \
|
||||||
|
_pid = p_flt.pid; \
|
||||||
|
}; \
|
||||||
|
lt_info("%s " _errfmt " fd:%d, ev:0x%x %s pid:0x%04hx flt:0x%02hx\n", \
|
||||||
|
__func__, _errstr, fd, _revents, DMX_T[dmx_type], _pid, _f); \
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
cDemux *videoDemux = NULL;
|
||||||
|
cDemux *audioDemux = NULL;
|
||||||
|
//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)
|
||||||
|
{
|
||||||
|
lt_info("%s ERROR: n invalid (%d)\n", __FUNCTION__, n);
|
||||||
|
num = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
num = n;
|
||||||
|
fd = -1;
|
||||||
|
measure = false;
|
||||||
|
last_measure = 0;
|
||||||
|
last_data = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cDemux::~cDemux()
|
||||||
|
{
|
||||||
|
lt_debug("%s #%d fd: %d\n", __FUNCTION__, num, fd);
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBufferSize)
|
||||||
|
{
|
||||||
|
int devnum = num;
|
||||||
|
int flags = O_RDWR|O_CLOEXEC;
|
||||||
|
if (fd > -1)
|
||||||
|
lt_info("%s FD ALREADY OPENED? fd = %d\n", __FUNCTION__, fd);
|
||||||
|
|
||||||
|
dmx_type = pes_type;
|
||||||
|
if (pes_type != DMX_PSI_CHANNEL)
|
||||||
|
flags |= O_NONBLOCK;
|
||||||
|
|
||||||
|
fd = open(devname[devnum], flags);
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
lt_info("%s %s: %m\n", __FUNCTION__, devname[devnum]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
lt_debug("%s #%d pes_type: %s(%d), uBufferSize: %d fd: %d\n", __func__,
|
||||||
|
num, DMX_T[pes_type], pes_type, uBufferSize, fd);
|
||||||
|
|
||||||
|
if (dmx_type == DMX_VIDEO_CHANNEL)
|
||||||
|
uBufferSize = 0x100000; /* 1MB */
|
||||||
|
if (dmx_type == DMX_AUDIO_CHANNEL)
|
||||||
|
uBufferSize = 0x10000; /* 64k */
|
||||||
|
#if 0
|
||||||
|
if (!pesfds.empty())
|
||||||
|
{
|
||||||
|
lt_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)
|
||||||
|
lt_info("%s DMX_SET_SOURCE %d failed! (%m)\n", __func__, n);
|
||||||
|
#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)
|
||||||
|
lt_info("%s DMX_SET_BUFFER_SIZE failed (%m)\n", __func__);
|
||||||
|
}
|
||||||
|
buffersize = uBufferSize;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cDemux::Close(void)
|
||||||
|
{
|
||||||
|
lt_debug("%s #%d, fd = %d\n", __FUNCTION__, num, fd);
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
lt_info("%s #%d: not open!\n", __FUNCTION__, num);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pesfds.clear();
|
||||||
|
ioctl(fd, DMX_STOP);
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
if (measure)
|
||||||
|
return;
|
||||||
|
if (dmx_type == DMX_TP_CHANNEL)
|
||||||
|
{
|
||||||
|
dmx_tp_count--;
|
||||||
|
if (dmx_tp_count < 0)
|
||||||
|
{
|
||||||
|
lt_info("%s dmx_tp_count < 0!!\n", __func__);
|
||||||
|
dmx_tp_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cDemux::Start(bool)
|
||||||
|
{
|
||||||
|
lt_debug("%s #%d fd: %d type: %s\n", __func__, num, fd, DMX_T[dmx_type]);
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
lt_info("%s #%d: not open!\n", __FUNCTION__, num);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ioctl(fd, DMX_START);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cDemux::Stop(void)
|
||||||
|
{
|
||||||
|
lt_debug("%s #%d fd: %d type: %s\n", __func__, num, fd, DMX_T[dmx_type]);
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
lt_info("%s #%d: not open!\n", __FUNCTION__, num);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ioctl(fd, DMX_STOP);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cDemux::Read(unsigned char *buff, int len, int timeout)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
if (len != 4095 && timeout != 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;
|
||||||
|
struct pollfd ufds;
|
||||||
|
ufds.fd = fd;
|
||||||
|
ufds.events = POLLIN|POLLPRI|POLLERR;
|
||||||
|
ufds.revents = 0;
|
||||||
|
|
||||||
|
if (timeout > 0)
|
||||||
|
{
|
||||||
|
retry:
|
||||||
|
rc = ::poll(&ufds, 1, timeout);
|
||||||
|
if (!rc)
|
||||||
|
return 0; // timeout
|
||||||
|
else if (rc < 0)
|
||||||
|
{
|
||||||
|
dmx_err("poll: %s,", strerror(errno), 0)
|
||||||
|
//lt_info("%s poll: %m\n", __FUNCTION__);
|
||||||
|
/* happens, when running under gdb... */
|
||||||
|
if (errno == EINTR)
|
||||||
|
goto retry;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
if (ufds.revents & POLLERR) /* POLLERR means buffer error, i.e. buffer overflow */
|
||||||
|
{
|
||||||
|
dmx_err("received %s,", "POLLERR", ufds.revents);
|
||||||
|
/* this seems to happen sometimes at recording start, without bad effects */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (ufds.revents & POLLHUP) /* we get POLLHUP if e.g. a too big DMX_BUFFER_SIZE was set */
|
||||||
|
{
|
||||||
|
dmx_err("received %s,", "POLLHUP", ufds.revents);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!(ufds.revents & POLLIN)) /* we requested POLLIN but did not get it? */
|
||||||
|
{
|
||||||
|
dmx_err("received %s, please report!", "POLLIN", ufds.revents);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ::read(fd, buff, len);
|
||||||
|
//fprintf(stderr, "fd %d ret: %d\n", fd, rc);
|
||||||
|
if (rc < 0)
|
||||||
|
dmx_err("read: %s", strerror(errno), 0);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cDemux::sectionFilter(unsigned short pid, const unsigned char * const filter,
|
||||||
|
const unsigned char * const mask, int len, int timeout,
|
||||||
|
const unsigned char * const negmask)
|
||||||
|
{
|
||||||
|
memset(&s_flt, 0, sizeof(s_flt));
|
||||||
|
|
||||||
|
if (len > DMX_FILTER_SIZE)
|
||||||
|
{
|
||||||
|
lt_info("%s #%d: len too long: %d, DMX_FILTER_SIZE %d\n", __func__, num, len, DMX_FILTER_SIZE);
|
||||||
|
len = DMX_FILTER_SIZE;
|
||||||
|
}
|
||||||
|
s_flt.pid = pid;
|
||||||
|
s_flt.timeout = timeout;
|
||||||
|
memcpy(s_flt.filter.filter, filter, len);
|
||||||
|
memcpy(s_flt.filter.mask, mask, len);
|
||||||
|
if (negmask != NULL)
|
||||||
|
memcpy(s_flt.filter.mode, negmask, len);
|
||||||
|
|
||||||
|
s_flt.flags = DMX_IMMEDIATE_START|DMX_CHECK_CRC;
|
||||||
|
|
||||||
|
int to = 0;
|
||||||
|
switch (filter[0]) {
|
||||||
|
case 0x00: /* program_association_section */
|
||||||
|
to = 2000;
|
||||||
|
break;
|
||||||
|
case 0x01: /* conditional_access_section */
|
||||||
|
to = 6000;
|
||||||
|
break;
|
||||||
|
case 0x02: /* program_map_section */
|
||||||
|
to = 1500;
|
||||||
|
break;
|
||||||
|
case 0x03: /* transport_stream_description_section */
|
||||||
|
to = 10000;
|
||||||
|
break;
|
||||||
|
/* 0x04 - 0x3F: reserved */
|
||||||
|
case 0x40: /* network_information_section - actual_network */
|
||||||
|
to = 10000;
|
||||||
|
break;
|
||||||
|
case 0x41: /* network_information_section - other_network */
|
||||||
|
to = 15000;
|
||||||
|
break;
|
||||||
|
case 0x42: /* service_description_section - actual_transport_stream */
|
||||||
|
to = 10000;
|
||||||
|
break;
|
||||||
|
/* 0x43 - 0x45: reserved for future use */
|
||||||
|
case 0x46: /* service_description_section - other_transport_stream */
|
||||||
|
to = 10000;
|
||||||
|
break;
|
||||||
|
/* 0x47 - 0x49: reserved for future use */
|
||||||
|
case 0x4A: /* bouquet_association_section */
|
||||||
|
to = 11000;
|
||||||
|
break;
|
||||||
|
/* 0x4B - 0x4D: reserved for future use */
|
||||||
|
case 0x4E: /* event_information_section - actual_transport_stream, present/following */
|
||||||
|
to = 2000;
|
||||||
|
break;
|
||||||
|
case 0x4F: /* event_information_section - other_transport_stream, present/following */
|
||||||
|
to = 10000;
|
||||||
|
break;
|
||||||
|
/* 0x50 - 0x5F: event_information_section - actual_transport_stream, schedule */
|
||||||
|
/* 0x60 - 0x6F: event_information_section - other_transport_stream, schedule */
|
||||||
|
case 0x70: /* time_date_section */
|
||||||
|
s_flt.flags &= ~DMX_CHECK_CRC; /* section has no CRC */
|
||||||
|
//s_flt.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.pid = 0x0014;
|
||||||
|
to = 30000;
|
||||||
|
break;
|
||||||
|
/* 0x74 - 0x7D: reserved for future use */
|
||||||
|
case 0x7E: /* discontinuity_information_section */
|
||||||
|
s_flt.flags &= ~DMX_CHECK_CRC; /* section has no CRC */
|
||||||
|
to = 0;
|
||||||
|
break;
|
||||||
|
case 0x7F: /* selection_information_section */
|
||||||
|
to = 0;
|
||||||
|
break;
|
||||||
|
/* 0x80 - 0x8F: ca_message_section */
|
||||||
|
/* 0x90 - 0xFE: user defined */
|
||||||
|
/* 0xFF: reserved */
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
// return -1;
|
||||||
|
}
|
||||||
|
/* the negmask == NULL is a hack: the users of negmask are PMT-update
|
||||||
|
* and sectionsd EIT-Version change. And they really want no timeout
|
||||||
|
* if timeout == 0 instead of "default timeout" */
|
||||||
|
if (timeout == 0 && negmask == NULL)
|
||||||
|
s_flt.timeout = to;
|
||||||
|
|
||||||
|
lt_debug("%s #%d pid:0x%04hx fd:%d type:%s len:%d to:%d flags:%x flt[0]:%02x\n", __func__, num,
|
||||||
|
pid, fd, DMX_T[dmx_type], len, s_flt.timeout,s_flt.flags, s_flt.filter.filter[0]);
|
||||||
|
#if 0
|
||||||
|
fprintf(stderr,"filt: ");for(int i=0;i<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;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cDemux::pesFilter(const unsigned short pid)
|
||||||
|
{
|
||||||
|
/* allow PID 0 for web streaming e.g.
|
||||||
|
* this check originally is from tuxbox cvs but I'm not sure
|
||||||
|
* what it is good for...
|
||||||
|
if (pid <= 0x0001 && dmx_type != DMX_PCR_ONLY_CHANNEL)
|
||||||
|
return false;
|
||||||
|
*/
|
||||||
|
if ((pid >= 0x0002 && pid <= 0x000f) || pid >= 0x1fff)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
lt_debug("%s #%d pid: 0x%04hx fd: %d type: %s\n", __FUNCTION__, num, pid, fd, DMX_T[dmx_type]);
|
||||||
|
|
||||||
|
memset(&p_flt, 0, sizeof(p_flt));
|
||||||
|
p_flt.pid = pid;
|
||||||
|
p_flt.output = DMX_OUT_DECODER;
|
||||||
|
p_flt.input = DMX_IN_FRONTEND;
|
||||||
|
|
||||||
|
/* for now, output to TS_TAP for live mode,
|
||||||
|
* test playback with "omxplayer /dev/dvb/adapter0/dvr0" */
|
||||||
|
switch (dmx_type) {
|
||||||
|
case DMX_PCR_ONLY_CHANNEL:
|
||||||
|
p_flt.pes_type = DMX_PES_OTHER;
|
||||||
|
p_flt.output = DMX_OUT_TS_TAP;
|
||||||
|
break;
|
||||||
|
case DMX_AUDIO_CHANNEL:
|
||||||
|
p_flt.pes_type = DMX_PES_OTHER;
|
||||||
|
p_flt.output = DMX_OUT_TS_TAP;
|
||||||
|
break;
|
||||||
|
case DMX_VIDEO_CHANNEL:
|
||||||
|
p_flt.pes_type = DMX_PES_OTHER;
|
||||||
|
p_flt.output = DMX_OUT_TS_TAP;
|
||||||
|
break;
|
||||||
|
case DMX_PES_CHANNEL:
|
||||||
|
p_flt.pes_type = DMX_PES_OTHER;
|
||||||
|
p_flt.output = DMX_OUT_TAP;
|
||||||
|
break;
|
||||||
|
case DMX_TP_CHANNEL:
|
||||||
|
p_flt.pes_type = DMX_PES_OTHER;
|
||||||
|
p_flt.output = DMX_OUT_TSDEMUX_TAP;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
lt_info("%s #%d invalid dmx_type %d!\n", __func__, num, dmx_type);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (ioctl(fd, DMX_SET_PES_FILTER, &p_flt) >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cDemux::SetSyncMode(AVSYNC_TYPE /*mode*/)
|
||||||
|
{
|
||||||
|
lt_debug("%s #%d\n", __FUNCTION__, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cDemux::getBuffer()
|
||||||
|
{
|
||||||
|
lt_debug("%s #%d\n", __FUNCTION__, num);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cDemux::getChannel()
|
||||||
|
{
|
||||||
|
lt_debug("%s #%d\n", __FUNCTION__, num);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cDemux::addPid(unsigned short Pid)
|
||||||
|
{
|
||||||
|
lt_debug("%s: pid 0x%04hx\n", __func__, Pid);
|
||||||
|
pes_pids pfd;
|
||||||
|
int ret;
|
||||||
|
if (dmx_type != DMX_TP_CHANNEL)
|
||||||
|
{
|
||||||
|
lt_info("%s pes_type %s not implemented yet! pid=%hx\n", __FUNCTION__, DMX_T[dmx_type], Pid);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (fd == -1)
|
||||||
|
lt_info("%s bucketfd not yet opened? pid=%hx\n", __FUNCTION__, Pid);
|
||||||
|
pfd.fd = fd; /* dummy */
|
||||||
|
pfd.pid = Pid;
|
||||||
|
pesfds.push_back(pfd);
|
||||||
|
ret = (ioctl(fd, DMX_ADD_PID, &Pid));
|
||||||
|
if (ret < 0)
|
||||||
|
lt_info("%s: DMX_ADD_PID (%m)\n", __func__);
|
||||||
|
return (ret != -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cDemux::removePid(unsigned short Pid)
|
||||||
|
{
|
||||||
|
if (dmx_type != DMX_TP_CHANNEL)
|
||||||
|
{
|
||||||
|
lt_info("%s pes_type %s not implemented yet! pid=%hx\n", __FUNCTION__, DMX_T[dmx_type], Pid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (std::vector<pes_pids>::iterator i = pesfds.begin(); i != pesfds.end(); ++i)
|
||||||
|
{
|
||||||
|
if ((*i).pid == Pid) {
|
||||||
|
lt_debug("removePid: removing demux fd %d pid 0x%04x\n", fd, Pid);
|
||||||
|
if (ioctl(fd, DMX_REMOVE_PID, Pid) < 0)
|
||||||
|
lt_info("%s: (DMX_REMOVE_PID, 0x%04hx): %m\n", __func__, Pid);
|
||||||
|
pesfds.erase(i);
|
||||||
|
return; /* TODO: what if the same PID is there multiple times */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lt_info("%s pid 0x%04x not found\n", __FUNCTION__, Pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cDemux::getSTC(int64_t * STC)
|
||||||
|
{
|
||||||
|
int64_t pts = 0;
|
||||||
|
if (videoDecoder)
|
||||||
|
pts = videoDecoder->GetPTS();
|
||||||
|
*STC = pts;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cDemux::getUnit(void)
|
||||||
|
{
|
||||||
|
lt_debug("%s #%d\n", __FUNCTION__, num);
|
||||||
|
/* just guessed that this is the right thing to do.
|
||||||
|
right now this is only used by the CA code which is stubbed out
|
||||||
|
anyway */
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cDemux::SetSource(int unit, int source)
|
||||||
|
{
|
||||||
|
lt_info_c("%s(%d, %d): not implemented yet\n", __func__, unit, source);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cDemux::GetSource(int unit)
|
||||||
|
{
|
||||||
|
lt_info_c("%s(%d): not implemented yet\n", __func__, unit);
|
||||||
|
return 0;
|
||||||
|
}
|
1
raspi/dmx_cs.h
Normal file
1
raspi/dmx_cs.h
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#include "dmx_lib.h"
|
70
raspi/dmx_lib.h
Normal file
70
raspi/dmx_lib.h
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#ifndef __DEMUX_TD_H
|
||||||
|
#define __DEMUX_TD_H
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <vector>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <linux/dvb/dmx.h>
|
||||||
|
#include "../common/cs_types.h"
|
||||||
|
|
||||||
|
#define MAX_DMX_UNITS 4
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DMX_INVALID = 0,
|
||||||
|
DMX_VIDEO_CHANNEL = 1,
|
||||||
|
DMX_AUDIO_CHANNEL,
|
||||||
|
DMX_PES_CHANNEL,
|
||||||
|
DMX_PSI_CHANNEL,
|
||||||
|
DMX_PIP_CHANNEL,
|
||||||
|
DMX_TP_CHANNEL,
|
||||||
|
DMX_PCR_ONLY_CHANNEL
|
||||||
|
} DMX_CHANNEL_TYPE;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
unsigned short pid;
|
||||||
|
} pes_pids;
|
||||||
|
|
||||||
|
class cDemux
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int num;
|
||||||
|
int fd;
|
||||||
|
int buffersize;
|
||||||
|
bool measure;
|
||||||
|
uint64_t last_measure, last_data;
|
||||||
|
DMX_CHANNEL_TYPE dmx_type;
|
||||||
|
std::vector<pes_pids> pesfds;
|
||||||
|
struct dmx_sct_filter_params s_flt;
|
||||||
|
struct dmx_pes_filter_params p_flt;
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool Open(DMX_CHANNEL_TYPE pes_type, void * x = NULL, int y = 0);
|
||||||
|
void Close(void);
|
||||||
|
bool Start(bool record = false);
|
||||||
|
bool Stop(void);
|
||||||
|
int Read(unsigned char *buff, int len, int Timeout = 0);
|
||||||
|
bool sectionFilter(unsigned short pid, const unsigned char * const filter, const unsigned char * const mask, int len, int Timeout = 0, const unsigned char * const negmask = NULL);
|
||||||
|
bool pesFilter(const unsigned short pid);
|
||||||
|
void SetSyncMode(AVSYNC_TYPE mode);
|
||||||
|
void * getBuffer();
|
||||||
|
void * getChannel();
|
||||||
|
DMX_CHANNEL_TYPE getChannelType(void) { return dmx_type; };
|
||||||
|
bool addPid(unsigned short pid);
|
||||||
|
void getSTC(int64_t * STC);
|
||||||
|
int getUnit(void);
|
||||||
|
static bool SetSource(int unit, int source);
|
||||||
|
static int GetSource(int unit);
|
||||||
|
// TD only functions
|
||||||
|
int getFD(void) { return fd; }; /* needed by cPlayback class */
|
||||||
|
void removePid(unsigned short Pid); /* needed by cRecord class */
|
||||||
|
std::vector<pes_pids> getPesPids(void) { return pesfds; };
|
||||||
|
//
|
||||||
|
cDemux(int num = 0);
|
||||||
|
~cDemux();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //__DEMUX_H
|
171
raspi/glfb.cpp
Normal file
171
raspi/glfb.cpp
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2013 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GLFB namespace is just because it's already established by the
|
||||||
|
generic-pc implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <OpenThreads/Condition>
|
||||||
|
|
||||||
|
#include "glfb.h"
|
||||||
|
#include "bcm_host.h"
|
||||||
|
|
||||||
|
#include "lt_debug.h"
|
||||||
|
|
||||||
|
#define lt_debug_c(args...) _lt_debug(HAL_DEBUG_INIT, NULL, args)
|
||||||
|
#define lt_info_c(args...) _lt_info(HAL_DEBUG_INIT, NULL, args)
|
||||||
|
#define lt_debug(args...) _lt_debug(HAL_DEBUG_INIT, this, args)
|
||||||
|
#define lt_info(args...) _lt_info(HAL_DEBUG_INIT, this, args)
|
||||||
|
|
||||||
|
/* I don't want to assert right now */
|
||||||
|
#define CHECK(x) if (!(x)) { lt_info("GLFB: %s:%d warning: %s\n", __func__, __LINE__, #x); }
|
||||||
|
|
||||||
|
/* TODO: encapsulate this into pdata? */
|
||||||
|
static DISPMANX_RESOURCE_HANDLE_T res[2];
|
||||||
|
static uint32_t vc_img_ptr[2];
|
||||||
|
static DISPMANX_UPDATE_HANDLE_T update;
|
||||||
|
static DISPMANX_ELEMENT_HANDLE_T element;
|
||||||
|
static DISPMANX_DISPLAY_HANDLE_T display;
|
||||||
|
static DISPMANX_MODEINFO_T info;
|
||||||
|
static VC_RECT_T dst_rect;
|
||||||
|
static void *image;
|
||||||
|
static int curr_res;
|
||||||
|
static int pitch;
|
||||||
|
static VC_IMAGE_TYPE_T type = VC_IMAGE_ARGB8888;
|
||||||
|
|
||||||
|
static OpenThreads::Mutex blit_mutex;
|
||||||
|
static OpenThreads::Condition blit_cond;
|
||||||
|
|
||||||
|
static bool goodbye = false; /* if set main loop is left */
|
||||||
|
static bool ready = false; /* condition predicate */
|
||||||
|
|
||||||
|
static int width; /* width and height, fixed for a framebuffer instance */
|
||||||
|
static int height;
|
||||||
|
|
||||||
|
GLFramebuffer::GLFramebuffer(int x, int y)
|
||||||
|
{
|
||||||
|
width = x;
|
||||||
|
height = y;
|
||||||
|
|
||||||
|
/* linux framebuffer compat mode */
|
||||||
|
si.bits_per_pixel = 32;
|
||||||
|
si.xres = si.xres_virtual = width;
|
||||||
|
si.yres = si.yres_virtual = height;
|
||||||
|
si.blue.length = si.green.length = si.red.length = si.transp.length = 8;
|
||||||
|
si.blue.offset = 0;
|
||||||
|
si.green.offset = 8;
|
||||||
|
si.red.offset = 16;
|
||||||
|
si.transp.offset = 24;
|
||||||
|
|
||||||
|
OpenThreads::Thread::start();
|
||||||
|
while (!ready)
|
||||||
|
usleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFramebuffer::~GLFramebuffer()
|
||||||
|
{
|
||||||
|
goodbye = true;
|
||||||
|
blit(); /* wake up thread */
|
||||||
|
OpenThreads::Thread::join();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLFramebuffer::run()
|
||||||
|
{
|
||||||
|
hal_set_threadname("hal:fbuff");
|
||||||
|
setup();
|
||||||
|
ready = true; /* signal that setup is finished */
|
||||||
|
blit_mutex.lock();
|
||||||
|
while (!goodbye)
|
||||||
|
{
|
||||||
|
blit_cond.wait(&blit_mutex);
|
||||||
|
blit_osd();
|
||||||
|
}
|
||||||
|
blit_mutex.unlock();
|
||||||
|
lt_info("GLFB: GL thread stopping\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLFramebuffer::blit()
|
||||||
|
{
|
||||||
|
blit_mutex.lock();
|
||||||
|
blit_cond.signal();
|
||||||
|
blit_mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLFramebuffer::setup()
|
||||||
|
{
|
||||||
|
lt_info("GLFB: raspi OMX fb setup\n");
|
||||||
|
int ret;
|
||||||
|
VC_RECT_T src_rect, dsp_rect; /* source and display size will not change. period. */
|
||||||
|
pitch = ALIGN_UP(width * 4, 32);
|
||||||
|
/* broadcom example code has this ALIGN_UP in there for a reasin, I suppose */
|
||||||
|
if (pitch != width * 4)
|
||||||
|
lt_info("GLFB: WARNING: width not a multiple of 8? I doubt this will work...\n");
|
||||||
|
|
||||||
|
/* global alpha nontransparent (255) */
|
||||||
|
VC_DISPMANX_ALPHA_T alpha = { DISPMANX_FLAGS_ALPHA_FROM_SOURCE, 255, 0 };
|
||||||
|
|
||||||
|
bcm_host_init();
|
||||||
|
|
||||||
|
display = vc_dispmanx_display_open(0);
|
||||||
|
ret = vc_dispmanx_display_get_info(display, &info);
|
||||||
|
CHECK(ret == 0);
|
||||||
|
/* 32bit FB depth, *2 because tuxtxt uses a shadow buffer */
|
||||||
|
osd_buf.resize(pitch * height * 2);
|
||||||
|
lt_info("GLFB: Display is %d x %d, FB is %d x %d, memory size %d\n",
|
||||||
|
info.width, info.height, width, height, osd_buf.size());
|
||||||
|
image = &osd_buf[0];
|
||||||
|
/* initialize to half-transparent grey */
|
||||||
|
memset(image, 0x7f, osd_buf.size());
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
res[i] = vc_dispmanx_resource_create(type, width, height, &vc_img_ptr[i]);
|
||||||
|
CHECK(res[i]);
|
||||||
|
}
|
||||||
|
vc_dispmanx_rect_set(&dst_rect, 0, 0, width, height);
|
||||||
|
ret = vc_dispmanx_resource_write_data(res[curr_res], type, pitch, image, &dst_rect);
|
||||||
|
CHECK(ret == 0);
|
||||||
|
update = vc_dispmanx_update_start(10);
|
||||||
|
CHECK(update);
|
||||||
|
vc_dispmanx_rect_set(&src_rect, 0, 0, width << 16, height << 16);
|
||||||
|
vc_dispmanx_rect_set(&dsp_rect, 0, 0, info.width, info.height);
|
||||||
|
element = vc_dispmanx_element_add(update,
|
||||||
|
display,
|
||||||
|
2000 /*layer*/,
|
||||||
|
&dsp_rect,
|
||||||
|
res[curr_res],
|
||||||
|
&src_rect,
|
||||||
|
DISPMANX_PROTECTION_NONE,
|
||||||
|
&alpha,
|
||||||
|
NULL,
|
||||||
|
DISPMANX_NO_ROTATE);
|
||||||
|
ret = vc_dispmanx_update_submit_sync(update);
|
||||||
|
CHECK(ret == 0);
|
||||||
|
curr_res = !curr_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLFramebuffer::blit_osd()
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
ret = vc_dispmanx_resource_write_data(res[curr_res], type, pitch, image, &dst_rect);
|
||||||
|
CHECK(ret == 0);
|
||||||
|
update = vc_dispmanx_update_start(10);
|
||||||
|
CHECK(update);
|
||||||
|
ret = vc_dispmanx_element_change_source(update, element, res[curr_res]);
|
||||||
|
CHECK(ret == 0);
|
||||||
|
ret = vc_dispmanx_update_submit_sync(update);
|
||||||
|
CHECK(ret == 0);
|
||||||
|
curr_res = !curr_res;
|
||||||
|
}
|
42
raspi/glfb.h
Normal file
42
raspi/glfb.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2013 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __glthread__
|
||||||
|
#define __glthread__
|
||||||
|
#include <OpenThreads/Thread>
|
||||||
|
#include <vector>
|
||||||
|
#include <linux/fb.h> /* for screeninfo etc. */
|
||||||
|
|
||||||
|
class GLFramebuffer : public OpenThreads::Thread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GLFramebuffer(int x, int y);
|
||||||
|
~GLFramebuffer();
|
||||||
|
std::vector<unsigned char> *getOSDBuffer() { return &osd_buf; } /* pointer to OSD bounce buffer */
|
||||||
|
void blit();
|
||||||
|
fb_var_screeninfo getScreenInfo() { return si; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void *pdata; /* not yet used */
|
||||||
|
fb_var_screeninfo si;
|
||||||
|
std::vector<unsigned char> osd_buf; /* silly bounce buffer */
|
||||||
|
void run(); /* for OpenThreads::Thread */
|
||||||
|
|
||||||
|
void setup();
|
||||||
|
void blit_osd();
|
||||||
|
};
|
||||||
|
#endif
|
37
raspi/hardware_caps.c
Normal file
37
raspi/hardware_caps.c
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* determine the capabilities of the hardware.
|
||||||
|
* part of libstb-hal
|
||||||
|
*
|
||||||
|
* (C) 2010-2013 Stefan Seyfried
|
||||||
|
*
|
||||||
|
* License: GPL v2 or later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <hardware_caps.h>
|
||||||
|
|
||||||
|
static int initialized = 0;
|
||||||
|
static hw_caps_t caps;
|
||||||
|
|
||||||
|
hw_caps_t *get_hwcaps(void)
|
||||||
|
{
|
||||||
|
if (initialized)
|
||||||
|
return ∩︀
|
||||||
|
|
||||||
|
memset(&caps, 0, sizeof(hw_caps_t));
|
||||||
|
|
||||||
|
initialized = 1;
|
||||||
|
caps.can_shutdown = 1; /* for testing */
|
||||||
|
caps.display_type = HW_DISPLAY_LINE_TEXT;
|
||||||
|
caps.has_HDMI = 1;
|
||||||
|
caps.display_xres = 8;
|
||||||
|
strcpy(caps.boxvendor, "Raspberry");
|
||||||
|
strcpy(caps.boxname, "Pi");
|
||||||
|
|
||||||
|
return ∩︀
|
||||||
|
}
|
229
raspi/init.cpp
Normal file
229
raspi/init.cpp
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
/*
|
||||||
|
* (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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* libstb-hal initialisation and input conversion routines
|
||||||
|
* for the Raspberry Pi
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <cstring>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <map>
|
||||||
|
#include <OpenThreads/Thread>
|
||||||
|
|
||||||
|
#include "init_lib.h"
|
||||||
|
#include "lt_debug.h"
|
||||||
|
#include "glfb.h"
|
||||||
|
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_INIT, NULL, args)
|
||||||
|
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_INIT, NULL, args)
|
||||||
|
|
||||||
|
static bool initialized = false;
|
||||||
|
GLFramebuffer *glfb = NULL;
|
||||||
|
|
||||||
|
typedef std::map<uint16_t, uint16_t> keymap_t;
|
||||||
|
static keymap_t kmap;
|
||||||
|
|
||||||
|
static void init_keymap(void)
|
||||||
|
{
|
||||||
|
/* same as generic-pc/glfb.cpp */
|
||||||
|
kmap[KEY_ENTER] = KEY_OK;
|
||||||
|
kmap[KEY_ESC] = KEY_EXIT;
|
||||||
|
kmap[KEY_E] = KEY_EPG;
|
||||||
|
kmap[KEY_I] = KEY_INFO;
|
||||||
|
kmap[KEY_M] = KEY_MENU;
|
||||||
|
kmap[KEY_F12] = KEY_VOLUMEUP; /* different than glfb, as we */
|
||||||
|
kmap[KEY_F11] = KEY_VOLUMEDOWN; /* don't consider the keyboard */
|
||||||
|
kmap[KEY_F10] = KEY_MUTE; /* layout... */
|
||||||
|
kmap[KEY_H] = KEY_HELP;
|
||||||
|
kmap[KEY_P] = KEY_POWER;
|
||||||
|
kmap[KEY_F1] = KEY_RED;
|
||||||
|
kmap[KEY_F2] = KEY_GREEN;
|
||||||
|
kmap[KEY_F3] = KEY_YELLOW;
|
||||||
|
kmap[KEY_F4] = KEY_BLUE;
|
||||||
|
kmap[KEY_F5] = KEY_WWW;
|
||||||
|
kmap[KEY_F6] = KEY_SUBTITLE;
|
||||||
|
kmap[KEY_F7] = KEY_MOVE;
|
||||||
|
kmap[KEY_F8] = KEY_SLEEP;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Input: public OpenThreads::Thread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Input();
|
||||||
|
~Input();
|
||||||
|
private:
|
||||||
|
void run();
|
||||||
|
bool running;
|
||||||
|
};
|
||||||
|
|
||||||
|
Input::Input()
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
Input::~Input()
|
||||||
|
{
|
||||||
|
running = false;
|
||||||
|
join();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dirfilter(const struct dirent *d)
|
||||||
|
{
|
||||||
|
return !strncmp(d->d_name, "event", 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Input::run()
|
||||||
|
{
|
||||||
|
struct input_event in;
|
||||||
|
int out_fd;
|
||||||
|
struct dirent **namelist;
|
||||||
|
int n;
|
||||||
|
unsigned long bit = 0;
|
||||||
|
char inputstr[] = "/dev/input/event9999999";
|
||||||
|
std::set<int>in_fds;
|
||||||
|
int fd_max = 0;
|
||||||
|
fd_set rfds;
|
||||||
|
hal_set_threadname("hal:input");
|
||||||
|
init_keymap();
|
||||||
|
unlink("/tmp/neutrino.input");
|
||||||
|
mkfifo("/tmp/neutrino.input", 0600);
|
||||||
|
out_fd = open("/tmp/neutrino.input", O_RDWR|O_CLOEXEC|O_NONBLOCK);
|
||||||
|
if (out_fd < 0)
|
||||||
|
lt_info("could not create /tmp/neutrino.input. good luck. error: %m\n");
|
||||||
|
|
||||||
|
n = scandir("/dev/input", &namelist, dirfilter, NULL);
|
||||||
|
if (n < 0)
|
||||||
|
lt_info("no input devices /dev/input/eventX??\n");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (n--) {
|
||||||
|
strcpy(inputstr + strlen("/dev/input/"), namelist[n]->d_name);
|
||||||
|
free(namelist[n]);
|
||||||
|
int fd = open(inputstr, O_RDWR|O_CLOEXEC|O_NONBLOCK);
|
||||||
|
if (fd < 0) {
|
||||||
|
lt_info("could not open %s:%m\n", inputstr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ioctl(fd, EVIOCGBIT(0, EV_MAX), &bit);
|
||||||
|
if ((bit & (1 << EV_KEY)) == 0) {
|
||||||
|
close(fd);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
lt_info("input dev: %s bit: 0x%08lx fd: %d\n", inputstr, bit, fd);
|
||||||
|
in_fds.insert(fd);
|
||||||
|
if (fd > fd_max)
|
||||||
|
fd_max = fd;
|
||||||
|
}
|
||||||
|
free(namelist);
|
||||||
|
}
|
||||||
|
|
||||||
|
fd_max++;
|
||||||
|
running = true;
|
||||||
|
while (running) {
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
for (std::set<int>::iterator i = in_fds.begin(); i != in_fds.end(); ++i)
|
||||||
|
FD_SET((*i), &rfds);
|
||||||
|
|
||||||
|
/* timeout should not be necessary, but somehow cancel / cleanup did not
|
||||||
|
* work correctly with OpenThreads::Thread :-( */
|
||||||
|
struct timeval timeout = { 0, 100000 }; /* 100ms */
|
||||||
|
int ret = select(fd_max, &rfds, NULL, NULL, &timeout);
|
||||||
|
if (ret == 0) /* timed out */
|
||||||
|
continue;
|
||||||
|
if (ret < 0) {
|
||||||
|
lt_info("input: select returned %d (%m)\n", ret);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::set<int>::iterator i = in_fds.begin(); i != in_fds.end(); ++i) {
|
||||||
|
if (!FD_ISSET((*i), &rfds))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = read(*i, &in, sizeof(in));
|
||||||
|
if (ret != sizeof(in)) {
|
||||||
|
if (errno == ENODEV) {
|
||||||
|
close(*i);
|
||||||
|
lt_info("input fd %d vanished?\n", *i);
|
||||||
|
in_fds.erase(i);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (in.type != EV_KEY)
|
||||||
|
continue;
|
||||||
|
keymap_t::const_iterator j = kmap.find(in.code);
|
||||||
|
if (j != kmap.end())
|
||||||
|
in.code = j->second;
|
||||||
|
lt_debug("GLFB::%s:(fd %d) pushing 0x%x, value %d\n", __func__, *i, in.code, in.value);
|
||||||
|
write(out_fd, &in, sizeof(in));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (std::set<int>::iterator i = in_fds.begin(); i != in_fds.end(); ++i)
|
||||||
|
close(*i);
|
||||||
|
in_fds.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Input *thread = NULL;
|
||||||
|
|
||||||
|
void init_td_api()
|
||||||
|
{
|
||||||
|
if (!initialized)
|
||||||
|
lt_debug_init();
|
||||||
|
lt_info("%s begin, initialized=%d, debug=0x%02x\n", __func__, (int)initialized, debuglevel);
|
||||||
|
if (! glfb) {
|
||||||
|
int x = 1280, y = 720; /* default OSD FB resolution */
|
||||||
|
/*
|
||||||
|
* export GLFB_RESOLUTION=720,576
|
||||||
|
* to restore old default behviour
|
||||||
|
*/
|
||||||
|
const char *tmp = getenv("GLFB_RESOLUTION");
|
||||||
|
const char *p = NULL;
|
||||||
|
if (tmp)
|
||||||
|
p = strchr(tmp, ',');
|
||||||
|
if (p) {
|
||||||
|
x = atoi(tmp);
|
||||||
|
y = atoi(p + 1);
|
||||||
|
}
|
||||||
|
lt_info("%s: setting Framebuffer size to %dx%d\n", __func__, x, y);
|
||||||
|
if (!p)
|
||||||
|
lt_info("%s: export GLFB_RESOLUTION=\"<w>,<h>\" to set another resolution\n", __func__);
|
||||||
|
|
||||||
|
glfb = new GLFramebuffer(x, y); /* hard coded to PAL resolution for now */
|
||||||
|
}
|
||||||
|
if (! thread)
|
||||||
|
thread = new Input();
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shutdown_td_api()
|
||||||
|
{
|
||||||
|
lt_info("%s, initialized = %d\n", __func__, (int)initialized);
|
||||||
|
if (glfb)
|
||||||
|
delete glfb;
|
||||||
|
if (thread)
|
||||||
|
delete thread;
|
||||||
|
initialized = false;
|
||||||
|
}
|
5
raspi/init_lib.h
Normal file
5
raspi/init_lib.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#ifndef __INIT_TD_H
|
||||||
|
#define __INIT_TD_H
|
||||||
|
void init_td_api();
|
||||||
|
void shutdown_td_api();
|
||||||
|
#endif
|
1
raspi/playback.cpp
Symbolic link
1
raspi/playback.cpp
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../generic-pc/playback.cpp
|
1
raspi/playback.h
Symbolic link
1
raspi/playback.h
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../generic-pc/playback.h
|
1
raspi/pwrmngr.cpp
Symbolic link
1
raspi/pwrmngr.cpp
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../libspark/pwrmngr.cpp
|
1
raspi/pwrmngr.h
Symbolic link
1
raspi/pwrmngr.h
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../libspark/pwrmngr.h
|
1
raspi/record.cpp
Symbolic link
1
raspi/record.cpp
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../libspark/record.cpp
|
1
raspi/record_lib.h
Symbolic link
1
raspi/record_lib.h
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../libspark/record_lib.h
|
189
raspi/video.cpp
Normal file
189
raspi/video.cpp
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
* (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, write to the Free Software
|
||||||
|
* Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA
|
||||||
|
*
|
||||||
|
* cVideo dummy implementation
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include "video_lib.h"
|
||||||
|
#include "lt_debug.h"
|
||||||
|
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, this, args)
|
||||||
|
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_VIDEO, this, args)
|
||||||
|
#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_VIDEO, NULL, args)
|
||||||
|
|
||||||
|
cVideo *videoDecoder = NULL;
|
||||||
|
int system_rev = 0;
|
||||||
|
|
||||||
|
cVideo::cVideo(int, void *, void *, unsigned int)
|
||||||
|
{
|
||||||
|
lt_debug("%s\n", __func__);
|
||||||
|
display_aspect = DISPLAY_AR_16_9;
|
||||||
|
display_crop = DISPLAY_AR_MODE_LETTERBOX;
|
||||||
|
v_format = VIDEO_FORMAT_MPEG2;
|
||||||
|
}
|
||||||
|
|
||||||
|
cVideo::~cVideo(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int cVideo::setAspectRatio(int vformat, int cropping)
|
||||||
|
{
|
||||||
|
lt_info("%s(%d, %d)\n", __func__, vformat, cropping);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cVideo::getAspectRatio(void)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cVideo::setCroppingMode(int)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cVideo::Start(void *, unsigned short, unsigned short, void *)
|
||||||
|
{
|
||||||
|
lt_debug("%s running %d >\n", __func__, thread_running);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cVideo::Stop(bool)
|
||||||
|
{
|
||||||
|
lt_debug("%s running %d >\n", __func__, thread_running);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cVideo::setBlank(int)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cVideo::SetVideoSystem(int system, bool)
|
||||||
|
{
|
||||||
|
int h;
|
||||||
|
switch(system)
|
||||||
|
{
|
||||||
|
case VIDEO_STD_NTSC:
|
||||||
|
case VIDEO_STD_480P:
|
||||||
|
h = 480;
|
||||||
|
break;
|
||||||
|
case VIDEO_STD_1080I60:
|
||||||
|
case VIDEO_STD_1080I50:
|
||||||
|
case VIDEO_STD_1080P30:
|
||||||
|
case VIDEO_STD_1080P24:
|
||||||
|
case VIDEO_STD_1080P25:
|
||||||
|
case VIDEO_STD_1080P50:
|
||||||
|
h = 1080;
|
||||||
|
break;
|
||||||
|
case VIDEO_STD_720P50:
|
||||||
|
case VIDEO_STD_720P60:
|
||||||
|
h = 720;
|
||||||
|
break;
|
||||||
|
case VIDEO_STD_AUTO:
|
||||||
|
lt_info("%s: VIDEO_STD_AUTO not implemented\n", __func__);
|
||||||
|
// fallthrough
|
||||||
|
case VIDEO_STD_SECAM:
|
||||||
|
case VIDEO_STD_PAL:
|
||||||
|
case VIDEO_STD_576P:
|
||||||
|
h = 576;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
lt_info("%s: unhandled value %d\n", __func__, system);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
v_std = (VIDEO_STD) system;
|
||||||
|
output_h = h;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cVideo::getPlayState(void)
|
||||||
|
{
|
||||||
|
return VIDEO_PLAYING;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cVideo::SetVideoMode(analog_mode_t)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void cVideo::ShowPicture(const char *fname)
|
||||||
|
{
|
||||||
|
lt_info("%s(%s)\n", __func__, fname);
|
||||||
|
if (access(fname, R_OK))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cVideo::StopPicture()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void cVideo::Standby(unsigned int)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int cVideo::getBlank(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cVideo::Pig(int x, int y, int w, int h, int, int)
|
||||||
|
{
|
||||||
|
pig_x = x;
|
||||||
|
pig_y = y;
|
||||||
|
pig_w = w;
|
||||||
|
pig_h = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cVideo::getPictureInfo(int &width, int &height, int &rate)
|
||||||
|
{
|
||||||
|
width = dec_w;
|
||||||
|
height = dec_h;
|
||||||
|
rate = dec_r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cVideo::SetSyncMode(AVSYNC_TYPE)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
int cVideo::SetStreamType(VIDEO_FORMAT v)
|
||||||
|
{
|
||||||
|
v_format = v;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cVideo::GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video, bool get_osd, bool scale_to_video)
|
||||||
|
{
|
||||||
|
lt_info("%s: data 0x%p xres %d yres %d vid %d osd %d scale %d\n",
|
||||||
|
__func__, data, xres, yres, get_video, get_osd, scale_to_video);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t cVideo::GetPTS(void)
|
||||||
|
{
|
||||||
|
int64_t pts = 0;
|
||||||
|
return pts;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cVideo::SetDemux(cDemux *)
|
||||||
|
{
|
||||||
|
lt_debug("%s: not implemented yet\n", __func__);
|
||||||
|
}
|
215
raspi/video_lib.h
Normal file
215
raspi/video_lib.h
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
#ifndef _VIDEO_TD_H
|
||||||
|
#define _VIDEO_TD_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <linux/dvb/video.h>
|
||||||
|
#include "../common/cs_types.h"
|
||||||
|
#include "dmx_lib.h"
|
||||||
|
extern "C" {
|
||||||
|
#include <libavutil/rational.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ANALOG_SD_RGB_CINCH = 0x00,
|
||||||
|
ANALOG_SD_YPRPB_CINCH,
|
||||||
|
ANALOG_HD_RGB_CINCH,
|
||||||
|
ANALOG_HD_YPRPB_CINCH,
|
||||||
|
ANALOG_SD_RGB_SCART = 0x10,
|
||||||
|
ANALOG_SD_YPRPB_SCART,
|
||||||
|
ANALOG_HD_RGB_SCART,
|
||||||
|
ANALOG_HD_YPRPB_SCART,
|
||||||
|
ANALOG_SCART_MASK = 0x10
|
||||||
|
} analog_mode_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
VIDEO_FORMAT_MPEG2 = 0,
|
||||||
|
VIDEO_FORMAT_MPEG4,
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
#define VDEC_MAXBUFS 0x30
|
||||||
|
class cVideo
|
||||||
|
{
|
||||||
|
friend class GLFramebuffer;
|
||||||
|
friend class cDemux;
|
||||||
|
private:
|
||||||
|
/* called from GL thread */
|
||||||
|
class SWFramebuffer : public std::vector<unsigned char>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SWFramebuffer() : mWidth(0), mHeight(0) {}
|
||||||
|
void width(int w) { mWidth = w; }
|
||||||
|
void height(int h) { mHeight = h; }
|
||||||
|
void pts(uint64_t p) { mPts = p; }
|
||||||
|
void AR(AVRational a) { mAR = a; }
|
||||||
|
int width() const { return mWidth; }
|
||||||
|
int height() const { return mHeight; }
|
||||||
|
int64_t pts() const { return mPts; }
|
||||||
|
AVRational AR() const { return mAR; }
|
||||||
|
private:
|
||||||
|
int mWidth;
|
||||||
|
int mHeight;
|
||||||
|
int64_t mPts;
|
||||||
|
AVRational mAR;
|
||||||
|
};
|
||||||
|
int buf_in, buf_out, buf_num;
|
||||||
|
int64_t GetPTS(void);
|
||||||
|
public:
|
||||||
|
/* constructor & destructor */
|
||||||
|
cVideo(int mode, void *, void *, unsigned int unit = 0);
|
||||||
|
~cVideo(void);
|
||||||
|
|
||||||
|
void * GetTVEnc() { return NULL; };
|
||||||
|
void * GetTVEncSD() { return NULL; };
|
||||||
|
|
||||||
|
/* aspect ratio */
|
||||||
|
int getAspectRatio(void);
|
||||||
|
void getPictureInfo(int &width, int &height, int &rate);
|
||||||
|
int setAspectRatio(int aspect, int mode);
|
||||||
|
|
||||||
|
/* cropping mode */
|
||||||
|
int setCroppingMode(int x = 0 /*vidDispMode_t x = VID_DISPMODE_NORM*/);
|
||||||
|
|
||||||
|
/* get play state */
|
||||||
|
int getPlayState(void);
|
||||||
|
|
||||||
|
/* blank on freeze */
|
||||||
|
int getBlank(void);
|
||||||
|
int setBlank(int enable);
|
||||||
|
|
||||||
|
/* change video play state. Parameters are all unused. */
|
||||||
|
int Start(void *PcrChannel = NULL, unsigned short PcrPid = 0, unsigned short VideoPid = 0, void *x = NULL);
|
||||||
|
int Stop(bool blank = true);
|
||||||
|
bool Pause(void);
|
||||||
|
|
||||||
|
/* set video_system */
|
||||||
|
int SetVideoSystem(int video_system, bool remember = true);
|
||||||
|
int SetStreamType(VIDEO_FORMAT type);
|
||||||
|
void SetSyncMode(AVSYNC_TYPE mode);
|
||||||
|
bool SetCECMode(VIDEO_HDMI_CEC_MODE) { return true; };
|
||||||
|
void SetCECAutoView(bool) { return; };
|
||||||
|
void SetCECAutoStandby(bool) { return; };
|
||||||
|
void ShowPicture(const char * fname);
|
||||||
|
void StopPicture();
|
||||||
|
void Standby(unsigned int bOn);
|
||||||
|
void Pig(int x, int y, int w, int h, int osd_w = 1064, int osd_h = 600);
|
||||||
|
void SetControl(int, int) { return; };
|
||||||
|
void setContrast(int val);
|
||||||
|
void SetVideoMode(analog_mode_t mode);
|
||||||
|
void SetDBDR(int) { return; };
|
||||||
|
void SetAudioHandle(void *) { return; };
|
||||||
|
void SetAutoModes(int [VIDEO_STD_MAX]) { return; };
|
||||||
|
int OpenVBI(int) { return 0; };
|
||||||
|
int CloseVBI(void) { return 0; };
|
||||||
|
int StartVBI(unsigned short) { return 0; };
|
||||||
|
int StopVBI(void) { return 0; };
|
||||||
|
void SetDemux(cDemux *dmx);
|
||||||
|
bool GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video = true, bool get_osd = false, bool scale_to_video = false);
|
||||||
|
private:
|
||||||
|
SWFramebuffer buffers[VDEC_MAXBUFS];
|
||||||
|
int dec_w, dec_h;
|
||||||
|
int dec_r;
|
||||||
|
bool w_h_changed;
|
||||||
|
bool thread_running;
|
||||||
|
VIDEO_FORMAT v_format;
|
||||||
|
VIDEO_STD v_std;
|
||||||
|
DISPLAY_AR display_aspect;
|
||||||
|
DISPLAY_AR_MODE display_crop;
|
||||||
|
int output_h;
|
||||||
|
int pig_x;
|
||||||
|
int pig_y;
|
||||||
|
int pig_w;
|
||||||
|
int pig_h;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Reference in New Issue
Block a user