mirror of
https://github.com/tuxbox-fork-migrations/recycled-ni-libstb-hal.git
synced 2025-08-26 23:12:44 +02:00
Merge branch 'master' of https://bitbucket.org/max_10/libstb-hal-max
Origin commit data
------------------
Branch: master
Commit: dddd094e2b
Author: TangoCash <eric@loxat.de>
Date: 2018-10-02 (Tue, 02 Oct 2018)
------------------
No further description and justification available within origin commit message!
------------------
This commit was generated by Migit
This commit is contained in:
@@ -2,12 +2,11 @@ ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
lib_LTLIBRARIES = libstb-hal.la
|
||||
libstb_hal_la_SOURCES =
|
||||
SUBDIRS = common tools libthread
|
||||
SUBDIRS = common tools
|
||||
#bin_PROGRAMS = libstb-hal-test
|
||||
|
||||
libstb_hal_la_LIBADD = \
|
||||
common/libcommon.la \
|
||||
libthread/libthread.la
|
||||
common/libcommon.la
|
||||
|
||||
|
||||
#libstb_hal_test_SOURCES = libtest.cpp
|
||||
|
@@ -152,11 +152,11 @@ AC_SUBST(PLUGINDIR)
|
||||
AC_SUBST(THEMESDIR)
|
||||
dnl end workaround
|
||||
|
||||
AC_DEFUN([TUXBOX_BOXTYPE],[
|
||||
AC_DEFUN([TUXBOX_BOXTYPE], [
|
||||
AC_ARG_WITH(boxtype,
|
||||
[ --with-boxtype valid values: tripledragon,spark,azbox,generic,duckbox,spark7162,armbox],
|
||||
AS_HELP_STRING([--with-boxtype], [valid values: tripledragon, spark, azbox, generic, armbox, duckbox, spark7162]),
|
||||
[case "${withval}" in
|
||||
tripledragon|azbox|generic)
|
||||
tripledragon|azbox|generic|armbox)
|
||||
BOXTYPE="$withval"
|
||||
;;
|
||||
spark|spark7162)
|
||||
|
@@ -1652,6 +1652,13 @@ FROM_FIRST:
|
||||
bool cCA::SendCaPMT(eDVBCISlot* slot)
|
||||
{
|
||||
printf("%s -> %s\n", FILENAME, __func__);
|
||||
if (slot->fd > 0)
|
||||
{
|
||||
#if HAVE_ARM_HARDWARE
|
||||
setInputSource(slot, true);
|
||||
#endif
|
||||
setSource(slot);
|
||||
}
|
||||
if ((slot->fd > 0) && (slot->camIsReady))
|
||||
{
|
||||
if (slot->hasCAManager)
|
||||
@@ -1667,14 +1674,6 @@ bool cCA::SendCaPMT(eDVBCISlot* slot)
|
||||
slot->camgrSession->sendSPDU(0x90, 0, 0, slot->pmtdata, slot->pmtlen);
|
||||
}
|
||||
}
|
||||
|
||||
if (slot->fd > 0)
|
||||
{
|
||||
#if HAVE_ARM_HARDWARE
|
||||
setInputSource(slot, true);
|
||||
#endif
|
||||
setSource(slot);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
25
configure.ac
25
configure.ac
@@ -20,6 +20,18 @@ AC_DISABLE_STATIC
|
||||
AC_SYS_LARGEFILE
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
AC_ARG_ENABLE(clutter,
|
||||
AS_HELP_STRING(--enable-clutter, use clutter instead of OpenGL),
|
||||
,[enable_clutter=no])
|
||||
|
||||
AM_CONDITIONAL(USE_CLUTTER,test "$enable_clutter" = "yes")
|
||||
AM_CONDITIONAL(USE_OPENGL,test "$enable_clutter" = "no")
|
||||
if test "$enable_clutter" = "yes"; then
|
||||
AC_DEFINE(USE_CLUTTER,1,[use clutter instead of opengl])
|
||||
else
|
||||
AC_DEFINE(USE_OPENGL,1,[use opengl instead of clutter])
|
||||
fi
|
||||
|
||||
if test x"$BOXTYPE" = x"tripledragon"; then
|
||||
PKG_CHECK_MODULES([DIRECTFB], [directfb])
|
||||
fi
|
||||
@@ -54,6 +66,9 @@ if test x$BOXTYPE = xarmbox -a "$enable_gstreamer_10" = "yes"; then
|
||||
fi
|
||||
|
||||
if test x$BOXTYPE = xgeneric -a x$BOXMODEL != xraspi; then
|
||||
if test x"$enable_clutter" = xyes; then
|
||||
PKG_CHECK_MODULES([CLUTTER], [clutter-1.0])
|
||||
fi
|
||||
PKG_CHECK_MODULES([AVFORMAT], [libavformat >= 53.21.1])
|
||||
PKG_CHECK_MODULES([AVCODEC], [libavcodec >= 54.28.0])
|
||||
# don't know which version is exactly needed here...
|
||||
@@ -62,12 +77,20 @@ if test x$BOXTYPE = xgeneric -a x$BOXMODEL != xraspi; then
|
||||
PKG_CHECK_MODULES([SWRESAMPLE], [libswresample])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(flv2mpeg4,
|
||||
AS_HELP_STRING(--enable-flv2mpeg4, use flv2mpeg4 libeplayer3-arm),
|
||||
,[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])
|
||||
fi
|
||||
|
||||
AC_OUTPUT([
|
||||
Makefile
|
||||
common/Makefile
|
||||
libeplayer3/Makefile
|
||||
libeplayer3-arm/Makefile
|
||||
libthread/Makefile
|
||||
azbox/Makefile
|
||||
generic-pc/Makefile
|
||||
libduckbox/Makefile
|
||||
|
@@ -1,29 +1,44 @@
|
||||
noinst_LTLIBRARIES = libgeneric.la
|
||||
|
||||
AM_CPPFLAGS = -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
|
||||
AM_CPPFLAGS += -Wfatal-errors
|
||||
AM_CPPFLAGS += \
|
||||
-I$(top_srcdir)/common \
|
||||
-I$(top_srcdir)/include
|
||||
-I$(top_srcdir)/include \
|
||||
@AVUTIL_CFLAGS@ \
|
||||
@CLUTTER_CFLAGS@
|
||||
|
||||
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
|
||||
|
||||
AM_LDFLAGS = \
|
||||
-lglut -lGL -lGLU -lGLEW -lao \
|
||||
-lao \
|
||||
-lOpenThreads \
|
||||
@AVFORMAT_LIBS@ \
|
||||
@AVUTIL_LIBS@ \
|
||||
@AVCODEC_LIBS@ \
|
||||
@SWRESAMPLE_LIBS@ \
|
||||
@SWSCALE_LIBS@
|
||||
@SWSCALE_LIBS@ \
|
||||
@CLUTTER_LIBS@
|
||||
|
||||
if USE_OPENGL
|
||||
AM_LDFLAGS += -lglut -lGL -lGLU -lGLEW -lao
|
||||
endif
|
||||
|
||||
libgeneric_la_SOURCES = \
|
||||
hardware_caps.c \
|
||||
dmx.cpp \
|
||||
video.cpp \
|
||||
audio.cpp \
|
||||
glfb.cpp \
|
||||
init.cpp \
|
||||
record.cpp
|
||||
|
||||
if USE_CLUTTER
|
||||
libgeneric_la_SOURCES += clutterfb.cpp
|
||||
endif
|
||||
if USE_OPENGL
|
||||
libgeneric_la_SOURCES += glfb.cpp
|
||||
endif
|
||||
|
||||
if ENABLE_GSTREAMER_01
|
||||
libgeneric_la_SOURCES += \
|
||||
playback_gst_01.cpp
|
||||
|
@@ -29,6 +29,7 @@
|
||||
#define lt_debug(args...) _lt_debug(HAL_DEBUG_AUDIO, this, args)
|
||||
#define lt_info(args...) _lt_info(HAL_DEBUG_AUDIO, this, args)
|
||||
|
||||
#include <OpenThreads/Thread>
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
@@ -104,7 +105,7 @@ int cAudio::Start(void)
|
||||
{
|
||||
lt_debug("%s >\n", __func__);
|
||||
if (! HAL_nodec)
|
||||
Thread::startThread();
|
||||
OpenThreads::Thread::start();
|
||||
lt_debug("%s <\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
@@ -115,7 +116,7 @@ int cAudio::Stop(void)
|
||||
if (thread_started)
|
||||
{
|
||||
thread_started = false;
|
||||
Thread::joinThread();
|
||||
OpenThreads::Thread::join();
|
||||
}
|
||||
lt_debug("%s <\n", __func__);
|
||||
return 0;
|
||||
@@ -201,8 +202,34 @@ void cAudio::getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &m
|
||||
freq = 0;
|
||||
bitrate = 0; /* not used, but easy to get :-) */
|
||||
mode = 0; /* default: stereo */
|
||||
printf("cAudio::getAudioInfo c %p\n", c);
|
||||
if (c) {
|
||||
type = (c->codec_id != AV_CODEC_ID_MP2); /* only mpeg / not mpeg is indicated */
|
||||
switch (c->codec_id) {
|
||||
case AV_CODEC_ID_MP2:
|
||||
type = AUDIO_FMT_MPEG;
|
||||
break;
|
||||
case AV_CODEC_ID_MP3:
|
||||
type = AUDIO_FMT_MP3;
|
||||
break;
|
||||
case AV_CODEC_ID_AC3:
|
||||
case AV_CODEC_ID_TRUEHD:
|
||||
type = AUDIO_FMT_DOLBY_DIGITAL;
|
||||
break;
|
||||
case AV_CODEC_ID_EAC3:
|
||||
type = AUDIO_FMT_DD_PLUS;
|
||||
break;
|
||||
case AV_CODEC_ID_AAC:
|
||||
type = AUDIO_FMT_AAC;
|
||||
break;
|
||||
case AV_CODEC_ID_DTS:
|
||||
type = AUDIO_FMT_DTS;
|
||||
break;
|
||||
case AV_CODEC_ID_MLP:
|
||||
type = AUDIO_FMT_MLP;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
freq = c->sample_rate;
|
||||
bitrate = c->bit_rate;
|
||||
if (c->channels == 1)
|
||||
@@ -240,7 +267,7 @@ void cAudio::getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &m
|
||||
}
|
||||
}
|
||||
lt_debug("%s t: %d l: %d f: %d b: %d m: %d codec_id: %x\n",
|
||||
__func__, type, layer, freq, bitrate, mode, c ? c->codec_id : 0);
|
||||
__func__, type, layer, freq, bitrate, mode, c?c->codec_id:-1);
|
||||
};
|
||||
|
||||
void cAudio::SetSRS(int /*iq_enable*/, int /*nmgr_enable*/, int /*iq_mode*/, int /*iq_level*/)
|
||||
|
@@ -4,7 +4,7 @@
|
||||
#define _AUDIO_LIB_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <thread_abstraction.h>
|
||||
#include <OpenThreads/Thread>
|
||||
#include "cs_types.h"
|
||||
|
||||
typedef enum
|
||||
@@ -38,7 +38,7 @@ typedef enum
|
||||
AUDIO_FMT_ADVANCED = AUDIO_FMT_MLP
|
||||
} AUDIO_FORMAT;
|
||||
|
||||
class cAudio : public Thread
|
||||
class cAudio : public OpenThreads::Thread
|
||||
{
|
||||
friend class cPlayback;
|
||||
private:
|
||||
|
481
generic-pc/clutterfb.cpp
Normal file
481
generic-pc/clutterfb.cpp
Normal file
@@ -0,0 +1,481 @@
|
||||
/*
|
||||
Framebuffer implementation using clutter https://developer.gnome.org/clutter/
|
||||
Copyright (C) 2016 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
|
||||
|
||||
based on the openGL framebuffer implementation
|
||||
Copyright 2010 Carsten Juttner <carjay@gmx.net>
|
||||
Copyright 2012,2013 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
TODO: AV-Sync code is "experimental" at best
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <vector>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/input.h>
|
||||
#include "glfb_priv.h"
|
||||
#include "video_priv.h"
|
||||
#include "audio_priv.h"
|
||||
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
|
||||
#include "lt_debug.h"
|
||||
|
||||
#define lt_debug_c(args...) _lt_debug(HAL_DEBUG_INIT, NULL, args)
|
||||
#define lt_info_c(args...) _lt_info(HAL_DEBUG_INIT, NULL, args)
|
||||
#define lt_debug(args...) _lt_debug(HAL_DEBUG_INIT, this, args)
|
||||
#define lt_info(args...) _lt_info(HAL_DEBUG_INIT, this, args)
|
||||
|
||||
|
||||
extern VDec *vdec;
|
||||
extern ADec *adec;
|
||||
|
||||
/* the private class that does stuff only needed inside libstb-hal.
|
||||
* is used e.g. by cVideo... */
|
||||
GLFbPC *glfb_priv = NULL;
|
||||
|
||||
GLFramebuffer::GLFramebuffer(int x, int y)
|
||||
{
|
||||
Init();
|
||||
glfb_priv = new GLFbPC(x, y, osd_buf);
|
||||
si = glfb_priv->getScreenInfo();
|
||||
start();
|
||||
while (!glfb_priv->mInitDone)
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
GLFramebuffer::~GLFramebuffer()
|
||||
{
|
||||
glfb_priv->mShutDown = true;
|
||||
join();
|
||||
delete glfb_priv;
|
||||
glfb_priv = NULL;
|
||||
}
|
||||
|
||||
void GLFramebuffer::blit()
|
||||
{
|
||||
glfb_priv->blit();
|
||||
}
|
||||
|
||||
GLFbPC::GLFbPC(int x, int y, std::vector<unsigned char> &buf): mReInit(true), mShutDown(false), mInitDone(false)
|
||||
{
|
||||
osd_buf = &buf;
|
||||
mState.width = x;
|
||||
mState.height = y;
|
||||
mX = &_mX[0];
|
||||
mY = &_mY[0];
|
||||
*mX = x;
|
||||
*mY = y;
|
||||
av_reduce(&mOA.num, &mOA.den, x, y, INT_MAX);
|
||||
mVA = mOA; /* initial aspect ratios are from the FB resolution, those */
|
||||
_mVA = mVA; /* will be updated by the videoDecoder functions anyway */
|
||||
mVAchanged = true;
|
||||
mCrop = DISPLAY_AR_MODE_PANSCAN;
|
||||
zoom = 1.0;
|
||||
xscale = 1.0;
|
||||
const char *tmp = getenv("GLFB_FULLSCREEN");
|
||||
mFullscreen = !!(tmp);
|
||||
|
||||
mState.blit = true;
|
||||
last_apts = 0;
|
||||
|
||||
/* linux framebuffer compat mode */
|
||||
si.bits_per_pixel = 32;
|
||||
si.xres = mState.width;
|
||||
si.xres_virtual = si.xres;
|
||||
si.yres = mState.height;
|
||||
si.yres_virtual = si.yres;
|
||||
si.blue.length = 8;
|
||||
si.blue.offset = 0;
|
||||
si.green.length = 8;
|
||||
si.green.offset = 8;
|
||||
si.red.length = 8;
|
||||
si.red.offset = 16;
|
||||
si.transp.length = 8;
|
||||
si.transp.offset = 24;
|
||||
|
||||
unlink("/tmp/neutrino.input");
|
||||
mkfifo("/tmp/neutrino.input", 0600);
|
||||
input_fd = open("/tmp/neutrino.input", O_RDWR|O_CLOEXEC|O_NONBLOCK);
|
||||
if (input_fd < 0)
|
||||
lt_info("%s: could not open /tmp/neutrino.input FIFO: %m\n", __func__);
|
||||
initKeys();
|
||||
}
|
||||
|
||||
GLFbPC::~GLFbPC()
|
||||
{
|
||||
mShutDown = true;
|
||||
if (input_fd >= 0)
|
||||
close(input_fd);
|
||||
osd_buf->clear();
|
||||
}
|
||||
|
||||
void GLFbPC::initKeys()
|
||||
{
|
||||
mKeyMap[CLUTTER_KEY_Up] = KEY_UP;
|
||||
mKeyMap[CLUTTER_KEY_Down] = KEY_DOWN;
|
||||
mKeyMap[CLUTTER_KEY_Left] = KEY_LEFT;
|
||||
mKeyMap[CLUTTER_KEY_Right] = KEY_RIGHT;
|
||||
|
||||
mKeyMap[CLUTTER_KEY_F1] = KEY_RED;
|
||||
mKeyMap[CLUTTER_KEY_F2] = KEY_GREEN;
|
||||
mKeyMap[CLUTTER_KEY_F3] = KEY_YELLOW;
|
||||
mKeyMap[CLUTTER_KEY_F4] = KEY_BLUE;
|
||||
|
||||
mKeyMap[CLUTTER_KEY_F5] = KEY_WWW;
|
||||
mKeyMap[CLUTTER_KEY_F6] = KEY_SUBTITLE;
|
||||
mKeyMap[CLUTTER_KEY_F7] = KEY_MOVE;
|
||||
mKeyMap[CLUTTER_KEY_F8] = KEY_SLEEP;
|
||||
|
||||
mKeyMap[CLUTTER_KEY_Page_Up] = KEY_PAGEUP;
|
||||
mKeyMap[CLUTTER_KEY_Page_Down] = KEY_PAGEDOWN;
|
||||
|
||||
mKeyMap[CLUTTER_KEY_Return] = KEY_OK;
|
||||
mKeyMap[CLUTTER_KEY_Escape] = KEY_EXIT;
|
||||
mKeyMap['e'] = KEY_EPG;
|
||||
mKeyMap['i'] = KEY_INFO;
|
||||
mKeyMap['m'] = KEY_MENU;
|
||||
|
||||
mKeyMap['+'] = KEY_VOLUMEUP;
|
||||
mKeyMap['-'] = KEY_VOLUMEDOWN;
|
||||
mKeyMap['.'] = KEY_MUTE;
|
||||
mKeyMap['h'] = KEY_HELP;
|
||||
mKeyMap['p'] = KEY_POWER;
|
||||
|
||||
mKeyMap['0'] = KEY_0;
|
||||
mKeyMap['1'] = KEY_1;
|
||||
mKeyMap['2'] = KEY_2;
|
||||
mKeyMap['3'] = KEY_3;
|
||||
mKeyMap['4'] = KEY_4;
|
||||
mKeyMap['5'] = KEY_5;
|
||||
mKeyMap['6'] = KEY_6;
|
||||
mKeyMap['7'] = KEY_7;
|
||||
mKeyMap['8'] = KEY_8;
|
||||
mKeyMap['9'] = KEY_9;
|
||||
}
|
||||
|
||||
static ClutterActor *stage = NULL;
|
||||
static ClutterActor *fb_actor = NULL;
|
||||
static ClutterActor *vid_actor = NULL;
|
||||
static ClutterTimeline *tl = NULL;
|
||||
void GLFramebuffer::run()
|
||||
{
|
||||
int argc = 1;
|
||||
int x = glfb_priv->mState.width;
|
||||
int y = glfb_priv->mState.height;
|
||||
/* some dummy commandline for GLUT to be happy */
|
||||
char *a = (char *)"neutrino";
|
||||
char **argv = (char **)malloc(sizeof(char *) * 2);
|
||||
argv[0] = a;
|
||||
argv[1] = NULL;
|
||||
lt_info("GLFB: GL thread starting x %d y %d\n", x, y);
|
||||
if (clutter_init(&argc, &argv) != CLUTTER_INIT_SUCCESS) {
|
||||
lt_info("GLFB: error initializing clutter\n");
|
||||
return;
|
||||
}
|
||||
lt_info("GLFB: %s:%d\n", __func__, __LINE__);
|
||||
ClutterColor stage_color = { 0, 0, 0, 255 };
|
||||
stage = clutter_stage_new();
|
||||
clutter_actor_set_size(stage, x, y);
|
||||
clutter_actor_set_background_color(stage, &stage_color);
|
||||
clutter_actor_set_content_gravity(stage, CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT);
|
||||
//g_signal_connect(stage, "destroy", G_CALLBACK(clutter_main_quit), NULL);
|
||||
g_signal_connect(stage, "key-press-event", G_CALLBACK(GLFbPC::keyboardcb), (void *)1);
|
||||
g_signal_connect(stage, "key-release-event", G_CALLBACK(GLFbPC::keyboardcb), NULL);
|
||||
clutter_stage_set_user_resizable(CLUTTER_STAGE (stage), TRUE);
|
||||
clutter_actor_grab_key_focus(stage);
|
||||
clutter_actor_show(stage);
|
||||
|
||||
/* 32bit FB depth, *2 because tuxtxt uses a shadow buffer */
|
||||
int fbmem = x * y * 4 * 2;
|
||||
osd_buf.resize(fbmem);
|
||||
lt_info("GLFB: OSD buffer set to %d bytes at 0x%p\n", fbmem, osd_buf.data());
|
||||
|
||||
/* video plane is below FB plane, so it comes first */
|
||||
vid_actor = clutter_actor_new();
|
||||
ClutterContent *fb = clutter_image_new();
|
||||
/* osd_buf, because it starts up black */
|
||||
if (!clutter_image_set_data(CLUTTER_IMAGE(fb), osd_buf.data(), COGL_PIXEL_FORMAT_BGR_888, x, y, x*3, NULL)) {
|
||||
lt_info("GLFB::%s clutter_image_set_data failed? (vid)\n", __func__);
|
||||
_exit(1); /* life is hard */
|
||||
}
|
||||
clutter_actor_set_content(vid_actor, fb);
|
||||
g_object_unref(fb);
|
||||
clutter_actor_set_size(vid_actor, x, y);
|
||||
clutter_actor_set_position(vid_actor, 0, 0);
|
||||
clutter_actor_add_constraint(vid_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_WIDTH, 0));
|
||||
clutter_actor_add_constraint(vid_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_HEIGHT, 0));
|
||||
clutter_actor_add_constraint(vid_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_X, 0));
|
||||
clutter_actor_add_constraint(vid_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_Y, 0));
|
||||
clutter_actor_set_content_gravity(vid_actor, CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT);
|
||||
clutter_actor_set_pivot_point(vid_actor, 0.5, 0.5);
|
||||
clutter_actor_add_child(stage, vid_actor);
|
||||
clutter_actor_show(vid_actor);
|
||||
|
||||
fb_actor = clutter_actor_new();
|
||||
fb = clutter_image_new();
|
||||
if (!clutter_image_set_data(CLUTTER_IMAGE(fb), osd_buf.data(), COGL_PIXEL_FORMAT_BGRA_8888, x, y, x*4, NULL)) {
|
||||
lt_info("GLFB::%s clutter_image_set_data failed? (osd)\n", __func__);
|
||||
_exit(1); /* life is hard */
|
||||
}
|
||||
clutter_actor_set_content(fb_actor, fb);
|
||||
g_object_unref(fb);
|
||||
clutter_actor_set_size(fb_actor, x, y);
|
||||
clutter_actor_set_position(fb_actor, 0, 0);
|
||||
clutter_actor_add_constraint(fb_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_WIDTH, 0));
|
||||
clutter_actor_add_constraint(fb_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_HEIGHT, 0));
|
||||
clutter_actor_add_constraint(fb_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_X, 0));
|
||||
clutter_actor_add_constraint(fb_actor, clutter_bind_constraint_new(stage, CLUTTER_BIND_Y, 0));
|
||||
clutter_actor_set_content_gravity(fb_actor, CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT);
|
||||
clutter_actor_add_child(stage, fb_actor);
|
||||
clutter_actor_show(fb_actor);
|
||||
|
||||
glfb_priv->mInitDone = true; /* signal that setup is finished */
|
||||
tl = clutter_timeline_new(100);
|
||||
g_signal_connect(tl, "new-frame", G_CALLBACK(GLFbPC::rendercb), NULL);
|
||||
clutter_timeline_set_repeat_count(tl, -1);
|
||||
clutter_timeline_start(tl);
|
||||
clutter_main();
|
||||
lt_info("GLFB: GL thread stopping\n");
|
||||
}
|
||||
|
||||
/* static */ void GLFbPC::rendercb()
|
||||
{
|
||||
glfb_priv->render();
|
||||
}
|
||||
|
||||
/* static */ bool GLFbPC::keyboardcb(ClutterActor * /*actor*/, ClutterEvent *event, gpointer user_data)
|
||||
{
|
||||
guint key = clutter_event_get_key_symbol (event);
|
||||
int keystate = user_data ? 1 : 0;
|
||||
lt_info_c("GLFB::%s: 0x%x, %d\n", __func__, key, keystate);
|
||||
|
||||
struct input_event ev;
|
||||
if (key == 'f' && keystate)
|
||||
{
|
||||
lt_info_c("GLFB::%s: toggle fullscreen %s\n", __func__, glfb_priv->mFullscreen?"off":"on");
|
||||
glfb_priv->mFullscreen = !(glfb_priv->mFullscreen);
|
||||
glfb_priv->mReInit = true;
|
||||
return true;
|
||||
}
|
||||
std::map<int, int>::const_iterator i = glfb_priv->mKeyMap.find(key);
|
||||
if (i == glfb_priv->mKeyMap.end())
|
||||
return true;
|
||||
ev.code = i->second;
|
||||
ev.value = keystate; /* key own */
|
||||
ev.type = EV_KEY;
|
||||
gettimeofday(&ev.time, NULL);
|
||||
lt_debug_c("GLFB::%s: pushing 0x%x\n", __func__, ev.code);
|
||||
write(glfb_priv->input_fd, &ev, sizeof(ev));
|
||||
return true;
|
||||
}
|
||||
|
||||
int sleep_us = 30000;
|
||||
|
||||
void GLFbPC::render()
|
||||
{
|
||||
if(mShutDown)
|
||||
clutter_main_quit();
|
||||
|
||||
mReInitLock.lock();
|
||||
if (mReInit)
|
||||
{
|
||||
int xoff = 0;
|
||||
int yoff = 0;
|
||||
mVAchanged = true;
|
||||
mReInit = false;
|
||||
#if 0
|
||||
mX = &_mX[mFullscreen];
|
||||
mY = &_mY[mFullscreen];
|
||||
#endif
|
||||
*mX = *mY * mOA.num / mOA.den;
|
||||
if (mFullscreen) {
|
||||
clutter_stage_set_fullscreen(CLUTTER_STAGE(stage), TRUE);
|
||||
clutter_actor_show(stage);
|
||||
clutter_stage_ensure_redraw(CLUTTER_STAGE(stage));
|
||||
} else {
|
||||
clutter_stage_set_fullscreen(CLUTTER_STAGE(stage), FALSE);
|
||||
// *mX = *mY * mOA.num / mOA.den;
|
||||
clutter_actor_set_size(stage, *mX, *mY);
|
||||
}
|
||||
lt_info("%s: reinit mX:%d mY:%d xoff:%d yoff:%d fs %d\n",
|
||||
__func__, *mX, *mY, xoff, yoff, mFullscreen);
|
||||
}
|
||||
mReInitLock.unlock();
|
||||
|
||||
bltDisplayBuffer(); /* decoded video stream */
|
||||
if (mState.blit) {
|
||||
/* only blit manually after fb->blit(), this helps to find missed blit() calls */
|
||||
mState.blit = false;
|
||||
lt_debug("GLFB::%s blit!\n", __func__);
|
||||
bltOSDBuffer(); /* OSD */
|
||||
}
|
||||
|
||||
if (mVAchanged)
|
||||
{
|
||||
mVAchanged = false;
|
||||
zoom = 1.0;
|
||||
float xzoom = 1.0;
|
||||
//xscale = 1.0;
|
||||
int cmp = av_cmp_q(mVA, mOA);
|
||||
const AVRational a149 = { 14, 9 };
|
||||
switch (cmp) {
|
||||
default:
|
||||
case INT_MIN: /* invalid */
|
||||
case 0: /* identical */
|
||||
lt_debug("%s: mVA == mOA (or fullscreen mode :-)\n", __func__);
|
||||
break;
|
||||
case 1: /* mVA > mOA -- video is wider than display */
|
||||
lt_debug("%s: mVA > mOA\n", __func__);
|
||||
switch (mCrop) {
|
||||
case DISPLAY_AR_MODE_PANSCAN:
|
||||
zoom = av_q2d(mVA) / av_q2d(mOA);
|
||||
break;
|
||||
case DISPLAY_AR_MODE_LETTERBOX:
|
||||
break;
|
||||
case DISPLAY_AR_MODE_PANSCAN2:
|
||||
zoom = av_q2d(a149) / av_q2d(mOA);
|
||||
break;
|
||||
case DISPLAY_AR_MODE_NONE:
|
||||
xzoom = av_q2d(mOA) / av_q2d(mVA);
|
||||
zoom = av_q2d(mVA) / av_q2d(mOA);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case -1: /* mVA < mOA -- video is taller than display */
|
||||
lt_debug("%s: mVA < mOA\n", __func__);
|
||||
switch (mCrop) {
|
||||
case DISPLAY_AR_MODE_LETTERBOX:
|
||||
break;
|
||||
case DISPLAY_AR_MODE_PANSCAN2:
|
||||
if (av_cmp_q(a149, mOA) < 0) {
|
||||
zoom = av_q2d(mVA) * av_q2d(a149) / av_q2d(mOA);
|
||||
break;
|
||||
}
|
||||
/* fallthrough for output format 14:9 */
|
||||
case DISPLAY_AR_MODE_PANSCAN:
|
||||
zoom = av_q2d(mOA) / av_q2d(mVA);
|
||||
break;
|
||||
case DISPLAY_AR_MODE_NONE:
|
||||
xzoom = av_q2d(mOA) / av_q2d(mVA);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
lt_debug("zoom: %f xscale: %f xzoom: %f\n", zoom, xscale,xzoom);
|
||||
clutter_actor_set_scale(vid_actor, xscale*zoom*xzoom, zoom);
|
||||
}
|
||||
clutter_timeline_stop(tl);
|
||||
clutter_timeline_set_delay(tl, sleep_us/1000);
|
||||
clutter_timeline_start(tl);
|
||||
}
|
||||
|
||||
void GLFbPC::bltOSDBuffer()
|
||||
{
|
||||
// lt_info("%s\n", __func__);
|
||||
int x = glfb_priv->mState.width;
|
||||
int y = glfb_priv->mState.height;
|
||||
ClutterContent *fb = clutter_image_new();
|
||||
if (!clutter_image_set_data(CLUTTER_IMAGE(fb), osd_buf->data(), COGL_PIXEL_FORMAT_BGRA_8888, x, y, x*4, NULL)) {
|
||||
lt_info("GLFB::%s clutter_image_set_data failed?\n", __func__);
|
||||
_exit(1); /* life is hard */
|
||||
}
|
||||
clutter_actor_set_content(fb_actor, fb);
|
||||
g_object_unref(fb);
|
||||
clutter_actor_show(fb_actor);
|
||||
}
|
||||
|
||||
void GLFbPC::bltDisplayBuffer()
|
||||
{
|
||||
// lt_info("GLFB::%s vdec: %p\n", __func__, vdec);
|
||||
if (!vdec) /* cannot start yet */
|
||||
return;
|
||||
static bool warn = true;
|
||||
VDec::SWFramebuffer *buf = vdec->getDecBuf();
|
||||
if (!buf) {
|
||||
if (warn)
|
||||
lt_info("GLFB::%s did not get a buffer...\n", __func__);
|
||||
warn = false;
|
||||
return;
|
||||
}
|
||||
warn = true;
|
||||
int w = buf->width(), h = buf->height();
|
||||
if (w == 0 || h == 0)
|
||||
return;
|
||||
|
||||
AVRational a = buf->AR();
|
||||
if (a.den != 0 && a.num != 0 && av_cmp_q(a, _mVA)) {
|
||||
_mVA = a;
|
||||
/* _mVA is the raw buffer's aspect, mVA is the real scaled output aspect */
|
||||
av_reduce(&mVA.num, &mVA.den, w * a.num, h * a.den, INT_MAX);
|
||||
// mVA.num: 16 mVA.den: 9 w: 720 h: 576
|
||||
// 16*576/720/9 = 1.42222
|
||||
xscale = (double)mVA.num*h/(double)mVA.den/w;
|
||||
mVAchanged = true;
|
||||
}
|
||||
|
||||
ClutterContent *fb = clutter_image_new();
|
||||
if (!clutter_image_set_data(CLUTTER_IMAGE(fb), &(*buf)[0], COGL_PIXEL_FORMAT_BGR_888, w, h, w*3, NULL)) {
|
||||
lt_info("GLFB::%s clutter_image_set_data failed?\n", __func__);
|
||||
_exit(1); /* life is hard */
|
||||
}
|
||||
clutter_actor_set_content(vid_actor, fb);
|
||||
g_object_unref(fb);
|
||||
clutter_actor_show(vid_actor);
|
||||
|
||||
/* "rate control" mechanism starts here...
|
||||
* this implementation is pretty naive and not working too well, but
|
||||
* better this than nothing... :-) */
|
||||
int64_t apts = 0;
|
||||
int64_t vpts = buf->pts();
|
||||
if (adec)
|
||||
apts = adec->getPts();
|
||||
if (apts != last_apts) {
|
||||
int rate, dummy1, dummy2;
|
||||
if (apts < vpts)
|
||||
sleep_us = (sleep_us * 2 + (vpts - apts)*10/9) / 3;
|
||||
else if (sleep_us > 1000)
|
||||
sleep_us -= 1000;
|
||||
last_apts = apts;
|
||||
vdec->getPictureInfo(dummy1, dummy2, rate);
|
||||
if (rate > 0)
|
||||
rate = 2000000 / rate; /* limit to half the frame rate */
|
||||
else
|
||||
rate = 50000; /* minimum 20 fps */
|
||||
if (sleep_us > rate)
|
||||
sleep_us = rate;
|
||||
else if (sleep_us < 1)
|
||||
sleep_us = 1;
|
||||
}
|
||||
lt_debug("vpts: 0x%" PRIx64 " apts: 0x%" PRIx64 " diff: %6.3f sleep_us %d buf %d\n",
|
||||
buf->pts(), apts, (buf->pts() - apts)/90000.0, sleep_us, vdec->buf_num);
|
||||
}
|
@@ -64,15 +64,12 @@ static const char *DMX_T[] = {
|
||||
};
|
||||
|
||||
/* map the device numbers. for now only demux0 is used */
|
||||
#define NUM_DEMUXDEV 1
|
||||
static const char *devname[NUM_DEMUXDEV] = {
|
||||
static const char *devname[] = {
|
||||
"/dev/dvb/adapter0/demux0",
|
||||
"/dev/dvb/adapter0/demux0",
|
||||
"/dev/dvb/adapter0/demux0"
|
||||
};
|
||||
|
||||
#define NUM_DEMUX 1
|
||||
static int dmx_source[NUM_DEMUX] = { 0 };
|
||||
static bool init[NUM_DEMUXDEV] = { false };
|
||||
|
||||
/* uuuugly */
|
||||
static int dmx_tp_count = 0;
|
||||
#define MAX_TS_COUNT 8
|
||||
@@ -492,28 +489,12 @@ int cDemux::getUnit(void)
|
||||
|
||||
bool cDemux::SetSource(int unit, int source)
|
||||
{
|
||||
//lt_info_c("%s(%d, %d): not implemented yet\n", __func__, unit, source);
|
||||
//return true;
|
||||
if (unit >= NUM_DEMUX || unit < 0) {
|
||||
lt_info_c("%s: unit (%d) out of range, NUM_DEMUX %d\n", __func__, unit, NUM_DEMUX);
|
||||
return false;
|
||||
}
|
||||
lt_info_c("%s(%d, %d) => %d to %d\n", __func__, unit, source, dmx_source[unit], source);
|
||||
if (source < 0 || source >= NUM_DEMUXDEV)
|
||||
lt_info_c("%s(%d, %d) ERROR: source %d out of range!\n", __func__, unit, source, source);
|
||||
else
|
||||
dmx_source[unit] = source;
|
||||
lt_info_c("%s(%d, %d): not implemented yet\n", __func__, unit, source);
|
||||
return true;
|
||||
}
|
||||
|
||||
int cDemux::GetSource(int unit)
|
||||
{
|
||||
//lt_info_c("%s(%d): not implemented yet\n", __func__, unit);
|
||||
//return 0;
|
||||
if (unit >= NUM_DEMUX || unit < 0) {
|
||||
lt_info_c("%s: unit (%d) out of range, NUM_DEMUX %d\n", __func__, unit, NUM_DEMUX);
|
||||
return -1;
|
||||
}
|
||||
lt_info_c("%s(%d) => %d\n", __func__, unit, dmx_source[unit]);
|
||||
return dmx_source[unit];
|
||||
lt_info_c("%s(%d): not implemented yet\n", __func__, unit);
|
||||
return 0;
|
||||
}
|
||||
|
@@ -22,6 +22,7 @@
|
||||
TODO: AV-Sync code is "experimental" at best
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <vector>
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -37,8 +38,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/input.h>
|
||||
#include "glfb.h"
|
||||
#include <GL/glx.h>
|
||||
#include "glfb_priv.h"
|
||||
#include "video_lib.h"
|
||||
#include "audio_lib.h"
|
||||
|
||||
@@ -53,10 +53,36 @@
|
||||
extern cVideo *videoDecoder;
|
||||
extern cAudio *audioDecoder;
|
||||
|
||||
static GLFramebuffer *gThiz = 0; /* GLUT does not allow for an arbitrary argument to the render func */
|
||||
/* the private class that does stuff only needed inside libstb-hal.
|
||||
* is used e.g. by cVideo... */
|
||||
GLFbPC *glfb_priv = NULL;
|
||||
|
||||
GLFramebuffer::GLFramebuffer(int x, int y): mReInit(true), mShutDown(false), mInitDone(false)
|
||||
GLFramebuffer::GLFramebuffer(int x, int y)
|
||||
{
|
||||
Init();
|
||||
glfb_priv = new GLFbPC(x, y, osd_buf);
|
||||
si = glfb_priv->getScreenInfo();
|
||||
start();
|
||||
while (!glfb_priv->mInitDone)
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
GLFramebuffer::~GLFramebuffer()
|
||||
{
|
||||
glfb_priv->mShutDown = true;
|
||||
join();
|
||||
delete glfb_priv;
|
||||
glfb_priv = NULL;
|
||||
}
|
||||
|
||||
void GLFramebuffer::blit()
|
||||
{
|
||||
glfb_priv->blit();
|
||||
}
|
||||
|
||||
GLFbPC::GLFbPC(int x, int y, std::vector<unsigned char> &buf): mReInit(true), mShutDown(false), mInitDone(false)
|
||||
{
|
||||
osd_buf = &buf;
|
||||
mState.width = x;
|
||||
mState.height = y;
|
||||
mX = &_mX[0];
|
||||
@@ -77,19 +103,19 @@ GLFramebuffer::GLFramebuffer(int x, int y): mReInit(true), mShutDown(false), mIn
|
||||
last_apts = 0;
|
||||
|
||||
/* linux framebuffer compat mode */
|
||||
screeninfo.bits_per_pixel = 32;
|
||||
screeninfo.xres = mState.width;
|
||||
screeninfo.xres_virtual = screeninfo.xres;
|
||||
screeninfo.yres = mState.height;
|
||||
screeninfo.yres_virtual = screeninfo.yres;
|
||||
screeninfo.blue.length = 8;
|
||||
screeninfo.blue.offset = 0;
|
||||
screeninfo.green.length = 8;
|
||||
screeninfo.green.offset = 8;
|
||||
screeninfo.red.length = 8;
|
||||
screeninfo.red.offset = 16;
|
||||
screeninfo.transp.length = 8;
|
||||
screeninfo.transp.offset = 24;
|
||||
si.bits_per_pixel = 32;
|
||||
si.xres = mState.width;
|
||||
si.xres_virtual = si.xres;
|
||||
si.yres = mState.height;
|
||||
si.yres_virtual = si.yres;
|
||||
si.blue.length = 8;
|
||||
si.blue.offset = 0;
|
||||
si.green.length = 8;
|
||||
si.green.offset = 8;
|
||||
si.red.length = 8;
|
||||
si.red.offset = 16;
|
||||
si.transp.length = 8;
|
||||
si.transp.offset = 24;
|
||||
|
||||
unlink("/tmp/neutrino.input");
|
||||
mkfifo("/tmp/neutrino.input", 0600);
|
||||
@@ -97,21 +123,22 @@ GLFramebuffer::GLFramebuffer(int x, int y): mReInit(true), mShutDown(false), mIn
|
||||
if (input_fd < 0)
|
||||
lt_info("%s: could not open /tmp/neutrino.input FIFO: %m\n", __func__);
|
||||
initKeys();
|
||||
Thread::startThread();
|
||||
while (!mInitDone)
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
GLFramebuffer::~GLFramebuffer()
|
||||
GLFbPC::~GLFbPC()
|
||||
{
|
||||
mShutDown = true;
|
||||
Thread::joinThread();
|
||||
if (input_fd >= 0)
|
||||
close(input_fd);
|
||||
osd_buf->clear();
|
||||
}
|
||||
|
||||
void GLFramebuffer::initKeys()
|
||||
void GLFbPC::initKeys()
|
||||
{
|
||||
/*
|
||||
Keep in sync with initKeys() in clutterfb.cpp
|
||||
*/
|
||||
|
||||
mSpecialMap[GLUT_KEY_UP] = KEY_UP;
|
||||
mSpecialMap[GLUT_KEY_DOWN] = KEY_DOWN;
|
||||
mSpecialMap[GLUT_KEY_LEFT] = KEY_LEFT;
|
||||
@@ -132,8 +159,8 @@ void GLFramebuffer::initKeys()
|
||||
mSpecialMap[GLUT_KEY_F11] = KEY_NEXT;
|
||||
mSpecialMap[GLUT_KEY_F12] = KEY_PREVIOUS;
|
||||
|
||||
mSpecialMap[GLUT_KEY_PAGE_UP] = KEY_PAGEUP;
|
||||
mSpecialMap[GLUT_KEY_PAGE_DOWN] = KEY_PAGEDOWN;
|
||||
mSpecialMap[GLUT_KEY_PAGE_UP] = KEY_PAGEUP;
|
||||
mSpecialMap[GLUT_KEY_PAGE_DOWN] = KEY_PAGEDOWN;
|
||||
|
||||
mKeyMap[0x0d] = KEY_OK;
|
||||
mKeyMap[0x1b] = KEY_EXIT;
|
||||
@@ -176,9 +203,21 @@ void GLFramebuffer::initKeys()
|
||||
|
||||
void GLFramebuffer::run()
|
||||
{
|
||||
setupCtx();
|
||||
setupOSDBuffer();
|
||||
mInitDone = true; /* signal that setup is finished */
|
||||
int argc = 1;
|
||||
int x = glfb_priv->mState.width;
|
||||
int y = glfb_priv->mState.height;
|
||||
/* some dummy commandline for GLUT to be happy */
|
||||
char const *argv[2] = { "neutrino", 0 };
|
||||
lt_info("GLFB: GL thread starting x %d y %d\n", x, y);
|
||||
glutInit(&argc, const_cast<char **>(argv));
|
||||
glutInitWindowSize(x, y);
|
||||
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
|
||||
glutCreateWindow("Neutrino");
|
||||
/* 32bit FB depth, *2 because tuxtxt uses a shadow buffer */
|
||||
int fbmem = x * y * 4 * 2;
|
||||
osd_buf.resize(fbmem);
|
||||
lt_info("GLFB: OSD buffer set to %d bytes at 0x%p\n", fbmem, osd_buf.data());
|
||||
glfb_priv->mInitDone = true; /* signal that setup is finished */
|
||||
|
||||
/* init the good stuff */
|
||||
GLenum err = glewInit();
|
||||
@@ -193,16 +232,15 @@ void GLFramebuffer::run()
|
||||
}
|
||||
else
|
||||
{
|
||||
gThiz = this;
|
||||
glutSetCursor(GLUT_CURSOR_NONE);
|
||||
glutDisplayFunc(GLFramebuffer::rendercb);
|
||||
glutKeyboardFunc(GLFramebuffer::keyboardcb);
|
||||
glutSpecialFunc(GLFramebuffer::specialcb);
|
||||
glutReshapeFunc(GLFramebuffer::resizecb);
|
||||
setupGLObjects(); /* needs GLEW prototypes */
|
||||
glutDisplayFunc(GLFbPC::rendercb);
|
||||
glutKeyboardFunc(GLFbPC::keyboardcb);
|
||||
glutSpecialFunc(GLFbPC::specialcb);
|
||||
glutReshapeFunc(GLFbPC::resizecb);
|
||||
glfb_priv->setupGLObjects(); /* needs GLEW prototypes */
|
||||
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
|
||||
glutMainLoop();
|
||||
releaseGLObjects();
|
||||
glfb_priv->releaseGLObjects();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -210,21 +248,20 @@ void GLFramebuffer::run()
|
||||
lt_info("GLFB: GL thread stopping\n");
|
||||
}
|
||||
|
||||
|
||||
void GLFramebuffer::setupCtx()
|
||||
#if 0
|
||||
void GLFbPC::setupCtx()
|
||||
{
|
||||
int argc = 1;
|
||||
/* some dummy commandline for GLUT to be happy */
|
||||
char const *argv[2] = { "neutrino", 0 };
|
||||
lt_info("GLFB: GL thread starting\n");
|
||||
lt_info("GLFB: GL thread starting x %d y %d\n", mX[0], mY[0]);
|
||||
glutInit(&argc, const_cast<char **>(argv));
|
||||
glutInitWindowSize(mX[0], mY[0]);
|
||||
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
|
||||
glutCreateWindow("Neutrino");
|
||||
GLWinID = glXGetCurrentDrawable(); // this was the holy grail to get the right window handle for gstreamer :D
|
||||
}
|
||||
|
||||
void GLFramebuffer::setupOSDBuffer()
|
||||
void GLFbPC::setupOSDBuffer()
|
||||
{ /* the OSD buffer size can be decoupled from the actual
|
||||
window size since the GL can blit-stretch with no
|
||||
trouble at all, ah, the luxury of ignorance... */
|
||||
@@ -233,12 +270,13 @@ void GLFramebuffer::setupOSDBuffer()
|
||||
{
|
||||
/* 32bit FB depth, *2 because tuxtxt uses a shadow buffer */
|
||||
int fbmem = mState.width * mState.height * 4 * 2;
|
||||
mOSDBuffer.resize(fbmem);
|
||||
lt_info("GLFB: OSD buffer set to %d bytes\n", fbmem);
|
||||
osd_buf->resize(fbmem);
|
||||
lt_info("GLFB: OSD buffer set to %d bytes at 0x%p\n", fbmem, osd_buf->data());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void GLFramebuffer::setupGLObjects()
|
||||
void GLFbPC::setupGLObjects()
|
||||
{
|
||||
unsigned char buf[4] = { 0, 0, 0, 0 }; /* 1 black pixel */
|
||||
glGenTextures(1, &mState.osdtex);
|
||||
@@ -266,7 +304,7 @@ void GLFramebuffer::setupGLObjects()
|
||||
}
|
||||
|
||||
|
||||
void GLFramebuffer::releaseGLObjects()
|
||||
void GLFbPC::releaseGLObjects()
|
||||
{
|
||||
glDeleteBuffers(1, &mState.pbo);
|
||||
glDeleteBuffers(1, &mState.displaypbo);
|
||||
@@ -275,56 +313,56 @@ void GLFramebuffer::releaseGLObjects()
|
||||
}
|
||||
|
||||
|
||||
/* static */ void GLFramebuffer::rendercb()
|
||||
/* static */ void GLFbPC::rendercb()
|
||||
{
|
||||
gThiz->render();
|
||||
glfb_priv->render();
|
||||
}
|
||||
|
||||
|
||||
/* static */ void GLFramebuffer::keyboardcb(unsigned char key, int /*x*/, int /*y*/)
|
||||
/* static */ void GLFbPC::keyboardcb(unsigned char key, int /*x*/, int /*y*/)
|
||||
{
|
||||
lt_debug_c("GLFB::%s: 0x%x\n", __func__, key);
|
||||
struct input_event ev;
|
||||
if (key == 'f')
|
||||
{
|
||||
lt_info_c("GLFB::%s: toggle fullscreen %s\n", __func__, gThiz->mFullscreen?"off":"on");
|
||||
gThiz->mFullscreen = !(gThiz->mFullscreen);
|
||||
gThiz->mReInit = true;
|
||||
lt_info_c("GLFB::%s: toggle fullscreen %s\n", __func__, glfb_priv->mFullscreen?"off":"on");
|
||||
glfb_priv->mFullscreen = !(glfb_priv->mFullscreen);
|
||||
glfb_priv->mReInit = true;
|
||||
return;
|
||||
}
|
||||
std::map<unsigned char, int>::const_iterator i = gThiz->mKeyMap.find(key);
|
||||
if (i == gThiz->mKeyMap.end())
|
||||
std::map<unsigned char, int>::const_iterator i = glfb_priv->mKeyMap.find(key);
|
||||
if (i == glfb_priv->mKeyMap.end())
|
||||
return;
|
||||
ev.code = i->second;
|
||||
ev.value = 1; /* key own */
|
||||
ev.type = EV_KEY;
|
||||
gettimeofday(&ev.time, NULL);
|
||||
lt_debug_c("GLFB::%s: pushing 0x%x\n", __func__, ev.code);
|
||||
write(gThiz->input_fd, &ev, sizeof(ev));
|
||||
write(glfb_priv->input_fd, &ev, sizeof(ev));
|
||||
ev.value = 0; /* neutrino is stupid, so push key up directly after key down */
|
||||
write(gThiz->input_fd, &ev, sizeof(ev));
|
||||
write(glfb_priv->input_fd, &ev, sizeof(ev));
|
||||
}
|
||||
|
||||
/* static */ void GLFramebuffer::specialcb(int key, int /*x*/, int /*y*/)
|
||||
/* static */ void GLFbPC::specialcb(int key, int /*x*/, int /*y*/)
|
||||
{
|
||||
lt_debug_c("GLFB::%s: 0x%x\n", __func__, key);
|
||||
struct input_event ev;
|
||||
std::map<int, int>::const_iterator i = gThiz->mSpecialMap.find(key);
|
||||
if (i == gThiz->mSpecialMap.end())
|
||||
std::map<int, int>::const_iterator i = glfb_priv->mSpecialMap.find(key);
|
||||
if (i == glfb_priv->mSpecialMap.end())
|
||||
return;
|
||||
ev.code = i->second;
|
||||
ev.value = 1;
|
||||
ev.type = EV_KEY;
|
||||
gettimeofday(&ev.time, NULL);
|
||||
lt_debug_c("GLFB::%s: pushing 0x%x\n", __func__, ev.code);
|
||||
write(gThiz->input_fd, &ev, sizeof(ev));
|
||||
write(glfb_priv->input_fd, &ev, sizeof(ev));
|
||||
ev.value = 0;
|
||||
write(gThiz->input_fd, &ev, sizeof(ev));
|
||||
write(glfb_priv->input_fd, &ev, sizeof(ev));
|
||||
}
|
||||
|
||||
int sleep_us = 30000;
|
||||
|
||||
void GLFramebuffer::render()
|
||||
void GLFbPC::render()
|
||||
{
|
||||
if(mShutDown)
|
||||
glutLeaveMainLoop();
|
||||
@@ -452,12 +490,12 @@ void GLFramebuffer::render()
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
/* static */ void GLFramebuffer::resizecb(int w, int h)
|
||||
/* static */ void GLFbPC::resizecb(int w, int h)
|
||||
{
|
||||
gThiz->checkReinit(w, h);
|
||||
glfb_priv->checkReinit(w, h);
|
||||
}
|
||||
|
||||
void GLFramebuffer::checkReinit(int x, int y)
|
||||
void GLFbPC::checkReinit(int x, int y)
|
||||
{
|
||||
static int last_x = 0, last_y = 0;
|
||||
|
||||
@@ -477,7 +515,7 @@ void GLFramebuffer::checkReinit(int x, int y)
|
||||
last_y = y;
|
||||
}
|
||||
|
||||
void GLFramebuffer::drawSquare(float size, float x_factor)
|
||||
void GLFbPC::drawSquare(float size, float x_factor)
|
||||
{
|
||||
GLfloat vertices[] = {
|
||||
1.0f, 1.0f,
|
||||
@@ -533,11 +571,11 @@ void GLFramebuffer::drawSquare(float size, float x_factor)
|
||||
}
|
||||
|
||||
|
||||
void GLFramebuffer::bltOSDBuffer()
|
||||
void GLFbPC::bltOSDBuffer()
|
||||
{
|
||||
/* FIXME: copy each time */
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mState.pbo);
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, mOSDBuffer.size(), &mOSDBuffer[0], GL_STREAM_DRAW_ARB);
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, osd_buf->size(), osd_buf->data(), GL_STREAM_DRAW_ARB);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, mState.osdtex);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mState.width, mState.height, GL_BGRA, GL_UNSIGNED_BYTE, 0);
|
||||
@@ -545,7 +583,7 @@ void GLFramebuffer::bltOSDBuffer()
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
|
||||
void GLFramebuffer::bltDisplayBuffer()
|
||||
void GLFbPC::bltDisplayBuffer()
|
||||
{
|
||||
if (!videoDecoder) /* cannot start yet */
|
||||
return;
|
||||
@@ -553,7 +591,7 @@ void GLFramebuffer::bltDisplayBuffer()
|
||||
cVideo::SWFramebuffer *buf = videoDecoder->getDecBuf();
|
||||
if (!buf) {
|
||||
if (warn)
|
||||
lt_debug("GLFB::%s did not get a buffer...\n", __func__);
|
||||
lt_info("GLFB::%s did not get a buffer...\n", __func__);
|
||||
warn = false;
|
||||
return;
|
||||
}
|
||||
@@ -606,9 +644,3 @@ void GLFramebuffer::bltDisplayBuffer()
|
||||
lt_debug("vpts: 0x%" PRIx64 " apts: 0x%" PRIx64 " diff: %6.3f sleep_us %d buf %d\n",
|
||||
buf->pts(), apts, (buf->pts() - apts)/90000.0, sleep_us, videoDecoder->buf_num);
|
||||
}
|
||||
|
||||
void GLFramebuffer::clear()
|
||||
{
|
||||
/* clears front and back buffer */
|
||||
memset(&mOSDBuffer[0], 0, mOSDBuffer.size());
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Copyright 2010 Carsten Juttner <carjay@gmx.net>
|
||||
Copyright 2012,2013 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
|
||||
Copyright 2012,2013,2016 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -14,44 +14,46 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
********************************************************************
|
||||
private stuff of the GLFB thread that is only used inside libstb-hal
|
||||
and not exposed to the application.
|
||||
*/
|
||||
|
||||
#ifndef __glthread__
|
||||
#define __glthread__
|
||||
#include <thread_abstraction.h>
|
||||
#include <mutex_abstraction.h>
|
||||
|
||||
#ifndef __glfb_priv__
|
||||
#define __glfb_priv__
|
||||
#include <OpenThreads/Mutex>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#if USE_OPENGL
|
||||
#include <GL/glew.h>
|
||||
#include <GL/freeglut.h>
|
||||
#include <GL/gl.h>
|
||||
#include <linux/fb.h> /* for screeninfo etc. */
|
||||
#endif
|
||||
#if USE_CLUTTER
|
||||
#include <clutter/clutter.h>
|
||||
#endif
|
||||
#include "glfb.h"
|
||||
extern "C" {
|
||||
#include <libavutil/rational.h>
|
||||
}
|
||||
|
||||
class GLFramebuffer : public Thread
|
||||
class GLFbPC
|
||||
{
|
||||
public:
|
||||
GLFramebuffer(int x, int y);
|
||||
~GLFramebuffer();
|
||||
|
||||
void run();
|
||||
std::vector<unsigned char> *getOSDBuffer() { return &mOSDBuffer; } /* pointer to OSD bounce buffer */
|
||||
|
||||
GLFbPC(int x, int y, std::vector<unsigned char> &buf);
|
||||
~GLFbPC();
|
||||
std::vector<unsigned char> *getOSDBuffer() { return osd_buf; } /* pointer to OSD bounce buffer */
|
||||
int getOSDWidth() { return mState.width; }
|
||||
int getOSDHeight() { return mState.height; }
|
||||
void blit() { mState.blit = true; }
|
||||
|
||||
void blit() { mState.blit = true; };
|
||||
fb_var_screeninfo getScreenInfo() { return si; }
|
||||
void setOutputFormat(AVRational a, int h, int c) { mOA = a; *mY = h; mCrop = c; mReInit = true; }
|
||||
|
||||
void clear();
|
||||
fb_var_screeninfo getScreenInfo() { return screeninfo; }
|
||||
int getWindowID() { return GLWinID; }
|
||||
|
||||
/* just make everything public for simplicity - this is only used inside libstb-hal anyway
|
||||
private:
|
||||
fb_var_screeninfo screeninfo;
|
||||
*/
|
||||
fb_var_screeninfo si;
|
||||
int *mX;
|
||||
int *mY;
|
||||
int _mX[2]; /* output window size */
|
||||
@@ -63,45 +65,59 @@ private:
|
||||
float zoom; /* for cropping */
|
||||
float xscale; /* and aspect ratio */
|
||||
int mCrop; /* DISPLAY_AR_MODE */
|
||||
int GLWinID;
|
||||
|
||||
bool mFullscreen; /* fullscreen? */
|
||||
bool mReInit; /* setup things for GL */
|
||||
Mutex mReInitLock;
|
||||
OpenThreads::Mutex mReInitLock;
|
||||
bool mShutDown; /* if set main loop is left */
|
||||
bool mInitDone; /* condition predicate */
|
||||
// OpenThreads::Condition mInitCond; /* condition variable for init */
|
||||
// mutable OpenThreads::Mutex mMutex; /* lock our data */
|
||||
|
||||
std::vector<unsigned char> mOSDBuffer; /* silly bounce buffer */
|
||||
std::vector<unsigned char> *osd_buf; /* silly bounce buffer */
|
||||
|
||||
#if USE_OPENGL
|
||||
std::map<unsigned char, int> mKeyMap;
|
||||
std::map<int, int> mSpecialMap;
|
||||
#endif
|
||||
#if USE_CLUTTER
|
||||
std::map<int, int> mKeyMap;
|
||||
#endif
|
||||
int input_fd;
|
||||
int64_t last_apts;
|
||||
void run();
|
||||
|
||||
static void rendercb(); /* callback for GLUT */
|
||||
void render(); /* actual render function */
|
||||
#if USE_OPENGL
|
||||
static void keyboardcb(unsigned char key, int x, int y);
|
||||
static void specialcb(int key, int x, int y);
|
||||
static void resizecb(int w, int h);
|
||||
void checkReinit(int w, int h); /* e.g. in case window was resized */
|
||||
|
||||
void initKeys(); /* setup key bindings for window */
|
||||
void setupCtx(); /* create the window and make the context current */
|
||||
void setupOSDBuffer(); /* create the OSD buffer */
|
||||
void setupGLObjects(); /* PBOs, textures and stuff */
|
||||
void releaseGLObjects();
|
||||
void drawSquare(float size, float x_factor = 1); /* do not be square */
|
||||
#endif
|
||||
#if USE_CLUTTER
|
||||
static bool keyboardcb(ClutterActor *actor, ClutterEvent *event, gpointer user_data);
|
||||
#endif
|
||||
|
||||
void initKeys(); /* setup key bindings for window */
|
||||
#if 0
|
||||
void setupCtx(); /* create the window and make the context current */
|
||||
void setupOSDBuffer(); /* create the OSD buffer */
|
||||
#endif
|
||||
|
||||
struct {
|
||||
int width; /* width and height, fixed for a framebuffer instance */
|
||||
int height;
|
||||
bool blit;
|
||||
#if USE_OPENGL
|
||||
GLuint osdtex; /* holds the OSD texture */
|
||||
GLuint pbo; /* PBO we use for transfer to texture */
|
||||
GLuint displaytex; /* holds the display texture */
|
||||
GLuint displaypbo;
|
||||
bool blit;
|
||||
#endif
|
||||
} mState;
|
||||
|
||||
void bltOSDBuffer();
|
@@ -1,4 +1,5 @@
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "init_td.h"
|
||||
|
@@ -23,6 +23,7 @@
|
||||
* TODO: buffer handling surely needs some locking...
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
@@ -39,9 +40,16 @@ extern "C" {
|
||||
/* my own buf 256k */
|
||||
#define DMX_BUF_SZ 0x20000
|
||||
|
||||
#if USE_OPENGL
|
||||
#define VDEC_PIXFMT AV_PIX_FMT_RGB32
|
||||
#endif
|
||||
#if USE_CLUTTER
|
||||
#define VDEC_PIXFMT AV_PIX_FMT_BGR24
|
||||
#endif
|
||||
|
||||
#include "video_lib.h"
|
||||
#include "dmx_hal.h"
|
||||
#include "glfb.h"
|
||||
#include "glfb_priv.h"
|
||||
#include "lt_debug.h"
|
||||
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, this, args)
|
||||
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_VIDEO, this, args)
|
||||
@@ -49,7 +57,7 @@ extern "C" {
|
||||
|
||||
cVideo *videoDecoder = NULL;
|
||||
extern cDemux *videoDemux;
|
||||
extern GLFramebuffer *glfb;
|
||||
extern GLFbPC *glfb_priv;
|
||||
int system_rev = 0;
|
||||
|
||||
extern bool HAL_nodec;
|
||||
@@ -103,7 +111,7 @@ int cVideo::setAspectRatio(int vformat, int cropping)
|
||||
if (cropping >= 0)
|
||||
display_crop = (DISPLAY_AR_MODE) cropping;
|
||||
if (display_aspect < DISPLAY_AR_RAW && output_h > 0) /* don't know what to do with this */
|
||||
glfb->setOutputFormat(aspect_ratios[display_aspect], output_h, display_crop);
|
||||
glfb_priv->setOutputFormat(aspect_ratios[display_aspect], output_h, display_crop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -145,7 +153,7 @@ int cVideo::Start(void *, unsigned short, unsigned short, void *)
|
||||
{
|
||||
lt_debug("%s running %d >\n", __func__, thread_running);
|
||||
if (!thread_running && !HAL_nodec)
|
||||
Thread::startThread();
|
||||
OpenThreads::Thread::start();
|
||||
lt_debug("%s running %d <\n", __func__, thread_running);
|
||||
return 0;
|
||||
}
|
||||
@@ -155,7 +163,7 @@ int cVideo::Stop(bool)
|
||||
lt_debug("%s running %d >\n", __func__, thread_running);
|
||||
if (thread_running) {
|
||||
thread_running = false;
|
||||
Thread::joinThread();
|
||||
OpenThreads::Thread::join();
|
||||
}
|
||||
lt_debug("%s running %d <\n", __func__, thread_running);
|
||||
return 0;
|
||||
@@ -214,7 +222,7 @@ int cVideo::SetVideoSystem(int system, bool)
|
||||
// v_std = (VIDEO_STD) system;
|
||||
output_h = h;
|
||||
if (display_aspect < DISPLAY_AR_RAW && output_h > 0) /* don't know what to do with this */
|
||||
glfb->setOutputFormat(aspect_ratios[display_aspect], output_h, display_crop);
|
||||
glfb_priv->setOutputFormat(aspect_ratios[display_aspect], output_h, display_crop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -294,9 +302,9 @@ void cVideo::ShowPicture(const char *fname)
|
||||
if (avpkt.size > len)
|
||||
lt_info("%s: WARN: pkt->size %d != len %d\n", __func__, avpkt.size, len);
|
||||
if (got_frame) {
|
||||
unsigned int need = av_image_get_buffer_size(AV_PIX_FMT_RGB32, c->width, c->height, 1);
|
||||
unsigned int need = av_image_get_buffer_size(VDEC_PIXFMT, c->width, c->height, 1);
|
||||
struct SwsContext *convert = sws_getContext(c->width, c->height, c->pix_fmt,
|
||||
c->width, c->height, AV_PIX_FMT_RGB32,
|
||||
c->width, c->height, VDEC_PIXFMT,
|
||||
SWS_BICUBIC, 0, 0, 0);
|
||||
if (!convert)
|
||||
lt_info("%s: ERROR setting up SWS context\n", __func__);
|
||||
@@ -305,7 +313,7 @@ void cVideo::ShowPicture(const char *fname)
|
||||
SWFramebuffer *f = &buffers[buf_in];
|
||||
if (f->size() < need)
|
||||
f->resize(need);
|
||||
av_image_fill_arrays(rgbframe->data, rgbframe->linesize, &(*f)[0], AV_PIX_FMT_RGB32,
|
||||
av_image_fill_arrays(rgbframe->data, rgbframe->linesize, &(*f)[0], VDEC_PIXFMT,
|
||||
c->width, c->height, 1);
|
||||
sws_scale(convert, frame->data, frame->linesize, 0, c->height,
|
||||
rgbframe->data, rgbframe->linesize);
|
||||
@@ -361,6 +369,7 @@ void cVideo::Pig(int x, int y, int w, int h, int /*osd_w*/, int /*osd_h*/, int /
|
||||
pig_y = y;
|
||||
pig_w = w;
|
||||
pig_h = h;
|
||||
pig_changed = true;
|
||||
}
|
||||
|
||||
void cVideo::getPictureInfo(int &width, int &height, int &rate)
|
||||
@@ -538,10 +547,10 @@ void cVideo::run(void)
|
||||
lt_info("%s: WARN: pkt->size %d != len %d\n", __func__, avpkt.size, len);
|
||||
still_m.lock();
|
||||
if (got_frame && ! stillpicture) {
|
||||
unsigned int need = av_image_get_buffer_size(AV_PIX_FMT_RGB32, c->width, c->height, 1);
|
||||
unsigned int need = av_image_get_buffer_size(VDEC_PIXFMT, c->width, c->height, 1);
|
||||
convert = sws_getCachedContext(convert,
|
||||
c->width, c->height, c->pix_fmt,
|
||||
c->width, c->height, AV_PIX_FMT_RGB32,
|
||||
c->width, c->height, VDEC_PIXFMT,
|
||||
SWS_BICUBIC, 0, 0, 0);
|
||||
if (!convert)
|
||||
lt_info("%s: ERROR setting up SWS context\n", __func__);
|
||||
@@ -550,7 +559,7 @@ void cVideo::run(void)
|
||||
SWFramebuffer *f = &buffers[buf_in];
|
||||
if (f->size() < need)
|
||||
f->resize(need);
|
||||
av_image_fill_arrays(rgbframe->data, rgbframe->linesize, &(*f)[0], AV_PIX_FMT_RGB32,
|
||||
av_image_fill_arrays(rgbframe->data, rgbframe->linesize, &(*f)[0], VDEC_PIXFMT,
|
||||
c->width, c->height, 1);
|
||||
sws_scale(convert, frame->data, frame->linesize, 0, c->height,
|
||||
rgbframe->data, rgbframe->linesize);
|
||||
@@ -564,10 +573,18 @@ void cVideo::run(void)
|
||||
f->width(c->width);
|
||||
f->height(c->height);
|
||||
int64_t vpts = av_frame_get_best_effort_timestamp(frame);
|
||||
/* a/v delay determined experimentally :-) */
|
||||
#if USE_OPENGL
|
||||
if (v_format == VIDEO_FORMAT_MPEG2)
|
||||
vpts += 90000*4/10; /* 400ms */
|
||||
else
|
||||
vpts += 90000*3/10; /* 300ms */
|
||||
#endif
|
||||
#if USE_CLUTTER
|
||||
/* no idea why there's a difference between OpenGL and clutter rendering... */
|
||||
if (v_format == VIDEO_FORMAT_MPEG2)
|
||||
vpts += 90000*3/10; /* 300ms */
|
||||
#endif
|
||||
f->pts(vpts);
|
||||
AVRational a = av_guess_sample_aspect_ratio(avfc, avfc->streams[0], frame);
|
||||
f->AR(a);
|
||||
@@ -667,8 +684,8 @@ bool cVideo::GetScreenImage(unsigned char * &data, int &xres, int &yres, bool ge
|
||||
std::vector<unsigned char> *osd = NULL;
|
||||
std::vector<unsigned char> s_osd; /* scaled OSD */
|
||||
int vid_w = 0, vid_h = 0;
|
||||
int osd_w = glfb->getOSDWidth();
|
||||
int osd_h = glfb->getOSDHeight();
|
||||
int osd_w = glfb_priv->getOSDWidth();
|
||||
int osd_h = glfb_priv->getOSDHeight();
|
||||
xres = osd_w;
|
||||
yres = osd_h;
|
||||
if (get_video) {
|
||||
@@ -692,24 +709,26 @@ bool cVideo::GetScreenImage(unsigned char * &data, int &xres, int &yres, bool ge
|
||||
yres = osd_h;
|
||||
}
|
||||
if (get_osd)
|
||||
osd = glfb->getOSDBuffer();
|
||||
osd = glfb_priv->getOSDBuffer();
|
||||
unsigned int need = av_image_get_buffer_size(AV_PIX_FMT_RGB32, xres, yres, 1);
|
||||
data = (unsigned char *)realloc(data, need); /* will be freed by caller */
|
||||
if (data == NULL) /* out of memory? */
|
||||
return false;
|
||||
|
||||
if (get_video) {
|
||||
//memcpy dont work with copy BGR24 to RGB32
|
||||
#if USE_OPENGL //memcpy dont work with copy BGR24 to RGB32
|
||||
if (vid_w != xres || vid_h != yres){ /* scale video into data... */
|
||||
bool ret = swscale(&video[0], data, vid_w, vid_h, xres, yres, AV_PIX_FMT_RGB32);
|
||||
#endif
|
||||
bool ret = swscale(&video[0], data, vid_w, vid_h, xres, yres,VDEC_PIXFMT);
|
||||
if(!ret){
|
||||
free(data);
|
||||
return false;
|
||||
}
|
||||
//memcpy dont work with copy BGR24 to RGB32
|
||||
} else { /* get_video and no fancy scaling needed */
|
||||
#if USE_OPENGL //memcpy dont work with copy BGR24 to RGB32
|
||||
}else{ /* get_video and no fancy scaling needed */
|
||||
memcpy(data, &video[0], xres * yres * sizeof(uint32_t));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (get_osd && (osd_w != xres || osd_h != yres)) {
|
||||
|
@@ -1,8 +1,8 @@
|
||||
#ifndef _VIDEO_LIB_H
|
||||
#define _VIDEO_LIB_H
|
||||
|
||||
#include <thread_abstraction.h>
|
||||
#include <mutex_abstraction.h>
|
||||
#include <OpenThreads/Thread>
|
||||
#include <OpenThreads/Mutex>
|
||||
#include <vector>
|
||||
#include <linux/dvb/video.h>
|
||||
#include "cs_types.h"
|
||||
@@ -120,10 +120,10 @@ typedef enum
|
||||
} VIDEO_CONTROL;
|
||||
|
||||
|
||||
#define VDEC_MAXBUFS 0x30
|
||||
class cVideo : public Thread
|
||||
#define VDEC_MAXBUFS 0x40
|
||||
class cVideo : public OpenThreads::Thread
|
||||
{
|
||||
friend class GLFramebuffer;
|
||||
friend class GLFbPC;
|
||||
friend class cDemux;
|
||||
private:
|
||||
/* called from GL thread */
|
||||
@@ -211,8 +211,7 @@ class cVideo : public Thread
|
||||
bool thread_running;
|
||||
VIDEO_FORMAT v_format;
|
||||
VIDEO_STD v_std;
|
||||
//OpenThreads::Mutex buf_m;
|
||||
Mutex buf_m;
|
||||
OpenThreads::Mutex buf_m;
|
||||
DISPLAY_AR display_aspect;
|
||||
DISPLAY_AR_MODE display_crop;
|
||||
int output_h;
|
||||
@@ -221,7 +220,7 @@ class cVideo : public Thread
|
||||
int pig_w;
|
||||
int pig_h;
|
||||
bool pig_changed;
|
||||
Mutex still_m;
|
||||
OpenThreads::Mutex still_m;
|
||||
bool stillpicture;
|
||||
};
|
||||
|
||||
|
@@ -1,23 +0,0 @@
|
||||
#ifndef _CONDITION_ABSTRACTION_H
|
||||
#define _CONDITION_ABSTRACTION_H
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "mutex_abstraction.h"
|
||||
|
||||
class Condition
|
||||
{
|
||||
pthread_cond_t mCondition;
|
||||
|
||||
Condition(const Condition&);
|
||||
const Condition& operator=(const Condition&);
|
||||
|
||||
public:
|
||||
Condition();
|
||||
virtual ~Condition();
|
||||
virtual int wait(Mutex* const aMutex);
|
||||
virtual int broadcast();
|
||||
virtual int signal();
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,10 +1,42 @@
|
||||
#include <config.h>
|
||||
#if HAVE_GENERIC_HARDWARE
|
||||
#if BOXMODEL_RASPI
|
||||
#include "../raspi/glfb.h"
|
||||
#else
|
||||
#include "../generic-pc/glfb.h"
|
||||
#endif
|
||||
#else
|
||||
#error glfb.h only works with HAVE_GENERIC_HARDWARE defined
|
||||
/*
|
||||
Copyright 2010 Carsten Juttner <carjay@gmx.net>
|
||||
Copyright 2012,2013 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __glfb__
|
||||
#define __glfb__
|
||||
#include <OpenThreads/Thread>
|
||||
#include <vector>
|
||||
#include <linux/fb.h> /* for screeninfo etc. */
|
||||
|
||||
class GLFramebuffer : public OpenThreads::Thread
|
||||
{
|
||||
public:
|
||||
GLFramebuffer(int x, int y);
|
||||
~GLFramebuffer();
|
||||
std::vector<unsigned char> *getOSDBuffer() { return &osd_buf; } /* pointer to OSD bounce buffer */
|
||||
void blit();
|
||||
fb_var_screeninfo getScreenInfo() { return si; }
|
||||
|
||||
private:
|
||||
fb_var_screeninfo si;
|
||||
std::vector<unsigned char> osd_buf; /* silly bounce buffer */
|
||||
void run(); /* for OpenThreads::Thread */
|
||||
void setup();
|
||||
void blit_osd();
|
||||
void *pdata; /* not yet used */
|
||||
};
|
||||
#endif
|
||||
|
@@ -1,25 +0,0 @@
|
||||
#ifndef _MUTEX_ABSTRACTION_H
|
||||
#define _MUTEX_ABSTRACTION_H
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
class Mutex
|
||||
{
|
||||
friend class Condition;
|
||||
|
||||
pthread_mutex_t mMutex;
|
||||
|
||||
Mutex(const Mutex&);
|
||||
const Mutex& operator=(const Mutex&);
|
||||
|
||||
protected:
|
||||
explicit Mutex(int);
|
||||
|
||||
public:
|
||||
Mutex();
|
||||
virtual ~Mutex();
|
||||
virtual void lock();
|
||||
virtual void unlock();
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,16 +0,0 @@
|
||||
#ifndef _REENTRANT_MUTEX_H
|
||||
#define _REENTRANT_MUTEX_H
|
||||
|
||||
#include "mutex_abstraction.h"
|
||||
|
||||
class ReentrantMutex : public Mutex
|
||||
{
|
||||
ReentrantMutex(const ReentrantMutex&);
|
||||
const ReentrantMutex& operator=(const ReentrantMutex&);
|
||||
|
||||
public:
|
||||
ReentrantMutex();
|
||||
virtual ~ReentrantMutex();
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,18 +0,0 @@
|
||||
#ifndef _SCOPED_LOCK_H
|
||||
#define _SCOPED_LOCK_H
|
||||
|
||||
#include "mutex_abstraction.h"
|
||||
|
||||
class ScopedLock
|
||||
{
|
||||
Mutex& mMutex;
|
||||
|
||||
ScopedLock(const ScopedLock&);
|
||||
const ScopedLock& operator=(const ScopedLock&);
|
||||
|
||||
public:
|
||||
ScopedLock(Mutex&);
|
||||
~ScopedLock();
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,30 +0,0 @@
|
||||
#ifndef _THREAD_ABSTRACTION_H
|
||||
#define _THREAD_ABSTRACTION_H
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
class Thread
|
||||
{
|
||||
bool mIsRunning;
|
||||
pthread_t mThread;
|
||||
|
||||
static void* runThread(void*);
|
||||
Thread(const Thread&);
|
||||
const Thread& operator=(const Thread&);
|
||||
|
||||
public:
|
||||
Thread();
|
||||
virtual ~Thread();
|
||||
int startThread();
|
||||
int cancelThread();
|
||||
int detachThread();
|
||||
int joinThread();
|
||||
|
||||
int setCancelModeDisable();
|
||||
int setSchedulePriority(int);
|
||||
|
||||
protected:
|
||||
virtual void run() = 0;
|
||||
};
|
||||
|
||||
#endif
|
@@ -47,33 +47,42 @@ bool cPlayback::Open(playmode_t PlayMode)
|
||||
last_size = 0;
|
||||
nPlaybackSpeed = 0;
|
||||
init_jump = -1;
|
||||
|
||||
if (player)
|
||||
free(player);
|
||||
player = NULL;
|
||||
|
||||
player = (Context_t *) malloc(sizeof(Context_t));
|
||||
|
||||
if (player)
|
||||
{
|
||||
player->playback = &PlaybackHandler;
|
||||
player->output = &OutputHandler;
|
||||
player->container = &ContainerHandler;
|
||||
player->manager = &ManagerHandler;
|
||||
|
||||
lt_info("%s - player output name: %s PlayMode: %s\n", __func__, player->output->Name, aPLAYMODE[PlayMode]);
|
||||
}
|
||||
|
||||
//Registration of output devices
|
||||
if (player && player->output)
|
||||
{
|
||||
player->output->Command(player, OUTPUT_ADD, (void *)"audio");
|
||||
player->output->Command(player, OUTPUT_ADD, (void *)"video");
|
||||
player->output->Command(player, OUTPUT_ADD, (void *)"subtitle");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cPlayback::Close(void)
|
||||
{
|
||||
lt_info("%s\n", __func__);
|
||||
|
||||
//Dagobert: movieplayer does not call stop, it calls close ;)
|
||||
if(playing)
|
||||
Stop();
|
||||
|
||||
if (decoders_closed)
|
||||
{
|
||||
audioDecoder->openDevice();
|
||||
@@ -92,7 +101,9 @@ bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, in
|
||||
bool ret = false;
|
||||
bool isHTTP = false;
|
||||
no_probe = false;
|
||||
|
||||
lt_info("%s - filename=%s vpid=%u vtype=%d apid=%u ac3=%d\n", __func__, filename, vpid, vtype, apid, ac3);
|
||||
|
||||
init_jump = -1;
|
||||
//create playback path
|
||||
mAudioStream = 0;
|
||||
@@ -100,11 +111,14 @@ bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, in
|
||||
mTeletextStream = -1;
|
||||
unlink("/tmp/.id3coverart");
|
||||
std::string file;
|
||||
|
||||
if (*filename == '/')
|
||||
file = "file://";
|
||||
file += filename;
|
||||
|
||||
if ((file.find(":31339/id=") != std::string::npos) || (file.find(":10000") != std::string::npos) || (file.find(":8001/") != std::string::npos)) // for LocalTV and Entertain-TV streaming
|
||||
no_probe = true;
|
||||
|
||||
if (file.substr(0, 7) == "file://")
|
||||
{
|
||||
if (file.substr(file.length() - 3) == ".ts")
|
||||
@@ -117,6 +131,7 @@ 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 (player->playback->Command(player, PLAYBACK_OPEN, &playbackFiles) == 0)
|
||||
{
|
||||
@@ -140,15 +155,16 @@ bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, in
|
||||
{
|
||||
printf("AudioTrack List\n");
|
||||
int i = 0;
|
||||
for (i = 0; TrackList[i] != NULL; i+=2)
|
||||
for (i = 0; TrackList[i] != NULL; i += 2)
|
||||
{
|
||||
printf("\t%s - %s\n", TrackList[i], TrackList[i+1]);
|
||||
printf("\t%s - %s\n", TrackList[i], TrackList[i + 1]);
|
||||
free(TrackList[i]);
|
||||
free(TrackList[i+1]);
|
||||
free(TrackList[i + 1]);
|
||||
}
|
||||
free(TrackList);
|
||||
}
|
||||
}
|
||||
|
||||
//SUB
|
||||
if (player && player->manager && player->manager->subtitle)
|
||||
{
|
||||
@@ -160,13 +176,14 @@ bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, in
|
||||
int i = 0;
|
||||
for (i = 0; TrackList[i] != NULL; i+=2)
|
||||
{
|
||||
printf("\t%s - %s\n", TrackList[i], TrackList[i+1]);
|
||||
printf("\t%s - %s\n", TrackList[i], TrackList[i + 1]);
|
||||
free(TrackList[i]);
|
||||
free(TrackList[i+1]);
|
||||
free(TrackList[i + 1]);
|
||||
}
|
||||
free(TrackList);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
//Teletext
|
||||
if (player && player->manager && player->manager->teletext)
|
||||
@@ -177,15 +194,16 @@ bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, in
|
||||
{
|
||||
printf("TeletextTrack List\n");
|
||||
int i = 0;
|
||||
for (i = 0; TrackList[i] != NULL; i+=2)
|
||||
for (i = 0; TrackList[i] != NULL; i += 2)
|
||||
{
|
||||
printf("\t%s - %s\n", TrackList[i], TrackList[i+1]);
|
||||
printf("\t%s - %s\n", TrackList[i], TrackList[i + 1]);
|
||||
free(TrackList[i]);
|
||||
free(TrackList[i+1]);
|
||||
free(TrackList[i + 1]);
|
||||
}
|
||||
free(TrackList);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
//Chapters
|
||||
if (player && player->manager && player->manager->chapter)
|
||||
@@ -196,19 +214,21 @@ bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, in
|
||||
{
|
||||
printf("Chapter List\n");
|
||||
int i = 0;
|
||||
for (i = 0; TrackList[i] != NULL; i+=2)
|
||||
for (i = 0; TrackList[i] != NULL; i += 2)
|
||||
{
|
||||
printf("\t%s - %s\n", TrackList[i], TrackList[i+1]);
|
||||
printf("\t%s - %s\n", TrackList[i], TrackList[i + 1]);
|
||||
free(TrackList[i]);
|
||||
free(TrackList[i+1]);
|
||||
free(TrackList[i + 1]);
|
||||
}
|
||||
free(TrackList);
|
||||
}
|
||||
}
|
||||
|
||||
playing = true;
|
||||
first = true;
|
||||
player->output->Command(player, OUTPUT_OPEN, NULL);
|
||||
ret = (player->playback->Command(player, PLAYBACK_PLAY, NULL) == 0);
|
||||
|
||||
if (ret && !isHTTP)
|
||||
playing = ret = (player->playback->Command(player, PLAYBACK_PAUSE, NULL) == 0);
|
||||
}
|
||||
@@ -219,17 +239,23 @@ bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, in
|
||||
bool cPlayback::Stop(void)
|
||||
{
|
||||
lt_info("%s playing %d\n", __func__, playing);
|
||||
|
||||
if (player && player->playback)
|
||||
player->playback->Command(player, PLAYBACK_STOP, NULL);
|
||||
|
||||
if (player && player->output)
|
||||
player->output->Command(player, OUTPUT_CLOSE, NULL);
|
||||
|
||||
if (player && player->output)
|
||||
{
|
||||
player->output->Command(player, OUTPUT_DEL, (void *)"audio");
|
||||
player->output->Command(player, OUTPUT_DEL, (void *)"video");
|
||||
player->output->Command(player, OUTPUT_DEL, (void *)"subtitle");
|
||||
}
|
||||
|
||||
if (player && player->playback)
|
||||
player->playback->Command(player, PLAYBACK_CLOSE, NULL);
|
||||
|
||||
playing = false;
|
||||
return true;
|
||||
}
|
||||
@@ -238,6 +264,7 @@ bool cPlayback::SetAPid(int pid, bool /* ac3 */)
|
||||
{
|
||||
lt_info("%s\n", __func__);
|
||||
int i = pid;
|
||||
|
||||
if (pid != mAudioStream)
|
||||
{
|
||||
if (player && player->playback)
|
||||
@@ -257,6 +284,7 @@ bool cPlayback::SetSubtitlePid(int pid)
|
||||
{
|
||||
lt_info("%s\n", __func__);
|
||||
int i = pid;
|
||||
|
||||
if (pid != mSubtitleStream)
|
||||
{
|
||||
if (player && player->playback)
|
||||
@@ -269,11 +297,13 @@ bool cPlayback::SetSubtitlePid(int pid)
|
||||
bool cPlayback::SetTeletextPid(int pid)
|
||||
{
|
||||
lt_info("%s\n", __func__);
|
||||
|
||||
//int i = pid;
|
||||
|
||||
if (pid != mTeletextStream)
|
||||
{
|
||||
//if(player && player->playback)
|
||||
//player->playback->Command(player, PLAYBACK_SWITCH_TELETEXT, (void*)&i);
|
||||
//if (player && player->playback)
|
||||
// player->playback->Command(player, PLAYBACK_SWITCH_TELETEXT, (void*)&i);
|
||||
mTeletextStream = pid;
|
||||
}
|
||||
return true;
|
||||
@@ -282,6 +312,7 @@ bool cPlayback::SetTeletextPid(int pid)
|
||||
bool cPlayback::SetSpeed(int speed)
|
||||
{
|
||||
lt_info("%s playing %d speed %d\n", __func__, playing, speed);
|
||||
|
||||
if (!decoders_closed)
|
||||
{
|
||||
audioDecoder->closeDevice();
|
||||
@@ -295,12 +326,15 @@ bool cPlayback::SetSpeed(int speed)
|
||||
playing = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!playing)
|
||||
return false;
|
||||
|
||||
if (player && player->playback)
|
||||
{
|
||||
int result = 0;
|
||||
nPlaybackSpeed = speed;
|
||||
|
||||
if (speed > 1)
|
||||
{
|
||||
/* direction switch ? */
|
||||
@@ -337,11 +371,13 @@ bool cPlayback::SetSpeed(int speed)
|
||||
{
|
||||
result = player->playback->Command(player, PLAYBACK_CONTINUE, NULL);
|
||||
}
|
||||
|
||||
if (init_jump > -1)
|
||||
{
|
||||
SetPosition(init_jump);
|
||||
init_jump = -1;
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
printf("returning false\n");
|
||||
@@ -369,6 +405,7 @@ bool cPlayback::GetPosition(int &position, int &duration)
|
||||
{
|
||||
bool got_duration = false;
|
||||
lt_debug("%s %d %d\n", __func__, position, duration);
|
||||
|
||||
/* hack: if the file is growing (timeshift), then determine its length
|
||||
* by comparing the mtime with the mtime of the xml file */
|
||||
if (pm == PLAYMODE_TS)
|
||||
@@ -390,17 +427,21 @@ bool cPlayback::GetPosition(int &position, int &duration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!playing)
|
||||
return false;
|
||||
|
||||
if (player && player->playback && !player->playback->isPlaying)
|
||||
{
|
||||
lt_info("%s !!!!EOF!!!! < -1\n", __func__);
|
||||
position = duration + 1000;
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t vpts = 0;
|
||||
if (player && player->playback)
|
||||
player->playback->Command(player, PLAYBACK_PTS, &vpts);
|
||||
|
||||
if (vpts <= 0)
|
||||
{
|
||||
//printf("ERROR: vpts==0");
|
||||
@@ -410,21 +451,31 @@ bool cPlayback::GetPosition(int &position, int &duration)
|
||||
/* len is in nanoseconds. we have 90 000 pts per second. */
|
||||
position = vpts / 90;
|
||||
}
|
||||
|
||||
if (got_duration)
|
||||
return true;
|
||||
|
||||
int64_t length = 0;
|
||||
|
||||
if (player && player->playback)
|
||||
player->playback->Command(player, PLAYBACK_LENGTH, &length);
|
||||
|
||||
if (length <= 0)
|
||||
{
|
||||
duration = duration + 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
duration = length * 1000;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cPlayback::SetPosition(int position, bool absolute)
|
||||
{
|
||||
lt_info("%s %d\n", __func__, position);
|
||||
|
||||
if (playing && first)
|
||||
{
|
||||
/* the calling sequence is:
|
||||
@@ -437,9 +488,12 @@ bool cPlayback::SetPosition(int position, bool absolute)
|
||||
first = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t pos = (position / 1000.0);
|
||||
|
||||
if (player && player->playback)
|
||||
player->playback->Command(player, absolute ? PLAYBACK_SEEK_ABS : PLAYBACK_SEEK, (void *)&pos);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -448,6 +502,7 @@ void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *nu
|
||||
lt_info("%s\n", __func__);
|
||||
int max_numpida = *numpida;
|
||||
*numpida = 0;
|
||||
|
||||
if (player && player->manager && player->manager->audio)
|
||||
{
|
||||
char **TrackList = NULL;
|
||||
@@ -467,9 +522,9 @@ void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *nu
|
||||
{
|
||||
apids[j] = _pid;
|
||||
// atUnknown, atMPEG, atMP3, atAC3, atDTS, atAAC, atPCM, atOGG, atFLAC
|
||||
if (!strncmp("A_MPEG/L3", TrackList[i + 1], 9))
|
||||
if (!strncmp("A_MPEG/L3", TrackList[i + 1], 9))
|
||||
ac3flags[j] = 3;
|
||||
if (!strncmp("A_MP3", TrackList[i + 1], 5))
|
||||
if (!strncmp("A_MP3", TrackList[i + 1], 5))
|
||||
ac3flags[j] = 4;
|
||||
else if (!strncmp("A_AC3", TrackList[i + 1], 5))
|
||||
ac3flags[j] = 1;
|
||||
@@ -502,8 +557,10 @@ void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *nu
|
||||
void cPlayback::FindAllSubtitlePids(int *pids, unsigned int *numpids, std::string *language)
|
||||
{
|
||||
lt_info("%s\n", __func__);
|
||||
|
||||
int max_numpids = *numpids;
|
||||
*numpids = 0;
|
||||
|
||||
if (player && player->manager && player->manager->subtitle)
|
||||
{
|
||||
char **TrackList = NULL;
|
||||
@@ -539,8 +596,8 @@ void cPlayback::FindAllTeletextsubtitlePids(int */*pids*/, unsigned int *numpids
|
||||
lt_info("%s\n", __func__);
|
||||
//int max_numpids = *numpids;
|
||||
*numpids = 0;
|
||||
/*
|
||||
if (player && player->manager && player->manager->teletext)
|
||||
|
||||
/* if (player && player->manager && player->manager->teletext)
|
||||
{
|
||||
char **TrackList = NULL;
|
||||
player->manager->teletext->Command(player, MANAGER_LIST, &TrackList);
|
||||
@@ -569,16 +626,15 @@ void cPlayback::FindAllTeletextsubtitlePids(int */*pids*/, unsigned int *numpids
|
||||
free(TrackList);
|
||||
*numpids = j;
|
||||
}
|
||||
}
|
||||
*/
|
||||
} */
|
||||
}
|
||||
|
||||
int cPlayback::GetTeletextPid(void)
|
||||
{
|
||||
lt_info("%s\n", __func__);
|
||||
int pid = -1;
|
||||
/*
|
||||
if (player && player->manager && player->manager->teletext)
|
||||
|
||||
/* if (player && player->manager && player->manager->teletext)
|
||||
{
|
||||
char **TrackList = NULL;
|
||||
player->manager->teletext->Command(player, MANAGER_LIST, &TrackList);
|
||||
@@ -602,8 +658,8 @@ int cPlayback::GetTeletextPid(void)
|
||||
}
|
||||
free(TrackList);
|
||||
}
|
||||
}
|
||||
*/
|
||||
} */
|
||||
|
||||
printf("teletext pid id %d (0x%x)\n", pid, pid);
|
||||
return pid;
|
||||
}
|
||||
@@ -625,6 +681,7 @@ void cPlayback::GetChapters(std::vector<int> &positions, std::vector<std::string
|
||||
{
|
||||
positions.clear();
|
||||
titles.clear();
|
||||
|
||||
if (player && player->manager && player->manager->chapter)
|
||||
{
|
||||
char **TrackList = NULL;
|
||||
@@ -681,6 +738,7 @@ cPlayback::cPlayback(int num __attribute__((unused)))
|
||||
cPlayback::~cPlayback()
|
||||
{
|
||||
lt_info("%s\n", __func__);
|
||||
|
||||
if (player)
|
||||
free(player);
|
||||
player = NULL;
|
||||
@@ -727,6 +785,7 @@ void cPlayback::ReleaseAVFormatContext()
|
||||
bool cPlayback::IsPlaying(void) const
|
||||
{
|
||||
lt_info("%s\n", __func__);
|
||||
|
||||
/* konfetti: there is no event/callback mechanism in libeplayer2
|
||||
* so in case of ending playback we have no information on a
|
||||
* terminated stream currently (or did I oversee it?).
|
||||
@@ -736,6 +795,7 @@ bool cPlayback::IsPlaying(void) const
|
||||
{
|
||||
return player->playback->isPlaying;
|
||||
}
|
||||
|
||||
return playing;
|
||||
}
|
||||
#endif
|
||||
|
@@ -1,30 +1,45 @@
|
||||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
AM_CFLAGS = -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
|
||||
|
||||
CXXFLAGS = -Wall
|
||||
|
||||
noinst_LTLIBRARIES = libeplayer3_arm.la
|
||||
|
||||
AM_CFLAGS = -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
|
||||
AM_CPPFLAGS = -I$(srcdir)/include
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS += -I$(srcdir)/external
|
||||
|
||||
AM_CPPFLAGS = -I$(srcdir)/include
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS += -I$(srcdir)/external
|
||||
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
|
||||
|
||||
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
|
||||
SOURCE_FILES = container/container.c
|
||||
SOURCE_FILES += container/container_ffmpeg.c
|
||||
SOURCE_FILES += manager/manager.c
|
||||
SOURCE_FILES += manager/audio.c
|
||||
SOURCE_FILES += manager/video.c
|
||||
SOURCE_FILES += manager/chapter.c
|
||||
SOURCE_FILES += manager/subtitle.c
|
||||
SOURCE_FILES += output/output_subtitle.c
|
||||
SOURCE_FILES += output/output.c
|
||||
SOURCE_FILES += output/writer/common/pes.c
|
||||
SOURCE_FILES += output/writer/common/misc.c
|
||||
SOURCE_FILES += output/writer/common/writer.c
|
||||
SOURCE_FILES += output/linuxdvb_buffering.c
|
||||
SOURCE_FILES += playback/playback.c
|
||||
SOURCE_FILES += external/ffmpeg/src/bitstream.c
|
||||
SOURCE_FILES += external/ffmpeg/src/latmenc.c
|
||||
SOURCE_FILES += external/ffmpeg/src/mpeg4audio.c
|
||||
|
||||
libeplayer3_arm_la_SOURCES = \
|
||||
container/container.c \
|
||||
container/container_ffmpeg.c \
|
||||
manager/manager.c \
|
||||
manager/audio.c \
|
||||
manager/video.c \
|
||||
manager/subtitle.c \
|
||||
manager/chapter.c \
|
||||
if ENABLE_FLV2MPEG4
|
||||
AM_CFLAGS += -DHAVE_FLV2MPEG4_CONVERTER
|
||||
AM_CPPFLAGS += -I$(srcdir)/external/flv2mpeg4
|
||||
SOURCE_FILES += external/flv2mpeg4/src/m4vencode.c
|
||||
SOURCE_FILES += external/flv2mpeg4/src/flvdecoder.c
|
||||
SOURCE_FILES += external/flv2mpeg4/src/dcprediction.c
|
||||
SOURCE_FILES += external/flv2mpeg4/src/flv2mpeg4.c
|
||||
endif
|
||||
|
||||
SOURCE_FILES += \
|
||||
output/linuxdvb_mipsel.c \
|
||||
output/linuxdvb_buffering.c \
|
||||
output/output_subtitle.c \
|
||||
output/output.c \
|
||||
output/writer/common/pes.c \
|
||||
output/writer/common/misc.c \
|
||||
output/writer/common/writer.c \
|
||||
output/writer/mipsel/writer.c \
|
||||
output/writer/mipsel/aac.c \
|
||||
output/writer/mipsel/ac3.c \
|
||||
@@ -42,15 +57,13 @@ libeplayer3_arm_la_SOURCES = \
|
||||
output/writer/mipsel/divx3.c \
|
||||
output/writer/mipsel/vp.c \
|
||||
output/writer/mipsel/wmv.c \
|
||||
output/writer/mipsel/vc1.c \
|
||||
playback/playback.c \
|
||||
external/ffmpeg/src/bitstream.c \
|
||||
external/ffmpeg/src/latmenc.c \
|
||||
external/ffmpeg/src/mpeg4audio.c
|
||||
output/writer/mipsel/vc1.c
|
||||
|
||||
libeplayer3_arm_la_SOURCES = $(SOURCE_FILES)
|
||||
|
||||
LIBEPLAYER3_LIBS = libeplayer3_arm.la -lpthread -lavformat -lavcodec -lavutil -lswresample -lz -lm
|
||||
LIBEPLAYER3_LIBS = libeplayer3_arm.la -lpthread -lavformat -lavcodec -lavutil -lswresample
|
||||
|
||||
bin_PROGRAMS = eplayer3
|
||||
eplayer3_SOURCES = main/exteplayer.c
|
||||
eplayer3_LDADD = $(LIBEPLAYER3_LIBS)
|
||||
eplayer3_DEPENDENCIES = libeplayer3_arm.la
|
||||
|
@@ -80,13 +80,13 @@
|
||||
static short debug_level = 1;
|
||||
|
||||
#define ffmpeg_printf(level, fmt, x...) do { \
|
||||
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
|
||||
if (debug_level >= level) printf("[%s::%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
|
||||
#else
|
||||
#define ffmpeg_printf(level, fmt, x...)
|
||||
#endif
|
||||
|
||||
#ifndef FFMPEG_SILENT
|
||||
#define ffmpeg_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
|
||||
#define ffmpeg_err(fmt, x...) do { printf("[%s::%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
|
||||
#else
|
||||
#define ffmpeg_err(fmt, x...)
|
||||
#endif
|
||||
@@ -105,6 +105,7 @@ if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x);
|
||||
#define cERR_CONTAINER_FFMPEG_END_OF_FILE -10
|
||||
|
||||
#define IPTV_AV_CONTEXT_MAX_NUM 2
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
@@ -548,8 +549,7 @@ static void FFMPEGThread(Context_t *context)
|
||||
threadname[16] = 0;
|
||||
prctl(PR_SET_NAME, (unsigned long)&threadname);
|
||||
AVPacket packet;
|
||||
//off_t lastSeek = -1;
|
||||
//int64_t lastPts = -1;
|
||||
|
||||
int64_t currentVideoPts = -1;
|
||||
int64_t currentAudioPts = -1;
|
||||
|
||||
@@ -561,7 +561,6 @@ static void FFMPEGThread(Context_t *context)
|
||||
|
||||
int64_t showtime = 0;
|
||||
int64_t bofcount = 0;
|
||||
//int32_t err = 0;
|
||||
AudioVideoOut_t avOut;
|
||||
|
||||
g_context = context;
|
||||
@@ -583,13 +582,14 @@ static void FFMPEGThread(Context_t *context)
|
||||
memset(&flv2mpeg4_context, 0, sizeof(Flv2Mpeg4Context));
|
||||
#endif
|
||||
ffmpeg_printf(10, "\n");
|
||||
|
||||
while (context->playback->isCreationPhase)
|
||||
{
|
||||
ffmpeg_printf(10, "Thread waiting for end of init phase...\n");
|
||||
usleep(1000);
|
||||
}
|
||||
ffmpeg_printf(10, "Running!\n");
|
||||
|
||||
|
||||
#ifdef __sh__
|
||||
uint32_t bufferSize = 0;
|
||||
context->output->Command(context, OUTPUT_GET_BUFFER_SIZE, &bufferSize);
|
||||
@@ -597,6 +597,7 @@ static void FFMPEGThread(Context_t *context)
|
||||
#endif
|
||||
|
||||
int8_t isWaitingForFinish = 0;
|
||||
|
||||
while (context && context->playback && context->playback->isPlaying)
|
||||
{
|
||||
/* When user press PAUSE we call pause on AUDIO and VIDEO decoders,
|
||||
@@ -636,19 +637,24 @@ static void FFMPEGThread(Context_t *context)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (context->playback->BackWard && av_gettime() >= showtime) {
|
||||
|
||||
if (context->playback->BackWard && av_gettime() >= showtime)
|
||||
{
|
||||
context->output->Command(context, OUTPUT_CLEAR, "video");
|
||||
|
||||
if (bofcount == 1) {
|
||||
showtime = av_gettime();
|
||||
usleep(100000);
|
||||
continue;
|
||||
if (bofcount == 1)
|
||||
{
|
||||
showtime = av_gettime();
|
||||
usleep(100000);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (avContextTab[0]->iformat->flags & AVFMT_TS_DISCONT) {
|
||||
if (avContextTab[0]->iformat->flags & AVFMT_TS_DISCONT)
|
||||
{
|
||||
off_t pos = avio_tell(avContextTab[0]->pb);
|
||||
|
||||
if (pos > 0) {
|
||||
if (pos > 0)
|
||||
{
|
||||
float br;
|
||||
if (avContextTab[0]->bit_rate)
|
||||
br = avContextTab[0]->bit_rate / 8.0;
|
||||
@@ -669,7 +675,7 @@ static void FFMPEGThread(Context_t *context)
|
||||
seek_target_seconds = AV_TIME_BASE;
|
||||
do_seek_target_seconds = 1;
|
||||
}
|
||||
showtime = av_gettime() + 300000; //jump back every 300ms
|
||||
showtime = av_gettime() + 300000; //jump back every 300ms
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -770,15 +776,16 @@ static void FFMPEGThread(Context_t *context)
|
||||
|
||||
if (!isWaitingForFinish && (ffmpegStatus = av_read_frame(avContextTab[cAVIdx], &packet)) == 0)
|
||||
{
|
||||
int64_t pts = 0;
|
||||
int64_t dts = 0;
|
||||
Track_t *videoTrack = NULL;
|
||||
Track_t *audioTrack = NULL;
|
||||
int64_t pts = 0;
|
||||
int64_t dts = 0;
|
||||
Track_t *videoTrack = NULL;
|
||||
Track_t *audioTrack = NULL;
|
||||
Track_t *subtitleTrack = NULL;
|
||||
|
||||
int32_t pid = avContextTab[cAVIdx]->streams[packet.stream_index]->id;
|
||||
|
||||
reset_finish_timeout();
|
||||
|
||||
if (avContextTab[cAVIdx]->streams[packet.stream_index]->discard != AVDISCARD_ALL)
|
||||
{
|
||||
if (context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack) < 0)
|
||||
@@ -992,6 +999,7 @@ static void FFMPEGThread(Context_t *context)
|
||||
decoded_frame = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR > 57) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR > 32))
|
||||
while (packet.size > 0 || (!packet.size && !packet.data))
|
||||
#else
|
||||
@@ -1059,6 +1067,7 @@ static void FFMPEGThread(Context_t *context)
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t e = 0;
|
||||
if (!swr)
|
||||
{
|
||||
@@ -1085,6 +1094,7 @@ static void FFMPEGThread(Context_t *context)
|
||||
{
|
||||
c->channel_layout = av_get_default_channel_layout(c->channels);
|
||||
}
|
||||
|
||||
out_channel_layout = c->channel_layout;
|
||||
|
||||
uint8_t downmix = stereo_software_decoder && out_channels > 2 ? 1 : 0;
|
||||
@@ -1108,7 +1118,6 @@ static void FFMPEGThread(Context_t *context)
|
||||
av_opt_set_int(swr, "in_sample_fmt", c->sample_fmt, 0);
|
||||
av_opt_set_int(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
|
||||
|
||||
|
||||
e = swr_init(swr);
|
||||
if (e < 0)
|
||||
{
|
||||
@@ -1346,6 +1355,7 @@ static void FFMPEGThread(Context_t *context)
|
||||
seek_target_seconds = 0;
|
||||
do_seek_target_seconds = 0;
|
||||
PlaybackDieNow(1);
|
||||
|
||||
ffmpeg_printf(10, "terminating\n");
|
||||
}
|
||||
|
||||
@@ -1888,13 +1898,16 @@ int32_t container_ffmpeg_init(Context_t *context, PlayFiles_t *playFilesNames)
|
||||
}
|
||||
|
||||
ffmpeg_printf(10, "filename %s\n", playFilesNames->szFirstFile);
|
||||
|
||||
if (playFilesNames->szSecondFile)
|
||||
{
|
||||
ffmpeg_printf(10, "second filename %s\n", playFilesNames->szSecondFile);
|
||||
}
|
||||
|
||||
/* initialize ffmpeg */
|
||||
avcodec_register_all();
|
||||
av_register_all();
|
||||
|
||||
avformat_network_init();
|
||||
|
||||
// SULGE DEBUG ENABLED
|
||||
@@ -1904,7 +1917,8 @@ int32_t container_ffmpeg_init(Context_t *context, PlayFiles_t *playFilesNames)
|
||||
|
||||
context->playback->abortRequested = 0;
|
||||
int32_t res = container_ffmpeg_init_av_context(context, playFilesNames->szFirstFile, playFilesNames->iFirstFileSize, \
|
||||
playFilesNames->szFirstMoovAtomFile, playFilesNames->iFirstMoovAtomOffset, 0);
|
||||
playFilesNames->szFirstMoovAtomFile, playFilesNames->iFirstMoovAtomOffset, 0);
|
||||
|
||||
if (0 != res)
|
||||
{
|
||||
return res;
|
||||
@@ -1913,7 +1927,7 @@ int32_t container_ffmpeg_init(Context_t *context, PlayFiles_t *playFilesNames)
|
||||
if (playFilesNames->szSecondFile && playFilesNames->szSecondFile[0] != '\0')
|
||||
{
|
||||
res = container_ffmpeg_init_av_context(context, playFilesNames->szSecondFile, playFilesNames->iSecondFileSize, \
|
||||
playFilesNames->szSecondMoovAtomFile, playFilesNames->iSecondMoovAtomOffset, 1);
|
||||
playFilesNames->szSecondMoovAtomFile, playFilesNames->iSecondMoovAtomOffset, 1);
|
||||
}
|
||||
|
||||
if (0 != res)
|
||||
@@ -1972,6 +1986,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32
|
||||
|
||||
|
||||
uint32_t cAVIdx = 0;
|
||||
|
||||
for (cAVIdx = 0; cAVIdx < IPTV_AV_CONTEXT_MAX_NUM; cAVIdx += 1)
|
||||
{
|
||||
if (NULL == avContextTab[cAVIdx])
|
||||
@@ -2082,6 +2097,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32
|
||||
case AVMEDIA_TYPE_VIDEO:
|
||||
ffmpeg_printf(10, "CODEC_TYPE_VIDEO %d\n", get_codecpar(stream)->codec_type);
|
||||
stream->discard = AVDISCARD_ALL; /* by default we discard all video streams */
|
||||
|
||||
if (encoding != NULL)
|
||||
{
|
||||
track.type = eTypeES;
|
||||
@@ -2098,6 +2114,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32
|
||||
*/
|
||||
track.aspect_ratio_num = stream->sample_aspect_ratio.num;
|
||||
track.aspect_ratio_den = stream->sample_aspect_ratio.den;
|
||||
|
||||
if (0 == track.aspect_ratio_num || 0 == track.aspect_ratio_den)
|
||||
{
|
||||
track.aspect_ratio_num = get_codecpar(stream)->sample_aspect_ratio.num;
|
||||
@@ -2117,6 +2134,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32
|
||||
}
|
||||
|
||||
/* fixme: revise this */
|
||||
|
||||
if (track.frame_rate < 23970)
|
||||
{
|
||||
track.TimeScale = 1001;
|
||||
@@ -2181,6 +2199,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
ffmpeg_printf(10, "CODEC_TYPE_AUDIO %d\n", get_codecpar(stream)->codec_type);
|
||||
stream->discard = AVDISCARD_ALL;
|
||||
|
||||
if (encoding != NULL)
|
||||
{
|
||||
AVDictionaryEntry *lang;
|
||||
@@ -2199,6 +2218,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32
|
||||
track.have_aacheader = -1;
|
||||
|
||||
track.duration = (int64_t)av_rescale(stream->duration, (int64_t)stream->time_base.num * 1000, stream->time_base.den);
|
||||
|
||||
if (stream->duration == AV_NOPTS_VALUE)
|
||||
{
|
||||
ffmpeg_printf(10, "Stream has no duration so we take the duration from context\n");
|
||||
@@ -2516,7 +2536,9 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32
|
||||
ffmpeg_printf(10, "CODEC_TYPE_SUBTITLE %d\n", get_codecpar(stream)->codec_type);
|
||||
|
||||
lang = av_dict_get(stream->metadata, "language", NULL, 0);
|
||||
|
||||
track.Name = lang ? lang->value : "und";
|
||||
|
||||
ffmpeg_printf(10, "Language %s\n", track.Name);
|
||||
|
||||
track.Encoding = encoding;
|
||||
@@ -2597,6 +2619,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32
|
||||
}
|
||||
|
||||
releaseMutex(__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
return cERR_CONTAINER_FFMPEG_NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -2625,14 +2648,12 @@ static int32_t container_ffmpeg_play(Context_t *context)
|
||||
if ((error = pthread_create(&PlayThread, &attr, (void *)&FFMPEGThread, context)) != 0)
|
||||
{
|
||||
ffmpeg_printf(10, "Error creating thread, error:%d:%s\n", error, strerror(error));
|
||||
|
||||
hasPlayThreadStarted = 0;
|
||||
ret = cERR_CONTAINER_FFMPEG_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
ffmpeg_printf(10, "Created thread\n");
|
||||
|
||||
hasPlayThreadStarted = 1;
|
||||
}
|
||||
}
|
||||
@@ -2643,6 +2664,7 @@ static int32_t container_ffmpeg_play(Context_t *context)
|
||||
}
|
||||
|
||||
ffmpeg_printf(10, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2672,6 +2694,7 @@ static int32_t container_ffmpeg_stop(Context_t *context)
|
||||
{
|
||||
/* force close */
|
||||
ffmpeg_err("Timeout waiting for thread!\n");
|
||||
|
||||
ret = cERR_CONTAINER_FFMPEG_ERR;
|
||||
/* to speed up close - we are in separate process for the moment this process will
|
||||
* be closed and whole resources will be free by the system
|
||||
@@ -2923,15 +2946,16 @@ static int32_t container_ffmpeg_seek(Context_t *context, int64_t sec, uint8_t ab
|
||||
}
|
||||
|
||||
ffmpeg_printf(10, "iformat->flags 0x%08x\n", avContextTab[0]->iformat->flags);
|
||||
|
||||
#if defined(TS_BYTES_SEEKING) && TS_BYTES_SEEKING
|
||||
if (avContextTab[0]->iformat->flags & AVFMT_TS_DISCONT)
|
||||
{
|
||||
/* konfetti: for ts streams seeking frame per seconds does not work (why?).
|
||||
* I take this algo partly from ffplay.c.
|
||||
*
|
||||
* seeking per HTTP does still not work very good. forward seeks everytime
|
||||
* about 10 seconds, backward does not work.
|
||||
*/
|
||||
* I take this algo partly from ffplay.c.
|
||||
*
|
||||
* seeking per HTTP does still not work very good. forward seeks everytime
|
||||
* about 10 seconds, backward does not work.
|
||||
*/
|
||||
|
||||
getMutex(__FILE__, __FUNCTION__, __LINE__);
|
||||
off_t pos = avio_tell(avContextTab[0]->pb);
|
||||
@@ -3029,6 +3053,7 @@ static int32_t container_ffmpeg_switch_audio(Context_t *context, int32_t *arg __
|
||||
{
|
||||
ffmpeg_printf(10, "track %d\n", *arg);
|
||||
getMutex(__FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
if (context->manager->audio)
|
||||
{
|
||||
Track_t *Tracks = NULL;
|
||||
@@ -3129,7 +3154,7 @@ static int32_t container_ffmpeg_get_info(Context_t *context, char **infoString)
|
||||
return cERR_CONTAINER_FFMPEG_NO_ERROR;
|
||||
}
|
||||
|
||||
static int container_ffmpeg_get_metadata(Context_t * context, char ***p)
|
||||
static int container_ffmpeg_get_metadata(Context_t *context, char ***p)
|
||||
{
|
||||
Track_t *videoTrack = NULL;
|
||||
Track_t *audioTrack = NULL;
|
||||
@@ -3251,12 +3276,12 @@ static int32_t Command(Context_t *context, ContainerCmd_t command, void *argumen
|
||||
}
|
||||
case CONTAINER_SWITCH_AUDIO:
|
||||
{
|
||||
ret = container_ffmpeg_switch_audio(context, (int32_t *) argument);
|
||||
ret = container_ffmpeg_switch_audio(context, (int32_t *)argument);
|
||||
break;
|
||||
}
|
||||
case CONTAINER_SWITCH_SUBTITLE:
|
||||
{
|
||||
ret = container_ffmpeg_switch_subtitle(context, (int32_t *) argument);
|
||||
ret = container_ffmpeg_switch_subtitle(context, (int32_t *)argument);
|
||||
break;
|
||||
}
|
||||
case CONTAINER_INFO:
|
||||
@@ -3288,7 +3313,7 @@ static int32_t Command(Context_t *context, ContainerCmd_t command, void *argumen
|
||||
}
|
||||
case CONTAINER_GET_METADATA:
|
||||
{
|
||||
ret = container_ffmpeg_get_metadata(context, (char ***) argument);
|
||||
ret = container_ffmpeg_get_metadata(context, (char ***)argument);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -3298,6 +3323,7 @@ static int32_t Command(Context_t *context, ContainerCmd_t command, void *argumen
|
||||
}
|
||||
|
||||
ffmpeg_printf(50, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@@ -45,7 +45,6 @@ typedef struct ContainerHandler_s
|
||||
{
|
||||
char *Name;
|
||||
Container_t *selectedContainer;
|
||||
|
||||
int (* Command)(Context_t *, ContainerCmd_t, void *);
|
||||
} ContainerHandler_t;
|
||||
|
||||
|
@@ -44,7 +44,7 @@ typedef struct Track_s
|
||||
/* new field for ffmpeg - add at the end so no problem
|
||||
* can occur with not changed srt saa container
|
||||
*/
|
||||
char *language;
|
||||
char *language;
|
||||
|
||||
/* length of track */
|
||||
int64_t duration;
|
||||
|
@@ -4,7 +4,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef void( * PlaybackDieNowCallback )();
|
||||
typedef void(* PlaybackDieNowCallback)();
|
||||
bool PlaybackDieNowRegisterCallback(PlaybackDieNowCallback callback);
|
||||
|
||||
typedef enum {
|
||||
|
@@ -252,11 +252,12 @@ static int HandleTracks(const Manager_t *ptrManager, const PlaybackCmd_t playbac
|
||||
ptrManager->Command(g_player, MANAGER_LIST, &TrackList);
|
||||
if (NULL != TrackList)
|
||||
{
|
||||
int i = 0, Id = -1;
|
||||
int i = 0;
|
||||
int Id = -1;
|
||||
char * pch;
|
||||
char Name[] = " ";
|
||||
fprintf(stderr, "{\"%c_%c\": [", argvBuff[0], argvBuff[1]);
|
||||
for (i = 0; TrackList[i] != NULL; i+=2)
|
||||
for (i = 0; TrackList[i] != NULL; i += 2)
|
||||
{
|
||||
pch = strtok(TrackList[i], " ");
|
||||
if (pch != NULL) {
|
||||
@@ -272,7 +273,7 @@ static int HandleTracks(const Manager_t *ptrManager, const PlaybackCmd_t playbac
|
||||
}
|
||||
fprintf(stderr, "{\"id\":%d,\"e\":\"%s\",\"n\":\"%s\"}", Id, TrackList[i+1], Name);
|
||||
free(TrackList[i]);
|
||||
free(TrackList[i+1]);
|
||||
free(TrackList[i + 1]);
|
||||
}
|
||||
fprintf(stderr, "]}\n");
|
||||
free(TrackList);
|
||||
@@ -297,7 +298,7 @@ static int HandleTracks(const Manager_t *ptrManager, const PlaybackCmd_t playbac
|
||||
else // video
|
||||
{
|
||||
fprintf(stderr, "{\"%c_%c\":{\"id\":%d,\"e\":\"%s\",\"n\":\"%s\",\"w\":%d,\"h\":%d,\"f\":%u,\"p\":%d,\"an\":%d,\"ad\":%d}}\n", \
|
||||
argvBuff[0], argvBuff[1], track->Id, track->Encoding, track->Name, track->width, track->height, track->frame_rate, track->progressive, track->aspect_ratio_num, track->aspect_ratio_den);
|
||||
argvBuff[0], argvBuff[1], track->Id, track->Encoding, track->Name, track->width, track->height, track->frame_rate, track->progressive, track->aspect_ratio_num, track->aspect_ratio_den);
|
||||
}
|
||||
free(track->Encoding);
|
||||
free(track->Name);
|
||||
@@ -336,7 +337,7 @@ static int HandleTracks(const Manager_t *ptrManager, const PlaybackCmd_t playbac
|
||||
{
|
||||
int i = 0;
|
||||
char * pch;
|
||||
for (i = 0; TrackList[i] != NULL; i+=2)
|
||||
for (i = 0; TrackList[i] != NULL; i += 2)
|
||||
{
|
||||
if (idx == i)
|
||||
{
|
||||
@@ -345,7 +346,7 @@ static int HandleTracks(const Manager_t *ptrManager, const PlaybackCmd_t playbac
|
||||
id = atoi(pch);
|
||||
}
|
||||
free(TrackList[i]);
|
||||
free(TrackList[i+1]);
|
||||
free(TrackList[i + 1]);
|
||||
}
|
||||
free(TrackList);
|
||||
}
|
||||
@@ -501,7 +502,7 @@ static int HandleTracks(const Manager_t *ptrManager, const PlaybackCmd_t playbac
|
||||
|
||||
static void UpdateVideoTrack()
|
||||
{
|
||||
HandleTracks(g_player->manager->video, (PlaybackCmd_t) - 1, "vc");
|
||||
HandleTracks(g_player->manager->video, (PlaybackCmd_t) -1, "vc");
|
||||
}
|
||||
|
||||
static int ParseParams(int argc, char *argv[], PlayFiles_t *playbackFiles, int *pAudioTrackIdx, int *subtitleTrackIdx, uint32_t *linuxDvbBufferSizeMB)
|
||||
@@ -657,6 +658,7 @@ static int ParseParams(int argc, char *argv[], PlayFiles_t *playbackFiles, int *
|
||||
ret = 0;
|
||||
playbackFiles->szFirstFile = malloc(IPTV_MAX_FILE_PATH);
|
||||
playbackFiles->szFirstFile[0] = '\0';
|
||||
|
||||
if (NULL == strstr(argv[optind], "://"))
|
||||
{
|
||||
strcpy(playbackFiles->szFirstFile, "file://");
|
||||
@@ -693,6 +695,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
PlayFiles_t playbackFiles;
|
||||
memset(&playbackFiles, 0x00, sizeof(playbackFiles));
|
||||
|
||||
if (0 != ParseParams(argc, argv, &playbackFiles, &audioTrackIdx, &subtitleTrackIdx, &linuxDvbBufferSizeMB))
|
||||
{
|
||||
printf("Usage: exteplayer3 filePath [-u user-agent] [-c cookies] [-h headers] [-p prio] [-a] [-d] [-w] [-l] [-s] [-i] [-t audioTrackId] [-9 subtitleTrackId] [-x separateAudioUri] plabackUri\n");
|
||||
@@ -816,24 +819,24 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
PlaybackDieNowRegisterCallback(TerminateWakeUp);
|
||||
|
||||
HandleTracks(g_player->manager->video, (PlaybackCmd_t) - 1, "vc");
|
||||
HandleTracks(g_player->manager->audio, (PlaybackCmd_t) - 1, "al");
|
||||
HandleTracks(g_player->manager->video, (PlaybackCmd_t) -1, "vc");
|
||||
HandleTracks(g_player->manager->audio, (PlaybackCmd_t) -1, "al");
|
||||
if (audioTrackIdx >= 0)
|
||||
{
|
||||
static char cmd[128] = ""; // static to not allocate on stack
|
||||
sprintf(cmd, "ai%d\n", audioTrackIdx);
|
||||
commandRetVal = HandleTracks(g_player->manager->audio, PLAYBACK_SWITCH_AUDIO, cmd);
|
||||
}
|
||||
HandleTracks(g_player->manager->audio, (PlaybackCmd_t) - 1, "ac");
|
||||
HandleTracks(g_player->manager->audio, (PlaybackCmd_t) -1, "ac");
|
||||
|
||||
HandleTracks(g_player->manager->subtitle, (PlaybackCmd_t) - 1, "sl");
|
||||
HandleTracks(g_player->manager->subtitle, (PlaybackCmd_t) -1, "sl");
|
||||
if (subtitleTrackIdx >= 0)
|
||||
{
|
||||
static char cmd[128] = ""; // static to not allocate on stack
|
||||
sprintf(cmd, "si%d\n", subtitleTrackIdx);
|
||||
commandRetVal = HandleTracks(g_player->manager->subtitle, PLAYBACK_SWITCH_SUBTITLE, cmd);
|
||||
}
|
||||
HandleTracks(g_player->manager->subtitle, (PlaybackCmd_t) - 1, "sc");
|
||||
HandleTracks(g_player->manager->subtitle, (PlaybackCmd_t) -1, "sc");
|
||||
}
|
||||
|
||||
while (g_player->playback->isPlaying && 0 == PlaybackDieNow(0))
|
||||
@@ -855,7 +858,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
case 'v':
|
||||
{
|
||||
HandleTracks(g_player->manager->video, (PlaybackCmd_t) - 1, argvBuff);
|
||||
HandleTracks(g_player->manager->video, (PlaybackCmd_t) -1, argvBuff);
|
||||
break;
|
||||
}
|
||||
case 'a':
|
||||
@@ -966,10 +969,12 @@ int main(int argc, char *argv[])
|
||||
|
||||
commandRetVal = g_player->playback->Command(g_player, PLAYBACK_PTS, &pts);
|
||||
CurrentSec = (int32_t)(pts / 90000);
|
||||
|
||||
if (0 == commandRetVal)
|
||||
{
|
||||
fprintf(stderr, "{\"J\":{\"ms\":%lld}}\n", pts / 90);
|
||||
}
|
||||
|
||||
if (0 == commandRetVal || force)
|
||||
{
|
||||
commandRetVal = g_player->playback->Command(g_player, PLAYBACK_LENGTH, (void *)&length);
|
||||
@@ -1016,6 +1021,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
int64_t lastPts = 0;
|
||||
commandRetVal = 1;
|
||||
|
||||
if (g_player->container && g_player->container->selectedContainer)
|
||||
{
|
||||
commandRetVal = g_player->container->selectedContainer->Command((Context_t*)g_player->container, CONTAINER_LAST_PTS, &lastPts);
|
||||
|
@@ -46,7 +46,7 @@
|
||||
static short debug_level = 40;
|
||||
|
||||
#define audio_mgr_printf(level, fmt, x...) do { \
|
||||
if (debug_level >= level) printf("[%s:%s] \n" fmt, __FILE__, __FUNCTION__, ## x); } while (0)
|
||||
if (debug_level >= level) printf("[%s::%s] \n" fmt, __FILE__, __FUNCTION__, ## x); } while (0)
|
||||
#else
|
||||
#define audio_mgr_printf(level, x...)
|
||||
#endif
|
||||
@@ -97,7 +97,7 @@ static int ManagerAdd(Context_t *context, Track_t track)
|
||||
|
||||
if (Tracks == NULL)
|
||||
{
|
||||
audio_mgr_err("%s:%s malloc failed\n", __FILE__, __FUNCTION__);
|
||||
audio_mgr_err("%s::%s malloc failed\n", __FILE__, __FUNCTION__);
|
||||
return cERR_AUDIO_MGR_ERROR;
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ static int ManagerAdd(Context_t *context, Track_t track)
|
||||
}
|
||||
else
|
||||
{
|
||||
audio_mgr_err("%s:%s TrackCount out if range %d - %d\n", __FILE__, __FUNCTION__, TrackCount, TRACKWRAP);
|
||||
audio_mgr_err("%s::%s TrackCount out if range %d - %d\n", __FILE__, __FUNCTION__, TrackCount, TRACKWRAP);
|
||||
return cERR_AUDIO_MGR_ERROR;
|
||||
}
|
||||
|
||||
@@ -128,6 +128,7 @@ static int ManagerAdd(Context_t *context, Track_t track)
|
||||
}
|
||||
|
||||
audio_mgr_printf(10, "%s::%s\n", __FILE__, __FUNCTION__);
|
||||
|
||||
return cERR_AUDIO_MGR_NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -137,13 +138,14 @@ static char **ManagerList(Context_t *context __attribute__((unused)))
|
||||
char **tracklist = NULL;
|
||||
|
||||
audio_mgr_printf(10, "%s::%s\n", __FILE__, __FUNCTION__);
|
||||
|
||||
if (Tracks != NULL)
|
||||
{
|
||||
tracklist = malloc(sizeof(char *) * ((TrackCount * 2) + 1));
|
||||
|
||||
if (tracklist == NULL)
|
||||
{
|
||||
audio_mgr_err("%s:%s malloc failed\n", __FILE__, __FUNCTION__);
|
||||
audio_mgr_err("%s::%s malloc failed\n", __FILE__, __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -160,9 +162,9 @@ static char **ManagerList(Context_t *context __attribute__((unused)))
|
||||
tracklist[j] = strdup(tmp);
|
||||
tracklist[j + 1] = strdup(Tracks[i].Encoding);
|
||||
}
|
||||
|
||||
tracklist[j] = NULL;
|
||||
}
|
||||
|
||||
audio_mgr_printf(10, "%s::%s return %p (%d - %d)\n", __FILE__, __FUNCTION__, tracklist, j, TrackCount);
|
||||
|
||||
return tracklist;
|
||||
@@ -181,7 +183,7 @@ static TrackDescription_t *ManagerList(Context_t *context __attribute__((unused
|
||||
|
||||
if (tracklist == NULL)
|
||||
{
|
||||
audio_mgr_err("%s:%s malloc failed\n", __FILE__, __FUNCTION__);
|
||||
audio_mgr_err("%s::%s malloc failed\n", __FILE__, __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -256,7 +258,7 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument)
|
||||
{
|
||||
container_ffmpeg_update_tracks(context, context->playback->uri, 0);
|
||||
// *((TrackDescription_t **)argument) = ManagerList(context);
|
||||
*((char ** *) argument) = (char **) ManagerList(context);
|
||||
*((char ***)argument) = (char **)ManagerList(context);
|
||||
break;
|
||||
}
|
||||
case MANAGER_REF_LIST:
|
||||
@@ -279,7 +281,7 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument)
|
||||
}
|
||||
else
|
||||
{
|
||||
*((int *)argument) = (int) - 1;
|
||||
*((int *)argument) = (int) -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -292,9 +294,9 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument)
|
||||
if (track)
|
||||
{
|
||||
memset(track, 0, sizeof(TrackDescription_t));
|
||||
track->Id = Tracks[CurrentTrack].Id;
|
||||
track->Name = strdup(Tracks[CurrentTrack].Name);
|
||||
track->Encoding = strdup(Tracks[CurrentTrack].Encoding);
|
||||
track->Id = Tracks[CurrentTrack].Id;
|
||||
track->Name = strdup(Tracks[CurrentTrack].Name);
|
||||
track->Encoding = strdup(Tracks[CurrentTrack].Encoding);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -382,7 +384,7 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument)
|
||||
break;
|
||||
}
|
||||
|
||||
audio_mgr_printf(10, "%s:%s: returning %d\n", __FILE__, __FUNCTION__, ret);
|
||||
audio_mgr_printf(10, "%s::%s returning %d\n", __FILE__, __FUNCTION__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@@ -118,7 +118,7 @@ static int ManagerAdd(Context_t *context __attribute__((unused)), Track_t track)
|
||||
}
|
||||
else
|
||||
{
|
||||
subtitle_mgr_err("%s:%s TrackCount out if range %d - %d\n", __FILE__, __FUNCTION__, TrackCount, TRACKWRAP);
|
||||
subtitle_mgr_err("%s::%s TrackCount out if range %d - %d\n", __FILE__, __FUNCTION__, TrackCount, TRACKWRAP);
|
||||
return cERR_SUBTITLE_MGR_ERROR;
|
||||
}
|
||||
|
||||
@@ -134,8 +134,8 @@ static int ManagerAdd(Context_t *context __attribute__((unused)), Track_t track)
|
||||
|
||||
static char **ManagerList(Context_t *context __attribute__((unused)))
|
||||
{
|
||||
char **tracklist = NULL;
|
||||
int i = 0, j = 0;
|
||||
char **tracklist = NULL;
|
||||
|
||||
subtitle_mgr_printf(10, "%s::%s\n", __FILE__, __FUNCTION__);
|
||||
|
||||
@@ -145,7 +145,7 @@ static char **ManagerList(Context_t *context __attribute__((unused)))
|
||||
|
||||
if (tracklist == NULL)
|
||||
{
|
||||
subtitle_mgr_err("%s:%s malloc failed\n", __FILE__, __FUNCTION__);
|
||||
subtitle_mgr_err("%s::%s malloc failed\n", __FILE__, __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -162,7 +162,6 @@ static char **ManagerList(Context_t *context __attribute__((unused)))
|
||||
tracklist[j] = strdup(tmp);
|
||||
tracklist[j + 1] = strdup(Tracks[i].Encoding);
|
||||
}
|
||||
|
||||
tracklist[j] = NULL;
|
||||
}
|
||||
|
||||
@@ -219,18 +218,20 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument)
|
||||
case MANAGER_LIST:
|
||||
{
|
||||
container_ffmpeg_update_tracks(context, context->playback->uri, 0);
|
||||
*((char ** *)argument) = (char **)ManagerList(context);
|
||||
*((char ***)argument) = (char **)ManagerList(context);
|
||||
break;
|
||||
}
|
||||
case MANAGER_GET:
|
||||
{
|
||||
subtitle_mgr_printf(20, "%s::%s MANAGER_GET\n", FILENAME, __FUNCTION__);
|
||||
|
||||
if (TrackCount > 0 && CurrentTrack >= 0)
|
||||
{
|
||||
*((int *)argument) = (int)Tracks[CurrentTrack].Id;
|
||||
}
|
||||
else
|
||||
{
|
||||
*((int *)argument) = (int) - 1;
|
||||
*((int *)argument) = (int) -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -243,9 +244,9 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument)
|
||||
if (track)
|
||||
{
|
||||
memset(track, 0, sizeof(TrackDescription_t));
|
||||
track->Id = Tracks[CurrentTrack].Id;
|
||||
track->Name = strdup(Tracks[CurrentTrack].Name);
|
||||
track->Encoding = strdup(Tracks[CurrentTrack].Encoding);
|
||||
track->Id = Tracks[CurrentTrack].Id;
|
||||
track->Name = strdup(Tracks[CurrentTrack].Name);
|
||||
track->Encoding = strdup(Tracks[CurrentTrack].Encoding);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -256,6 +257,8 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument)
|
||||
}
|
||||
case MANAGER_GET_TRACK:
|
||||
{
|
||||
subtitle_mgr_printf(20, "%s::%s MANAGER_GET_TRACK\n", FILENAME, __FUNCTION__);
|
||||
|
||||
if ((TrackCount > 0) && (CurrentTrack >= 0))
|
||||
{
|
||||
*((Track_t **)argument) = (Track_t *) &Tracks[CurrentTrack];
|
||||
@@ -293,6 +296,7 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument)
|
||||
case MANAGER_SET:
|
||||
{
|
||||
int i;
|
||||
|
||||
subtitle_mgr_printf(20, "%s::%s MANAGER_SET id=%d\n", __FILE__, __FUNCTION__, *((int *)argument));
|
||||
|
||||
if (*((int *)argument) < 0)
|
||||
@@ -332,12 +336,12 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument)
|
||||
break;
|
||||
}
|
||||
default:
|
||||
subtitle_mgr_err("%s:%s: ContainerCmd not supported!", __FILE__, __FUNCTION__);
|
||||
subtitle_mgr_err("%s::%s ContainerCmd not supported!", __FILE__, __FUNCTION__);
|
||||
ret = cERR_SUBTITLE_MGR_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
subtitle_mgr_printf(50, "%s:%s: returning %d\n", __FILE__, __FUNCTION__, ret);
|
||||
subtitle_mgr_printf(50, "%s::%s returning %d\n", __FILE__, __FUNCTION__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@@ -97,7 +97,7 @@ static int ManagerAdd(Context_t *context, Track_t track)
|
||||
|
||||
if (Tracks == NULL)
|
||||
{
|
||||
video_mgr_err("%s:%s malloc failed\n", __FILE__, __FUNCTION__);
|
||||
video_mgr_err("%s::%s malloc failed\n", __FILE__, __FUNCTION__);
|
||||
return cERR_VIDEO_MGR_ERROR;
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ static int ManagerAdd(Context_t *context, Track_t track)
|
||||
}
|
||||
else
|
||||
{
|
||||
video_mgr_err("%s:%s TrackCount out if range %d - %d\n", __FILE__, __FUNCTION__, TrackCount, TRACKWRAP);
|
||||
video_mgr_err("%s::%s TrackCount out if range %d - %d\n", __FILE__, __FUNCTION__, TrackCount, TRACKWRAP);
|
||||
return cERR_VIDEO_MGR_ERROR;
|
||||
}
|
||||
|
||||
@@ -128,6 +128,7 @@ static int ManagerAdd(Context_t *context, Track_t track)
|
||||
}
|
||||
|
||||
video_mgr_printf(10, "%s::%s\n", __FILE__, __FUNCTION__);
|
||||
|
||||
return cERR_VIDEO_MGR_NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -144,7 +145,7 @@ static char **ManagerList(Context_t *context __attribute__((unused)))
|
||||
|
||||
if (tracklist == NULL)
|
||||
{
|
||||
video_mgr_err("%s:%s malloc failed\n", __FILE__, __FUNCTION__);
|
||||
video_mgr_err("%s::%s malloc failed\n", __FILE__, __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -164,6 +165,7 @@ static char **ManagerList(Context_t *context __attribute__((unused)))
|
||||
}
|
||||
|
||||
video_mgr_printf(10, "%s::%s return %p (%d - %d)\n", __FILE__, __FUNCTION__, tracklist, j, TrackCount);
|
||||
|
||||
return tracklist;
|
||||
}
|
||||
|
||||
@@ -213,7 +215,7 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument)
|
||||
case MANAGER_LIST:
|
||||
{
|
||||
container_ffmpeg_update_tracks(context, context->playback->uri, 0);
|
||||
*((char ** *)argument) = (char **)ManagerList(context);
|
||||
*((char ***)argument) = (char **)ManagerList(context);
|
||||
break;
|
||||
}
|
||||
case MANAGER_GET:
|
||||
@@ -224,7 +226,7 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument)
|
||||
}
|
||||
else
|
||||
{
|
||||
*((int *)argument) = (int) - 1;
|
||||
*((int *)argument) = (int) -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -342,7 +344,7 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument)
|
||||
break;
|
||||
}
|
||||
|
||||
video_mgr_printf(10, "%s:%s: returning %d\n", __FILE__, __FUNCTION__, ret);
|
||||
video_mgr_printf(10, "%s::%s returning %d\n", __FILE__, __FUNCTION__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@@ -252,6 +252,7 @@ int LinuxDvbPlay(Context_t *context, char *type)
|
||||
linuxdvb_printf(10, "V %s\n", Encoding);
|
||||
|
||||
writer = getWriter(Encoding);
|
||||
|
||||
if (writer == NULL)
|
||||
{
|
||||
linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding);
|
||||
@@ -324,7 +325,6 @@ int LinuxDvbPlay(Context_t *context, char *type)
|
||||
|
||||
ret = cERR_LINUXDVB_NO_ERROR;
|
||||
return ret;
|
||||
//return 0;
|
||||
}
|
||||
|
||||
int LinuxDvbStop(Context_t *context __attribute__((unused)), char *type)
|
||||
@@ -354,6 +354,7 @@ int LinuxDvbStop(Context_t *context __attribute__((unused)), char *type)
|
||||
ioctl(videofd, VIDEO_FAST_FORWARD, 0);
|
||||
ioctl(videofd, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX);
|
||||
}
|
||||
|
||||
if (audio && audiofd != -1)
|
||||
{
|
||||
if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1)
|
||||
@@ -634,6 +635,7 @@ int LinuxDvbPts(Context_t *context __attribute__((unused)), unsigned long long i
|
||||
}
|
||||
|
||||
*((unsigned long long int *)pts) = (unsigned long long int)sCURRENT_PTS;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1095,7 +1097,7 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument)
|
||||
case OUTPUT_GET_BUFFER_SIZE:
|
||||
{
|
||||
ret = cERR_LINUXDVB_NO_ERROR;
|
||||
*((uint32_t*)argument) = LinuxDvbBuffGetSize();
|
||||
*((uint32_t *)argument) = LinuxDvbBuffGetSize();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@@ -90,6 +90,7 @@ static void printOutputCapabilities()
|
||||
for (i = 0; AvailableOutput[i] != NULL; i++)
|
||||
{
|
||||
output_printf(10, "\t%s : ", AvailableOutput[i]->Name);
|
||||
|
||||
for (j = 0; AvailableOutput[i]->Capabilities[j] != NULL; j++)
|
||||
{
|
||||
output_printf(10, "%s ", AvailableOutput[i]->Capabilities[j]);
|
||||
@@ -191,10 +192,12 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument)
|
||||
{
|
||||
ret |= context->output->video->Command(context, OUTPUT_CLOSE, "video");
|
||||
}
|
||||
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
ret |= context->output->audio->Command(context, OUTPUT_CLOSE, "audio");
|
||||
}
|
||||
|
||||
if (context->playback->isSubtitle)
|
||||
{
|
||||
ret |= context->output->subtitle->Command(context, OUTPUT_CLOSE, "subtitle");
|
||||
@@ -238,6 +241,7 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument)
|
||||
{
|
||||
ret = context->output->audio->Command(context, OUTPUT_PLAY, "audio");
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
if (context->playback->isSubtitle)
|
||||
@@ -260,10 +264,12 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument)
|
||||
{
|
||||
ret |= context->output->video->Command(context, OUTPUT_STOP, "video");
|
||||
}
|
||||
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
ret |= context->output->audio->Command(context, OUTPUT_STOP, "audio");
|
||||
}
|
||||
|
||||
if (context->playback->isSubtitle)
|
||||
{
|
||||
ret |= context->output->subtitle->Command(context, OUTPUT_STOP, "subtitle");
|
||||
@@ -283,10 +289,12 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument)
|
||||
{
|
||||
ret |= context->output->video->Command(context, OUTPUT_FLUSH, "video");
|
||||
}
|
||||
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
ret |= context->output->audio->Command(context, OUTPUT_FLUSH, "audio");
|
||||
}
|
||||
|
||||
if (context->playback->isSubtitle)
|
||||
{
|
||||
ret |= context->output->subtitle->Command(context, OUTPUT_FLUSH, "subtitle");
|
||||
@@ -306,10 +314,12 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument)
|
||||
{
|
||||
ret |= context->output->video->Command(context, OUTPUT_PAUSE, "video");
|
||||
}
|
||||
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
ret |= context->output->audio->Command(context, OUTPUT_PAUSE, "audio");
|
||||
}
|
||||
|
||||
if (context->playback->isSubtitle)
|
||||
{
|
||||
ret |= context->output->subtitle->Command(context, OUTPUT_PAUSE, "subtitle");
|
||||
@@ -329,6 +339,7 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument)
|
||||
{
|
||||
ret |= context->output->video->Command(context, OUTPUT_FASTFORWARD, "video");
|
||||
}
|
||||
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
ret |= context->output->audio->Command(context, OUTPUT_FASTFORWARD, "audio");
|
||||
@@ -348,6 +359,7 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument)
|
||||
{
|
||||
ret |= context->output->video->Command(context, OUTPUT_REVERSE, "video");
|
||||
}
|
||||
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
ret |= context->output->audio->Command(context, OUTPUT_REVERSE, "audio");
|
||||
@@ -367,10 +379,12 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument)
|
||||
{
|
||||
ret |= context->output->video->Command(context, OUTPUT_CONTINUE, "video");
|
||||
}
|
||||
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
ret |= context->output->audio->Command(context, OUTPUT_CONTINUE, "audio");
|
||||
}
|
||||
|
||||
if (context->playback->isSubtitle)
|
||||
{
|
||||
ret |= context->output->subtitle->Command(context, OUTPUT_CONTINUE, "subtitle");
|
||||
@@ -405,10 +419,12 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument)
|
||||
{
|
||||
ret |= context->output->video->Command(context, OUTPUT_CLEAR, "video");
|
||||
}
|
||||
|
||||
if (context->playback->isAudio && (argument == NULL || *(char *) argument == 'a'))
|
||||
{
|
||||
ret |= context->output->audio->Command(context, OUTPUT_CLEAR, "audio");
|
||||
}
|
||||
|
||||
if (context->playback->isSubtitle && (argument == NULL || *(char *) argument == 's'))
|
||||
{
|
||||
ret |= context->output->subtitle->Command(context, OUTPUT_CLEAR, "subtitle");
|
||||
@@ -428,6 +444,7 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument)
|
||||
{
|
||||
return context->output->video->Command(context, OUTPUT_PTS, argument);
|
||||
}
|
||||
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
return context->output->audio->Command(context, OUTPUT_PTS, argument);
|
||||
@@ -447,10 +464,12 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument)
|
||||
{
|
||||
return context->output->audio->Command(context, OUTPUT_SWITCH, "audio");
|
||||
}
|
||||
|
||||
if (context->playback->isVideo)
|
||||
{
|
||||
return context->output->video->Command(context, OUTPUT_SWITCH, "video");
|
||||
}
|
||||
|
||||
if (context->playback->isSubtitle)
|
||||
{
|
||||
return context->output->subtitle->Command(context, OUTPUT_SWITCH, "subtitle");
|
||||
@@ -470,6 +489,7 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument)
|
||||
{
|
||||
ret |= context->output->video->Command(context, OUTPUT_SLOWMOTION, "video");
|
||||
}
|
||||
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
ret |= context->output->audio->Command(context, OUTPUT_SLOWMOTION, "audio");
|
||||
@@ -519,6 +539,7 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument)
|
||||
{
|
||||
return context->output->video->Command(context, OUTPUT_GET_FRAME_COUNT, argument);
|
||||
}
|
||||
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
return context->output->audio->Command(context, OUTPUT_GET_FRAME_COUNT, argument);
|
||||
|
@@ -266,8 +266,6 @@ static int32_t subtitle_Open(Context_t *context __attribute__((unused)))
|
||||
|
||||
static int32_t subtitle_Close(Context_t *context __attribute__((unused)))
|
||||
{
|
||||
//uint32_t i = 0 ;
|
||||
|
||||
subtitle_printf(10, "\n");
|
||||
|
||||
getMutex(__LINE__);
|
||||
@@ -341,6 +339,7 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument __att
|
||||
}
|
||||
|
||||
subtitle_printf(50, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@@ -70,5 +70,5 @@ if (debug_level >= level) printf(x); } while (0)
|
||||
void FlushPipe(int pipefd)
|
||||
{
|
||||
char tmp;
|
||||
while(1 == read(pipefd, &tmp, 1));
|
||||
while (1 == read(pipefd, &tmp, 1));
|
||||
}
|
||||
|
@@ -52,6 +52,7 @@
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
#define PES_AUDIO_PRIVATE_HEADER_SIZE 16 // consider maximum private header size.
|
||||
#define PES_AUDIO_HEADER_SIZE (32 + PES_AUDIO_PRIVATE_HEADER_SIZE)
|
||||
#define PES_AUDIO_PACKET_SIZE 2028
|
||||
|
@@ -169,6 +169,7 @@ static int writeData(WriterAVCallData_t *call)
|
||||
iov[0].iov_len = headerSize;
|
||||
iov[1].iov_base = call->data;
|
||||
iov[1].iov_len = call->len;
|
||||
|
||||
return call->WriteV(call->fd, iov, 2);
|
||||
}
|
||||
|
||||
|
@@ -54,7 +54,7 @@ if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x);
|
||||
#define cERR_PLAYBACK_NO_ERROR 0
|
||||
#define cERR_PLAYBACK_ERROR -1
|
||||
|
||||
#define cMaxSpeed_ff 128 /* fixme: revise */
|
||||
#define cMaxSpeed_ff 128 /* fixme: revise */
|
||||
#define cMaxSpeed_fr -320 /* fixme: revise */
|
||||
|
||||
#define MAX_PLAYBACK_DIE_NOW_CALLBACKS 10
|
||||
@@ -140,6 +140,7 @@ static void SupervisorThread(Context_t *context)
|
||||
{
|
||||
usleep(100000);
|
||||
}
|
||||
|
||||
playback_printf(10, "<\n");
|
||||
hasThreadStarted = 2;
|
||||
PlaybackTerminate(context);
|
||||
@@ -293,6 +294,7 @@ static int PlaybackPlay(Context_t *context)
|
||||
{
|
||||
playback_err("OUTPUT_PLAY failed!\n");
|
||||
playback_err("clearing isCreationPhase!\n");
|
||||
|
||||
context->playback->isCreationPhase = 0; // allow thread to go into next state
|
||||
context->playback->isPlaying = 0;
|
||||
context->playback->isPaused = 0;
|
||||
@@ -300,6 +302,7 @@ static int PlaybackPlay(Context_t *context)
|
||||
context->playback->BackWard = 0;
|
||||
context->playback->SlowMotion = 0;
|
||||
context->playback->Speed = 0;
|
||||
|
||||
if (context->container && context->container->selectedContainer)
|
||||
ret = context->container->selectedContainer->Command(context, CONTAINER_STOP, NULL);
|
||||
}
|
||||
@@ -317,7 +320,8 @@ static int PlaybackPlay(Context_t *context)
|
||||
int error;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
if ((error = pthread_create(&supervisorThread, &attr, (void *) &SupervisorThread, context)) != 0)
|
||||
|
||||
if ((error = pthread_create(&supervisorThread, &attr, (void *)&SupervisorThread, context)) != 0)
|
||||
{
|
||||
playback_printf(10, "Error creating thread, error:%d:%s\n", error, strerror(error));
|
||||
ret = cERR_PLAYBACK_ERROR;
|
||||
@@ -334,11 +338,11 @@ static int PlaybackPlay(Context_t *context)
|
||||
|
||||
if (context->container && context->container->selectedContainer)
|
||||
ret = context->container->selectedContainer->Command(context, CONTAINER_PLAY, NULL);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
playback_err("CONTAINER_PLAY failed!\n");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -363,10 +367,9 @@ static int PlaybackPause(Context_t *context)
|
||||
if (context->playback->SlowMotion)
|
||||
context->output->Command(context, OUTPUT_CLEAR, NULL);
|
||||
|
||||
context->playback->isPaused = 1;
|
||||
|
||||
context->output->Command(context, OUTPUT_PAUSE, NULL);
|
||||
|
||||
context->playback->isPaused = 1;
|
||||
//context->playback->isPlaying = 1;
|
||||
context->playback->isForwarding = 0;
|
||||
context->playback->BackWard = 0;
|
||||
@@ -396,6 +399,8 @@ static int32_t PlaybackContinue(Context_t *context)
|
||||
if (context->playback->SlowMotion || context->playback->isForwarding || context->playback->BackWard)
|
||||
context->output->Command(context, OUTPUT_CLEAR, NULL);
|
||||
|
||||
context->output->Command(context, OUTPUT_CONTINUE, NULL);
|
||||
|
||||
if (context->playback->BackWard)
|
||||
context->output->Command(context, OUTPUT_AUDIOMUTE, "0");
|
||||
|
||||
@@ -405,7 +410,6 @@ static int32_t PlaybackContinue(Context_t *context)
|
||||
context->playback->BackWard = 0;
|
||||
context->playback->SlowMotion = 0;
|
||||
context->playback->Speed = 1;
|
||||
context->output->Command(context, OUTPUT_CONTINUE, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -414,6 +418,7 @@ static int32_t PlaybackContinue(Context_t *context)
|
||||
}
|
||||
|
||||
playback_printf(10, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -428,7 +433,6 @@ static int32_t PlaybackStop(Context_t *context)
|
||||
|
||||
if (context && context->playback && context->playback->isPlaying)
|
||||
{
|
||||
|
||||
context->playback->isPaused = 0;
|
||||
context->playback->isPlaying = 0;
|
||||
context->playback->isForwarding = 0;
|
||||
@@ -438,7 +442,6 @@ static int32_t PlaybackStop(Context_t *context)
|
||||
|
||||
context->output->Command(context, OUTPUT_STOP, NULL);
|
||||
context->container->selectedContainer->Command(context, CONTAINER_STOP, NULL);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -459,13 +462,13 @@ static int32_t PlaybackStop(Context_t *context)
|
||||
}
|
||||
|
||||
playback_printf(10, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t PlaybackTerminate(Context_t *context)
|
||||
{
|
||||
int32_t ret = cERR_PLAYBACK_NO_ERROR;
|
||||
|
||||
int wait_time = 20;
|
||||
|
||||
playback_printf(20, "\n");
|
||||
@@ -475,12 +478,13 @@ static int32_t PlaybackTerminate(Context_t *context)
|
||||
if (context && context->playback && context->playback->isPlaying)
|
||||
{
|
||||
//First Flush and than delete container, else e2 cant read length of file anymore
|
||||
|
||||
if (context->output->Command(context, OUTPUT_FLUSH, NULL) < 0)
|
||||
{
|
||||
playback_err("failed to flush output.\n");
|
||||
}
|
||||
|
||||
ret = context->container->selectedContainer->Command(context, CONTAINER_STOP, NULL);
|
||||
|
||||
context->playback->isPaused = 0;
|
||||
context->playback->isPlaying = 0;
|
||||
context->playback->isForwarding = 0;
|
||||
@@ -488,7 +492,6 @@ static int32_t PlaybackTerminate(Context_t *context)
|
||||
context->playback->SlowMotion = 0;
|
||||
context->playback->Speed = 0;
|
||||
context->output->Command(context, OUTPUT_STOP, NULL);
|
||||
ret = context->container->selectedContainer->Command(context, CONTAINER_STOP, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -513,6 +516,7 @@ static int32_t PlaybackTerminate(Context_t *context)
|
||||
}
|
||||
|
||||
playback_printf(20, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -530,6 +534,7 @@ static int PlaybackFastForward(Context_t *context, int *speed)
|
||||
playback_err("speed %d out of range (1 - %d) \n", *speed, cMaxSpeed_ff);
|
||||
return cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
context->playback->isForwarding = 1;
|
||||
context->playback->Speed = *speed;
|
||||
playback_printf(20, "Speed: %d x {%d}\n", *speed, context->playback->Speed);
|
||||
@@ -562,19 +567,30 @@ static int PlaybackFastBackward(Context_t *context, int *speed)
|
||||
playback_err("speed %d out of range (0 - %d) \n", *speed, cMaxSpeed_fr);
|
||||
return cERR_PLAYBACK_ERROR;
|
||||
}
|
||||
|
||||
PlaybackContinue(context);
|
||||
|
||||
if (*speed == 0)
|
||||
{
|
||||
context->playback->BackWard = 0;
|
||||
context->playback->Speed = 0; /* reverse end */
|
||||
context->playback->isPaused = 0;
|
||||
//context->playback->isPlaying = 0;
|
||||
context->playback->isForwarding = 0;
|
||||
context->playback->BackWard = 0;
|
||||
context->playback->SlowMotion = 0;
|
||||
context->playback->Speed = 0;
|
||||
context->output->Command(context, OUTPUT_AUDIOMUTE, "0");
|
||||
}
|
||||
else
|
||||
{
|
||||
context->playback->isSeeking = 1;
|
||||
context->playback->Speed = *speed;
|
||||
context->playback->BackWard = 1;
|
||||
context->playback->isPaused = 0;
|
||||
//context->playback->isPlaying = 0;
|
||||
context->playback->isForwarding = 0;
|
||||
context->playback->BackWard = 1;
|
||||
context->playback->SlowMotion = 0;
|
||||
context->playback->Speed = *speed;
|
||||
context->playback->isSeeking = 1;
|
||||
context->output->Command(context, OUTPUT_AUDIOMUTE, "1");
|
||||
playback_printf(1, "S %d B %d\n", context->playback->Speed, context->playback->BackWard);
|
||||
playback_printf(1, "Speed: %d, Backward: %d\n", context->playback->Speed, context->playback->BackWard);
|
||||
}
|
||||
|
||||
context->output->Command(context, OUTPUT_CLEAR, NULL);
|
||||
@@ -602,6 +618,7 @@ static int32_t PlaybackSlowMotion(Context_t *context, int *speed)
|
||||
{
|
||||
if (context->playback->isPaused)
|
||||
PlaybackContinue(context);
|
||||
|
||||
switch (*speed)
|
||||
{
|
||||
case 2:
|
||||
@@ -614,7 +631,9 @@ static int32_t PlaybackSlowMotion(Context_t *context, int *speed)
|
||||
context->playback->SlowMotion = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
playback_printf(20, "SlowMotion: %d x {%d}\n", *speed, context->playback->SlowMotion);
|
||||
|
||||
context->output->Command(context, OUTPUT_SLOWMOTION, NULL);
|
||||
}
|
||||
else
|
||||
@@ -727,6 +746,7 @@ static int32_t PlaybackLength(Context_t *context, int64_t *length)
|
||||
}
|
||||
|
||||
playback_printf(20, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -754,7 +774,6 @@ static int32_t PlaybackSwitchAudio(Context_t *context, int32_t *track)
|
||||
|
||||
if (nextrackid != curtrackid)
|
||||
{
|
||||
|
||||
//PlaybackPause(context);
|
||||
if (context->output && context->output->audio)
|
||||
{
|
||||
@@ -775,6 +794,7 @@ static int32_t PlaybackSwitchAudio(Context_t *context, int32_t *track)
|
||||
}
|
||||
|
||||
playback_printf(10, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -861,7 +881,6 @@ static int32_t Command(Context_t *context, PlaybackCmd_t command, void *argument
|
||||
|
||||
playback_printf(20, "Command %d\n", command);
|
||||
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case PLAYBACK_OPEN:
|
||||
@@ -899,6 +918,11 @@ static int32_t Command(Context_t *context, PlaybackCmd_t command, void *argument
|
||||
ret = PlaybackTerminate(context);
|
||||
break;
|
||||
}
|
||||
case PLAYBACK_FASTFORWARD:
|
||||
{
|
||||
ret = PlaybackFastForward(context, (int *)argument);
|
||||
break;
|
||||
}
|
||||
case PLAYBACK_SEEK:
|
||||
{
|
||||
ret = PlaybackSeek(context, (int64_t *)argument, 0);
|
||||
@@ -944,11 +968,6 @@ static int32_t Command(Context_t *context, PlaybackCmd_t command, void *argument
|
||||
ret = PlaybackFastBackward(context, (int *)argument);
|
||||
break;
|
||||
}
|
||||
case PLAYBACK_FASTFORWARD:
|
||||
{
|
||||
ret = PlaybackFastForward(context, (int *)argument);
|
||||
break;
|
||||
}
|
||||
case PLAYBACK_GET_FRAME_COUNT:
|
||||
{
|
||||
ret = PlaybackGetFrameCount(context, (uint64_t *)argument);
|
||||
|
@@ -4,7 +4,7 @@ noinst_LTLIBRARIES = libeplayer3.la
|
||||
|
||||
AM_CPPFLAGS = -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS
|
||||
AM_CPPFLAGS += -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
|
||||
AM_CPPFLAGS += -I$(srcdir)/include -I$(top_srcdir)/include
|
||||
AM_CPPFLAGS += -I$(srcdir)/include
|
||||
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
|
||||
|
||||
libeplayer3_la_SOURCES = \
|
||||
|
@@ -26,7 +26,9 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <scoped_lock.h>
|
||||
#include <OpenThreads/ScopedLock>
|
||||
#include <OpenThreads/Thread>
|
||||
#include <OpenThreads/Condition>
|
||||
|
||||
extern "C" {
|
||||
#include <libavutil/avutil.h>
|
||||
@@ -46,7 +48,7 @@ class Input
|
||||
friend int interrupt_cb(void *arg);
|
||||
|
||||
private:
|
||||
Mutex mutex;
|
||||
OpenThreads::Mutex mutex;
|
||||
|
||||
Track *videoTrack;
|
||||
Track *audioTrack;
|
||||
|
@@ -26,7 +26,9 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <scoped_lock.h>
|
||||
#include <OpenThreads/ScopedLock>
|
||||
#include <OpenThreads/Thread>
|
||||
#include <OpenThreads/Condition>
|
||||
|
||||
extern "C" {
|
||||
#include <libavutil/avutil.h>
|
||||
@@ -64,7 +66,7 @@ class Manager
|
||||
|
||||
private:
|
||||
Player *player;
|
||||
Mutex mutex;
|
||||
OpenThreads::Mutex mutex;
|
||||
std::map<int,Track*> videoTracks, audioTracks, subtitleTracks, teletextTracks;
|
||||
std::map<int,Program> Programs;
|
||||
void addTrack(std::map<int,Track*> &tracks, Track &track);
|
||||
|
@@ -26,7 +26,9 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <scoped_lock.h>
|
||||
#include <OpenThreads/ScopedLock>
|
||||
#include <OpenThreads/Thread>
|
||||
#include <OpenThreads/Condition>
|
||||
|
||||
extern "C" {
|
||||
#include <libavutil/avutil.h>
|
||||
@@ -48,7 +50,7 @@ class Output
|
||||
int videofd;
|
||||
int audiofd;
|
||||
Writer *videoWriter, *audioWriter;
|
||||
Mutex audioMutex, videoMutex;
|
||||
OpenThreads::Mutex audioMutex, videoMutex;
|
||||
Track *audioTrack, *videoTrack;
|
||||
Player *player;
|
||||
public:
|
||||
|
@@ -21,7 +21,9 @@
|
||||
#ifndef __PLAYER_H__
|
||||
#define __PLAYER_H__
|
||||
|
||||
#include <scoped_lock.h>
|
||||
#include <OpenThreads/ScopedLock>
|
||||
#include <OpenThreads/Thread>
|
||||
#include <OpenThreads/Condition>
|
||||
|
||||
extern "C" {
|
||||
#include <libavutil/avutil.h>
|
||||
@@ -61,7 +63,7 @@ class Player {
|
||||
Input input;
|
||||
Output output;
|
||||
Manager manager;
|
||||
Mutex chapterMutex;
|
||||
OpenThreads::Mutex chapterMutex;
|
||||
std::vector<Chapter> chapters;
|
||||
pthread_t playThread;
|
||||
|
||||
|
@@ -290,17 +290,17 @@ static int lock_callback(void **mutex, enum AVLockOp op)
|
||||
{
|
||||
switch (op) {
|
||||
case AV_LOCK_CREATE:
|
||||
*mutex = (void *) new Mutex;
|
||||
*mutex = (void *) new OpenThreads::Mutex;
|
||||
return !*mutex;
|
||||
case AV_LOCK_DESTROY:
|
||||
delete static_cast<Mutex *>(*mutex);
|
||||
delete static_cast<OpenThreads::Mutex *>(*mutex);
|
||||
*mutex = NULL;
|
||||
return 0;
|
||||
case AV_LOCK_OBTAIN:
|
||||
static_cast<Mutex *>(*mutex)->lock();
|
||||
static_cast<OpenThreads::Mutex *>(*mutex)->lock();
|
||||
return 0;
|
||||
case AV_LOCK_RELEASE:
|
||||
static_cast<Mutex *>(*mutex)->unlock();
|
||||
static_cast<OpenThreads::Mutex *>(*mutex)->unlock();
|
||||
return 0;
|
||||
default:
|
||||
return -1;
|
||||
@@ -656,7 +656,7 @@ bool Input::Stop()
|
||||
av_log(NULL, AV_LOG_QUIET, "%s", "");
|
||||
|
||||
if (avfc) {
|
||||
ScopedLock lock(mutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mutex);
|
||||
for (unsigned int i = 0; i < avfc->nb_streams; i++)
|
||||
avcodec_close(avfc->streams[i]->codec);
|
||||
avformat_close_input(&avfc);
|
||||
|
@@ -25,7 +25,7 @@
|
||||
|
||||
void Manager::addTrack(std::map<int,Track*> &tracks, Track &track)
|
||||
{
|
||||
ScopedLock m_lock(mutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||
std::map<int,Track*>::iterator it = tracks.find(track.pid);
|
||||
if (it == tracks.end()) {
|
||||
Track *t = new Track;
|
||||
@@ -59,7 +59,7 @@ std::vector<Track> Manager::getTracks(std::map<int,Track*> &tracks)
|
||||
{
|
||||
player->input.UpdateTracks();
|
||||
std::vector<Track> res;
|
||||
ScopedLock m_lock(mutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||
for(std::map<int,Track*>::iterator it = tracks.begin(); it != tracks.end(); ++it)
|
||||
if (!it->second->inactive && !it->second->hidden)
|
||||
res.push_back(*it->second);
|
||||
@@ -88,7 +88,7 @@ std::vector<Track> Manager::getTeletextTracks()
|
||||
|
||||
Track *Manager::getTrack(std::map<int,Track*> &tracks, int pid)
|
||||
{
|
||||
ScopedLock m_lock(mutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||
std::map<int,Track*>::iterator it = tracks.find(pid);
|
||||
if (it != tracks.end() && !it->second->inactive)
|
||||
return it->second;
|
||||
@@ -116,7 +116,7 @@ Track *Manager::getTeletextTrack(int pid)
|
||||
|
||||
bool Manager::initTrackUpdate()
|
||||
{
|
||||
ScopedLock m_lock(mutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||
|
||||
for (std::map<int,Track*>::iterator it = audioTracks.begin(); it != audioTracks.end(); ++it)
|
||||
it->second->inactive = !it->second->is_static;
|
||||
@@ -140,7 +140,7 @@ void Manager::addProgram(Program &program)
|
||||
|
||||
std::vector<Program> Manager::getPrograms(void)
|
||||
{
|
||||
ScopedLock m_lock(mutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||
std::vector<Program> res;
|
||||
for (std::map<int,Program>::iterator it = Programs.begin(); it != Programs.end(); ++it)
|
||||
res.push_back(it->second);
|
||||
@@ -149,7 +149,7 @@ std::vector<Program> Manager::getPrograms(void)
|
||||
|
||||
bool Manager::selectProgram(const int id)
|
||||
{
|
||||
ScopedLock m_lock(mutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||
std::map<int,Program>::iterator i = Programs.find(id);
|
||||
if (i != Programs.end()) {
|
||||
|
||||
@@ -236,7 +236,7 @@ bool Manager::selectProgram(const int id)
|
||||
|
||||
void Manager::clearTracks()
|
||||
{
|
||||
ScopedLock m_lock(mutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||
|
||||
for (std::map<int,Track*>::iterator it = audioTracks.begin(); it != audioTracks.end(); ++it)
|
||||
delete it->second;
|
||||
|
@@ -68,9 +68,9 @@ Output::~Output()
|
||||
|
||||
bool Output::Open()
|
||||
{
|
||||
ScopedLock v_lock(videoMutex);
|
||||
ScopedLock a_lock(audioMutex);
|
||||
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
|
||||
|
||||
if (videofd < 0)
|
||||
videofd = open(VIDEODEV, O_RDWR);
|
||||
|
||||
@@ -102,8 +102,8 @@ bool Output::Close()
|
||||
{
|
||||
Stop();
|
||||
|
||||
ScopedLock v_lock(videoMutex);
|
||||
ScopedLock a_lock(audioMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
|
||||
|
||||
if (videofd > -1) {
|
||||
close(videofd);
|
||||
@@ -124,8 +124,8 @@ bool Output::Play()
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
ScopedLock v_lock(videoMutex);
|
||||
ScopedLock a_lock(audioMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
|
||||
|
||||
AVCodecContext *avcc;
|
||||
|
||||
@@ -154,8 +154,8 @@ bool Output::Stop()
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
ScopedLock v_lock(videoMutex);
|
||||
ScopedLock a_lock(audioMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
|
||||
|
||||
if (videofd > -1) {
|
||||
ioctl(videofd, VIDEO_CLEAR_BUFFER, NULL);
|
||||
@@ -180,8 +180,8 @@ bool Output::Pause()
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
ScopedLock v_lock(videoMutex);
|
||||
ScopedLock a_lock(audioMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
|
||||
|
||||
if (videofd > -1) {
|
||||
if (dioctl(videofd, VIDEO_FREEZE, NULL))
|
||||
@@ -200,8 +200,8 @@ bool Output::Continue()
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
ScopedLock v_lock(videoMutex);
|
||||
ScopedLock a_lock(audioMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
|
||||
|
||||
if (videofd > -1 && dioctl(videofd, VIDEO_CONTINUE, NULL))
|
||||
ret = false;
|
||||
@@ -214,7 +214,7 @@ bool Output::Continue()
|
||||
|
||||
bool Output::Mute(bool b)
|
||||
{
|
||||
ScopedLock a_lock(audioMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
|
||||
//AUDIO_SET_MUTE has no effect with new player
|
||||
return audiofd > -1 && !dioctl(audiofd, b ? AUDIO_STOP : AUDIO_PLAY, NULL);
|
||||
}
|
||||
@@ -224,8 +224,8 @@ bool Output::Flush()
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
ScopedLock v_lock(videoMutex);
|
||||
ScopedLock a_lock(audioMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
|
||||
|
||||
if (videofd > -1 && ioctl(videofd, VIDEO_FLUSH, NULL))
|
||||
ret = false;
|
||||
@@ -246,31 +246,31 @@ bool Output::Flush()
|
||||
|
||||
bool Output::FastForward(int speed)
|
||||
{
|
||||
ScopedLock v_lock(videoMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
|
||||
return videofd > -1 && !dioctl(videofd, VIDEO_FAST_FORWARD, speed);
|
||||
}
|
||||
|
||||
bool Output::SlowMotion(int speed)
|
||||
{
|
||||
ScopedLock v_lock(videoMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
|
||||
return videofd > -1 && !dioctl(videofd, VIDEO_SLOWMOTION, speed);
|
||||
}
|
||||
|
||||
bool Output::AVSync(bool b)
|
||||
{
|
||||
ScopedLock a_lock(audioMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
|
||||
return audiofd > -1 && !dioctl(audiofd, AUDIO_SET_AV_SYNC, b);
|
||||
}
|
||||
|
||||
bool Output::ClearAudio()
|
||||
{
|
||||
ScopedLock a_lock(audioMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
|
||||
return audiofd > -1 && !ioctl(audiofd, AUDIO_CLEAR_BUFFER, NULL);
|
||||
}
|
||||
|
||||
bool Output::ClearVideo()
|
||||
{
|
||||
ScopedLock v_lock(videoMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
|
||||
return videofd > -1 && !ioctl(videofd, VIDEO_CLEAR_BUFFER, NULL);
|
||||
}
|
||||
|
||||
@@ -302,7 +302,7 @@ bool Output::GetFrameCount(int64_t &framecount)
|
||||
|
||||
bool Output::SwitchAudio(Track *track)
|
||||
{
|
||||
ScopedLock a_lock(audioMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
|
||||
if (audioTrack && track->stream == audioTrack->stream)
|
||||
return true;
|
||||
if (audiofd > -1) {
|
||||
@@ -329,7 +329,7 @@ bool Output::SwitchAudio(Track *track)
|
||||
|
||||
bool Output::SwitchVideo(Track *track)
|
||||
{
|
||||
ScopedLock v_lock(videoMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
|
||||
if (videoTrack && track->stream == videoTrack->stream)
|
||||
return true;
|
||||
if (videofd > -1) {
|
||||
@@ -355,11 +355,11 @@ bool Output::Write(AVStream *stream, AVPacket *packet, int64_t pts)
|
||||
{
|
||||
switch (stream->codec->codec_type) {
|
||||
case AVMEDIA_TYPE_VIDEO: {
|
||||
ScopedLock v_lock(videoMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
|
||||
return videofd > -1 && videoWriter && videoWriter->Write(packet, pts);
|
||||
}
|
||||
case AVMEDIA_TYPE_AUDIO: {
|
||||
ScopedLock a_lock(audioMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
|
||||
return audiofd > -1 && audioWriter && audioWriter->Write(packet, pts);
|
||||
}
|
||||
default:
|
||||
|
@@ -372,7 +372,7 @@ bool Player::GetChapters(std::vector<int> &positions, std::vector<std::string> &
|
||||
positions.clear();
|
||||
titles.clear();
|
||||
input.UpdateTracks();
|
||||
ScopedLock m_lock(chapterMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(chapterMutex);
|
||||
for (std::vector<Chapter>::iterator it = chapters.begin(); it != chapters.end(); ++it) {
|
||||
positions.push_back(it->start/1000);
|
||||
titles.push_back(it->title);
|
||||
@@ -382,7 +382,7 @@ bool Player::GetChapters(std::vector<int> &positions, std::vector<std::string> &
|
||||
|
||||
void Player::SetChapters(std::vector<Chapter> &Chapters)
|
||||
{
|
||||
ScopedLock m_lock(chapterMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(chapterMutex);
|
||||
chapters = Chapters;
|
||||
}
|
||||
|
||||
|
@@ -1,16 +0,0 @@
|
||||
noinst_LTLIBRARIES = libthread.la
|
||||
|
||||
AM_CPPFLAGS = -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
|
||||
AM_CPPFLAGS += \
|
||||
-I$(top_srcdir)/include
|
||||
|
||||
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
|
||||
|
||||
AM_LDFLAGS = -lpthread -lrt
|
||||
|
||||
libthread_la_SOURCES = \
|
||||
condition_abstraction.cpp \
|
||||
reentrant_mutex.cpp \
|
||||
scoped_lock.cpp \
|
||||
thread_abstraction.cpp \
|
||||
mutex_abstraction.cpp
|
@@ -1,27 +0,0 @@
|
||||
#include <condition_abstraction.h>
|
||||
|
||||
Condition::Condition() :
|
||||
mCondition()
|
||||
{
|
||||
pthread_cond_init(&mCondition, 0);
|
||||
}
|
||||
|
||||
Condition::~Condition()
|
||||
{
|
||||
pthread_cond_destroy(&mCondition);
|
||||
}
|
||||
|
||||
int Condition::wait(Mutex* const aMutex)
|
||||
{
|
||||
return pthread_cond_wait(&mCondition, &(aMutex->mMutex));
|
||||
}
|
||||
|
||||
int Condition::broadcast()
|
||||
{
|
||||
return pthread_cond_broadcast(&mCondition);
|
||||
}
|
||||
|
||||
int Condition::signal()
|
||||
{
|
||||
return pthread_cond_signal(&mCondition);
|
||||
}
|
@@ -1,32 +0,0 @@
|
||||
#include <mutex_abstraction.h>
|
||||
|
||||
Mutex::Mutex() :
|
||||
mMutex()
|
||||
{
|
||||
pthread_mutex_init(&mMutex, 0);
|
||||
}
|
||||
|
||||
Mutex::Mutex(int attr) :
|
||||
mMutex()
|
||||
{
|
||||
pthread_mutexattr_t Attr;
|
||||
|
||||
pthread_mutexattr_init(&Attr);
|
||||
pthread_mutexattr_settype(&Attr, attr);
|
||||
pthread_mutex_init(&mMutex, &Attr);
|
||||
}
|
||||
|
||||
Mutex::~Mutex()
|
||||
{
|
||||
pthread_mutex_destroy(&mMutex);
|
||||
}
|
||||
|
||||
void Mutex::lock()
|
||||
{
|
||||
pthread_mutex_lock(&mMutex);
|
||||
}
|
||||
|
||||
void Mutex::unlock()
|
||||
{
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
#include <reentrant_mutex.h>
|
||||
|
||||
ReentrantMutex::ReentrantMutex() :
|
||||
Mutex(PTHREAD_MUTEX_RECURSIVE)
|
||||
{
|
||||
}
|
||||
|
||||
ReentrantMutex::~ReentrantMutex()
|
||||
{
|
||||
//safely destroyed in ~Mutex();
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
#include <scoped_lock.h>
|
||||
|
||||
ScopedLock::ScopedLock(Mutex& aMutex) :
|
||||
mMutex(aMutex)
|
||||
{
|
||||
mMutex.lock();
|
||||
}
|
||||
|
||||
ScopedLock::~ScopedLock()
|
||||
{
|
||||
mMutex.unlock();
|
||||
}
|
@@ -1,58 +0,0 @@
|
||||
#include <thread_abstraction.h>
|
||||
|
||||
Thread::Thread() :
|
||||
mIsRunning(false),
|
||||
mThread()
|
||||
{
|
||||
}
|
||||
|
||||
Thread::~Thread()
|
||||
{
|
||||
// if thread is still running on object destruction, cancel thread the hard way:
|
||||
if (mIsRunning)
|
||||
{
|
||||
pthread_cancel(mThread);
|
||||
}
|
||||
}
|
||||
|
||||
int Thread::startThread()
|
||||
{
|
||||
mIsRunning = true;
|
||||
return pthread_create(&mThread, 0, &Thread::runThread, this);
|
||||
}
|
||||
|
||||
int Thread::cancelThread()
|
||||
{
|
||||
return pthread_cancel(mThread);
|
||||
mIsRunning = false;
|
||||
}
|
||||
|
||||
int Thread::detachThread()
|
||||
{
|
||||
mIsRunning = false; // thread shall not cancel on object destruction!
|
||||
return pthread_detach(mThread);
|
||||
}
|
||||
|
||||
int Thread::joinThread()
|
||||
{
|
||||
int ret = pthread_join(mThread, 0);
|
||||
mIsRunning = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Thread::setCancelModeDisable()
|
||||
{
|
||||
return pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0);
|
||||
}
|
||||
|
||||
int Thread::setSchedulePriority(int prio)
|
||||
{
|
||||
return pthread_setschedprio(mThread, prio);
|
||||
}
|
||||
|
||||
void* Thread::runThread(void* ptr)
|
||||
{
|
||||
Thread* t = static_cast<Thread*>(ptr);
|
||||
t->run();
|
||||
return 0;
|
||||
}
|
@@ -10,7 +10,8 @@ AM_CPPFLAGS += \
|
||||
AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing
|
||||
|
||||
AM_LDFLAGS = \
|
||||
-L/opt/vc/lib/ -lopenmaxil -lbcm_host -lvcos -lvchiq_arm -lpthread -lrt
|
||||
-L/opt/vc/lib/ -lopenmaxil -lbcm_host -lvcos -lvchiq_arm -lpthread -lrt \
|
||||
-lOpenThreads
|
||||
|
||||
libraspi_la_SOURCES = \
|
||||
hardware_caps.c \
|
||||
|
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <condition_abstraction.h>
|
||||
#include <OpenThreads/Condition>
|
||||
|
||||
#include "glfb.h"
|
||||
#include "bcm_host.h"
|
||||
@@ -47,8 +47,8 @@ static int curr_res;
|
||||
static int pitch;
|
||||
static VC_IMAGE_TYPE_T type = VC_IMAGE_ARGB8888;
|
||||
|
||||
static Mutex blit_mutex;
|
||||
static Condition blit_cond;
|
||||
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 */
|
||||
@@ -71,7 +71,7 @@ GLFramebuffer::GLFramebuffer(int x, int y)
|
||||
si.red.offset = 16;
|
||||
si.transp.offset = 24;
|
||||
|
||||
Thread::start();
|
||||
OpenThreads::Thread::start();
|
||||
while (!ready)
|
||||
usleep(1);
|
||||
}
|
||||
@@ -80,7 +80,7 @@ GLFramebuffer::~GLFramebuffer()
|
||||
{
|
||||
goodbye = true;
|
||||
blit(); /* wake up thread */
|
||||
Thread::join();
|
||||
OpenThreads::Thread::join();
|
||||
}
|
||||
|
||||
void GLFramebuffer::run()
|
||||
|
@@ -17,11 +17,11 @@
|
||||
|
||||
#ifndef __glthread__
|
||||
#define __glthread__
|
||||
#include <thread_abstraction.h>
|
||||
#include <OpenThreads/Thread>
|
||||
#include <vector>
|
||||
#include <linux/fb.h> /* for screeninfo etc. */
|
||||
|
||||
class GLFramebuffer : public Thread
|
||||
class GLFramebuffer : public OpenThreads::Thread
|
||||
{
|
||||
public:
|
||||
GLFramebuffer(int x, int y);
|
||||
@@ -34,7 +34,7 @@ private:
|
||||
void *pdata; /* not yet used */
|
||||
fb_var_screeninfo si;
|
||||
std::vector<unsigned char> osd_buf; /* silly bounce buffer */
|
||||
void run(); /* for Thread */
|
||||
void run(); /* for OpenThreads::Thread */
|
||||
|
||||
void setup();
|
||||
void blit_osd();
|
||||
|
@@ -32,7 +32,7 @@
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <thread_abstraction.h>
|
||||
#include <OpenThreads/Thread>
|
||||
|
||||
#include "init_td.h"
|
||||
#include "lt_debug.h"
|
||||
@@ -69,7 +69,7 @@ static void init_keymap(void)
|
||||
kmap[KEY_F8] = KEY_SLEEP;
|
||||
}
|
||||
|
||||
class Input: public Thread
|
||||
class Input: public OpenThreads::Thread
|
||||
{
|
||||
public:
|
||||
Input();
|
||||
@@ -82,13 +82,13 @@ class Input: public Thread
|
||||
Input::Input()
|
||||
{
|
||||
Init();
|
||||
Thread::start();
|
||||
start();
|
||||
}
|
||||
|
||||
Input::~Input()
|
||||
{
|
||||
running = false;
|
||||
Thread::join();
|
||||
join();
|
||||
}
|
||||
|
||||
static int dirfilter(const struct dirent *d)
|
||||
|
Reference in New Issue
Block a user