mirror of
https://projects.vdr-developer.org/git/vdr-plugin-streamdev.git
synced 2023-10-10 19:16:51 +02:00
Snapshot 2010-09-15
This commit is contained in:
parent
db3274c046
commit
635ccc479f
@ -132,6 +132,10 @@ Norman Thiel
|
|||||||
|
|
||||||
vel_tins
|
vel_tins
|
||||||
for reporting that externremux x264 uses value of ABR for VBR
|
for reporting that externremux x264 uses value of ABR for VBR
|
||||||
|
for various suggestions to improve externremux.sh
|
||||||
|
|
||||||
Matthias Prill
|
Matthias Prill
|
||||||
for reporting a compiler error with older libstdc++ versions
|
for reporting a compiler error with older libstdc++ versions
|
||||||
|
|
||||||
|
Timothy D. Lenz
|
||||||
|
for reporting missing support for invisible channel groups in HTTP menu
|
||||||
|
23
HISTORY
23
HISTORY
@ -1,6 +1,29 @@
|
|||||||
VDR Plugin 'streamdev' Revision History
|
VDR Plugin 'streamdev' Revision History
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
|
- VTP no longer uses a static priority value for its server-side receivers.
|
||||||
|
The server stores channel and priority requested with the PROV command and
|
||||||
|
re-uses these values in a subsequent TUNE for the same channel. The new
|
||||||
|
PRIO command is used to update the receiver's priority if necessary.
|
||||||
|
- added parameter HEIGHT to externremux.sh
|
||||||
|
- fixed syslog messages reporting local instead of remote IP and port
|
||||||
|
- log an error if externremux.sh is missing or not executable
|
||||||
|
- added dsyslog messages to help troubleshouting channel switch issues
|
||||||
|
- VTP command SUSP didn't attach the player to the primary device
|
||||||
|
- replacing a connections receiver is now an atomic operation. Solves
|
||||||
|
stuttering audio/video due to lost TS packets when adding/removing PIDs
|
||||||
|
- fixed missing support for invisible channel groups (groups without name)
|
||||||
|
in HTTP menu (reported by Timothy D. Lenz)
|
||||||
|
- don't quote actual program call in externremux.sh, so you can run th
|
||||||
|
program through e.g. nice or taskset just by extending the variable
|
||||||
|
which holds the program name
|
||||||
|
- in externremux.sh each mencoder audio and video codec has a dedicated
|
||||||
|
variable for a default option string now. Still you can override each
|
||||||
|
default option with an URL parameter
|
||||||
|
- externremux.sh mencoder now uses scale parameter with negative height
|
||||||
|
instead of -xy for scaling (suggested by vel_tins@vdrportal)
|
||||||
|
- added FPS (frames per second) parameter to externremux.sh (suggested by
|
||||||
|
vel_tins@vdrportal)
|
||||||
- don't use std::map.at(). It's not available in older libstdc++ version
|
- don't use std::map.at(). It's not available in older libstdc++ version
|
||||||
(reported by Matthias Prill)
|
(reported by Matthias Prill)
|
||||||
- fixed extremux x264 using value of ABR for VBR (thanks to vel_tins@vdrportal)
|
- fixed extremux x264 using value of ABR for VBR (thanks to vel_tins@vdrportal)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: device.c,v 1.18.2.3 2010/06/08 05:56:15 schmirl Exp $
|
* $Id: device.c,v 1.18.2.4 2010/08/18 10:26:18 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "client/device.h"
|
#include "client/device.h"
|
||||||
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "tools/select.h"
|
#include "tools/select.h"
|
||||||
|
|
||||||
|
#include <vdr/config.h>
|
||||||
#include <vdr/channels.h>
|
#include <vdr/channels.h>
|
||||||
#include <vdr/ringbuffer.h>
|
#include <vdr/ringbuffer.h>
|
||||||
#include <vdr/eit.h>
|
#include <vdr/eit.h>
|
||||||
@ -32,6 +33,7 @@ cStreamdevDevice::cStreamdevDevice(void) {
|
|||||||
|
|
||||||
m_Device = this;
|
m_Device = this;
|
||||||
m_Pids = 0;
|
m_Pids = 0;
|
||||||
|
m_Priority = -1;
|
||||||
m_DvrClosed = true;
|
m_DvrClosed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,6 +121,9 @@ bool cStreamdevDevice::SetChannelDevice(const cChannel *Channel,
|
|||||||
bool LiveView) {
|
bool LiveView) {
|
||||||
Dprintf("SetChannelDevice Channel: %s, LiveView: %s\n", Channel->Name(),
|
Dprintf("SetChannelDevice Channel: %s, LiveView: %s\n", Channel->Name(),
|
||||||
LiveView ? "true" : "false");
|
LiveView ? "true" : "false");
|
||||||
|
LOCK_THREAD;
|
||||||
|
|
||||||
|
m_UpdatePriority = ClientSocket.SupportsPrio();
|
||||||
|
|
||||||
if (LiveView)
|
if (LiveView)
|
||||||
return false;
|
return false;
|
||||||
@ -139,6 +144,8 @@ bool cStreamdevDevice::SetPid(cPidHandle *Handle, int Type, bool On) {
|
|||||||
Handle->used);
|
Handle->used);
|
||||||
LOCK_THREAD;
|
LOCK_THREAD;
|
||||||
|
|
||||||
|
m_UpdatePriority = ClientSocket.SupportsPrio();
|
||||||
|
|
||||||
if (On && !m_TSBuffer) {
|
if (On && !m_TSBuffer) {
|
||||||
Dprintf("SetPid: no data connection -> OpenDvr()");
|
Dprintf("SetPid: no data connection -> OpenDvr()");
|
||||||
OpenDvrInt();
|
OpenDvrInt();
|
||||||
@ -305,3 +312,16 @@ bool cStreamdevDevice::ReInit(void) {
|
|||||||
return StreamdevClientSetup.StartClient ? Init() : true;
|
return StreamdevClientSetup.StartClient ? Init() : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cStreamdevDevice::UpdatePriority(void) {
|
||||||
|
if (m_Device) {
|
||||||
|
m_Device->Lock();
|
||||||
|
if (m_Device->m_UpdatePriority && ClientSocket.DataSocket(siLive)) {
|
||||||
|
int Priority = m_Device->Priority();
|
||||||
|
if (m_Device == cDevice::ActualDevice() && Priority < Setup.PrimaryLimit)
|
||||||
|
Priority = Setup.PrimaryLimit;
|
||||||
|
if (m_Device->m_Priority != Priority && ClientSocket.SetPriority(Priority))
|
||||||
|
m_Device->m_Priority = Priority;
|
||||||
|
}
|
||||||
|
m_Device->Unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: device.h,v 1.7.2.1 2008/04/07 15:07:39 schmirl Exp $
|
* $Id: device.h,v 1.7.2.2 2010/08/18 10:26:18 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEV_DEVICE_H
|
#ifndef VDR_STREAMDEV_DEVICE_H
|
||||||
@ -15,13 +15,14 @@ class cTBString;
|
|||||||
#define CMD_LOCK_OBJ(x) cMutexLock CmdLock((cMutex*)&(x)->m_Mutex)
|
#define CMD_LOCK_OBJ(x) cMutexLock CmdLock((cMutex*)&(x)->m_Mutex)
|
||||||
|
|
||||||
class cStreamdevDevice: public cDevice {
|
class cStreamdevDevice: public cDevice {
|
||||||
friend class cRemoteRecordings;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const cChannel *m_Channel;
|
const cChannel *m_Channel;
|
||||||
cTSBuffer *m_TSBuffer;
|
cTSBuffer *m_TSBuffer;
|
||||||
cStreamdevFilters *m_Filters;
|
cStreamdevFilters *m_Filters;
|
||||||
int m_Pids;
|
int m_Pids;
|
||||||
|
int m_Priority;
|
||||||
|
bool m_UpdatePriority;
|
||||||
bool m_DvrClosed;
|
bool m_DvrClosed;
|
||||||
|
|
||||||
static cStreamdevDevice *m_Device;
|
static cStreamdevDevice *m_Device;
|
||||||
@ -56,6 +57,7 @@ public:
|
|||||||
bool *NeedsDetachReceivers = NULL) const;
|
bool *NeedsDetachReceivers = NULL) const;
|
||||||
virtual bool IsTunedToTransponder(const cChannel *Channel);
|
virtual bool IsTunedToTransponder(const cChannel *Channel);
|
||||||
|
|
||||||
|
static void UpdatePriority(void);
|
||||||
static bool Init(void);
|
static bool Init(void);
|
||||||
static bool ReInit(void);
|
static bool ReInit(void);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: socket.c,v 1.11.2.1 2010/06/08 05:56:15 schmirl Exp $
|
* $Id: socket.c,v 1.11.2.3 2010/08/18 10:26:18 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <tools/select.h>
|
#include <tools/select.h>
|
||||||
@ -21,6 +21,7 @@ cClientSocket ClientSocket;
|
|||||||
cClientSocket::cClientSocket(void)
|
cClientSocket::cClientSocket(void)
|
||||||
{
|
{
|
||||||
memset(m_DataSockets, 0, sizeof(cTBSocket*) * si_Count);
|
memset(m_DataSockets, 0, sizeof(cTBSocket*) * si_Count);
|
||||||
|
m_Prio = false;
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,8 +144,14 @@ bool cClientSocket::CheckConnection(void) {
|
|||||||
if(Command("CAPS FILTERS", 220))
|
if(Command("CAPS FILTERS", 220))
|
||||||
Filters = ",FILTERS";
|
Filters = ",FILTERS";
|
||||||
|
|
||||||
isyslog("Streamdev: Connected to server %s:%d using capabilities TSPIDS%s",
|
const char *Prio = "";
|
||||||
RemoteIp().c_str(), RemotePort(), Filters);
|
if(Command("CAPS PRIO", 220)) {
|
||||||
|
Prio = ",PRIO";
|
||||||
|
m_Prio = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
isyslog("Streamdev: Connected to server %s:%d using capabilities TSPIDS%s%s",
|
||||||
|
RemoteIp().c_str(), RemotePort(), Filters, Prio);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +249,7 @@ bool cClientSocket::SetChannelDevice(const cChannel *Channel) {
|
|||||||
CMD_LOCK;
|
CMD_LOCK;
|
||||||
|
|
||||||
std::string command = (std::string)"TUNE "
|
std::string command = (std::string)"TUNE "
|
||||||
+ (const char*)Channel->GetChannelID().ToString();
|
+ (const char*)Channel->GetChannelID().ToString();
|
||||||
if (!Command(command, 220)) {
|
if (!Command(command, 220)) {
|
||||||
if (errno == 0)
|
if (errno == 0)
|
||||||
esyslog("ERROR: Streamdev: Couldn't tune %s:%d to channel %s",
|
esyslog("ERROR: Streamdev: Couldn't tune %s:%d to channel %s",
|
||||||
@ -252,6 +259,21 @@ bool cClientSocket::SetChannelDevice(const cChannel *Channel) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cClientSocket::SetPriority(int Priority) {
|
||||||
|
if (!CheckConnection()) return false;
|
||||||
|
|
||||||
|
CMD_LOCK;
|
||||||
|
|
||||||
|
std::string command = (std::string)"PRIO " + (const char*)itoa(Priority);
|
||||||
|
if (!Command(command, 220)) {
|
||||||
|
if (errno == 0)
|
||||||
|
esyslog("Streamdev: Failed to update priority on %s:%d", RemoteIp().c_str(),
|
||||||
|
RemotePort());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool cClientSocket::SetPid(int Pid, bool On) {
|
bool cClientSocket::SetPid(int Pid, bool On) {
|
||||||
if (!CheckConnection()) return false;
|
if (!CheckConnection()) return false;
|
||||||
|
|
||||||
@ -260,8 +282,8 @@ bool cClientSocket::SetPid(int Pid, bool On) {
|
|||||||
std::string command = (std::string)(On ? "ADDP " : "DELP ") + (const char*)itoa(Pid);
|
std::string command = (std::string)(On ? "ADDP " : "DELP ") + (const char*)itoa(Pid);
|
||||||
if (!Command(command, 220)) {
|
if (!Command(command, 220)) {
|
||||||
if (errno == 0)
|
if (errno == 0)
|
||||||
esyslog("Streamdev: Pid %d not available from %s:%d", Pid, LocalIp().c_str(),
|
esyslog("Streamdev: Pid %d not available from %s:%d", Pid, RemoteIp().c_str(),
|
||||||
LocalPort());
|
RemotePort());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -277,7 +299,7 @@ bool cClientSocket::SetFilter(ushort Pid, uchar Tid, uchar Mask, bool On) {
|
|||||||
if (!Command(command, 220)) {
|
if (!Command(command, 220)) {
|
||||||
if (errno == 0)
|
if (errno == 0)
|
||||||
esyslog("Streamdev: Filter %hu, %hhu, %hhu not available from %s:%d",
|
esyslog("Streamdev: Filter %hu, %hhu, %hhu not available from %s:%d",
|
||||||
Pid, Tid, Mask, LocalIp().c_str(), LocalPort());
|
Pid, Tid, Mask, RemoteIp().c_str(), RemotePort());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: socket.h,v 1.6.2.1 2010/06/08 05:56:15 schmirl Exp $
|
* $Id: socket.h,v 1.6.2.2 2010/08/18 10:26:18 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEV_CLIENT_CONNECTION_H
|
#ifndef VDR_STREAMDEV_CLIENT_CONNECTION_H
|
||||||
@ -20,6 +20,7 @@ private:
|
|||||||
cTBSocket *m_DataSockets[si_Count];
|
cTBSocket *m_DataSockets[si_Count];
|
||||||
cMutex m_Mutex;
|
cMutex m_Mutex;
|
||||||
char m_Buffer[BUFSIZ + 1]; // various uses
|
char m_Buffer[BUFSIZ + 1]; // various uses
|
||||||
|
bool m_Prio; // server supports command PRIO
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* Send Command, and return true if the command results in Expected.
|
/* Send Command, and return true if the command results in Expected.
|
||||||
@ -45,6 +46,8 @@ public:
|
|||||||
bool CreateDataConnection(eSocketId Id);
|
bool CreateDataConnection(eSocketId Id);
|
||||||
bool CloseDataConnection(eSocketId Id);
|
bool CloseDataConnection(eSocketId Id);
|
||||||
bool SetChannelDevice(const cChannel *Channel);
|
bool SetChannelDevice(const cChannel *Channel);
|
||||||
|
bool SupportsPrio() { return m_Prio; }
|
||||||
|
bool SetPriority(int Priority);
|
||||||
bool SetPid(int Pid, bool On);
|
bool SetPid(int Pid, bool On);
|
||||||
bool SetFilter(ushort Pid, uchar Tid, uchar Mask, bool On);
|
bool SetFilter(ushort Pid, uchar Tid, uchar Mask, bool On);
|
||||||
bool CloseDvr(void);
|
bool CloseDvr(void);
|
||||||
|
2
i18n.h
2
i18n.h
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: i18n.h,v 1.1 2004/12/30 22:43:58 lordjaxom Exp $
|
* $Id: i18n.h,v 1.1.1.1 2004/12/30 22:43:58 lordjaxom Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEV_I18N_H
|
#ifndef VDR_STREAMDEV_I18N_H
|
||||||
|
@ -191,6 +191,11 @@ cTSExt::cTSExt(cRingBufferLinear *ResultBuffer, const cServerConnection *Connect
|
|||||||
if (setpgid(0, 0) == -1)
|
if (setpgid(0, 0) == -1)
|
||||||
esyslog("streamdev-server: externremux setpgid failed: %m");
|
esyslog("streamdev-server: externremux setpgid failed: %m");
|
||||||
|
|
||||||
|
if (access(opt_remux, X_OK) == -1) {
|
||||||
|
esyslog("streamdev-server %s: %m", opt_remux);
|
||||||
|
_exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
if (execle("/bin/sh", "sh", "-c", opt_remux, NULL, env) == -1) {
|
if (execle("/bin/sh", "sh", "-c", opt_remux, NULL, env) == -1) {
|
||||||
esyslog("streamdev-server: externremux script '%s' execution failed: %m", opt_remux);
|
esyslog("streamdev-server: externremux script '%s' execution failed: %m", opt_remux);
|
||||||
_exit(-1);
|
_exit(-1);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: connection.c,v 1.10.2.3 2010/07/19 13:50:14 schmirl Exp $
|
* $Id: connection.c,v 1.10.2.4 2010/08/03 10:56:58 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "server/connection.h"
|
#include "server/connection.h"
|
||||||
@ -254,12 +254,16 @@ cDevice *cServerConnection::GetDevice(const cChannel *Channel, int Priority)
|
|||||||
}
|
}
|
||||||
Dprintf(" * Found device for live tv: %p (%d)\n", newdev,
|
Dprintf(" * Found device for live tv: %p (%d)\n", newdev,
|
||||||
newdev ? newdev->CardIndex() + 1 : 0);
|
newdev ? newdev->CardIndex() + 1 : 0);
|
||||||
if (newdev == NULL || newdev == device)
|
if (newdev == NULL || newdev == device) {
|
||||||
// no suitable device to continue live TV, giving up...
|
// no suitable device to continue live TV, giving up...
|
||||||
device = NULL;
|
device = NULL;
|
||||||
|
dsyslog("streamdev: Not providing channel %s at priority %d - live TV not suspended", Channel->Name(), Priority);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
newdev->SwitchChannel(current, true);
|
newdev->SwitchChannel(current, true);
|
||||||
}
|
}
|
||||||
|
else if (!device)
|
||||||
|
dsyslog("streamdev: No device provides channel %s at priority %d", Channel->Name(), Priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
return device;
|
return device;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: connectionVTP.c,v 1.18.2.7 2010/07/19 13:50:14 schmirl Exp $
|
* $Id: connectionVTP.c,v 1.18.2.9 2010/08/18 10:26:19 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "server/connectionVTP.h"
|
#include "server/connectionVTP.h"
|
||||||
@ -726,6 +726,8 @@ cConnectionVTP::cConnectionVTP(void):
|
|||||||
m_StreamType(stTSPIDS),
|
m_StreamType(stTSPIDS),
|
||||||
m_FiltersSupport(false),
|
m_FiltersSupport(false),
|
||||||
m_RecPlayer(NULL),
|
m_RecPlayer(NULL),
|
||||||
|
m_TuneChannel(NULL),
|
||||||
|
m_TunePriority(0),
|
||||||
m_LSTEHandler(NULL),
|
m_LSTEHandler(NULL),
|
||||||
m_LSTCHandler(NULL),
|
m_LSTCHandler(NULL),
|
||||||
m_LSTTHandler(NULL),
|
m_LSTTHandler(NULL),
|
||||||
@ -816,6 +818,7 @@ bool cConnectionVTP::Command(char *Cmd)
|
|||||||
else if (strcasecmp(Cmd, "READ") == 0) return CmdREAD(param);
|
else if (strcasecmp(Cmd, "READ") == 0) return CmdREAD(param);
|
||||||
else if (strcasecmp(Cmd, "TUNE") == 0) return CmdTUNE(param);
|
else if (strcasecmp(Cmd, "TUNE") == 0) return CmdTUNE(param);
|
||||||
else if (strcasecmp(Cmd, "PLAY") == 0) return CmdPLAY(param);
|
else if (strcasecmp(Cmd, "PLAY") == 0) return CmdPLAY(param);
|
||||||
|
else if (strcasecmp(Cmd, "PRIO") == 0) return CmdPRIO(param);
|
||||||
else if (strcasecmp(Cmd, "ADDP") == 0) return CmdADDP(param);
|
else if (strcasecmp(Cmd, "ADDP") == 0) return CmdADDP(param);
|
||||||
else if (strcasecmp(Cmd, "DELP") == 0) return CmdDELP(param);
|
else if (strcasecmp(Cmd, "DELP") == 0) return CmdDELP(param);
|
||||||
else if (strcasecmp(Cmd, "ADDF") == 0) return CmdADDF(param);
|
else if (strcasecmp(Cmd, "ADDF") == 0) return CmdADDF(param);
|
||||||
@ -874,6 +877,11 @@ bool cConnectionVTP::CmdCAPS(char *Opts)
|
|||||||
return Respond(220, "Capability \"%s\" accepted", Opts);
|
return Respond(220, "Capability \"%s\" accepted", Opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Command PRIO is known
|
||||||
|
if (strcasecmp(Opts, "PRIO") == 0) {
|
||||||
|
return Respond(220, "Capability \"%s\" accepted", Opts);
|
||||||
|
}
|
||||||
|
|
||||||
return Respond(561, "Capability \"%s\" not known", Opts);
|
return Respond(561, "Capability \"%s\" not known", Opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -891,9 +899,15 @@ bool cConnectionVTP::CmdPROV(char *Opts)
|
|||||||
if ((chan = ChannelFromString(Opts)) == NULL)
|
if ((chan = ChannelFromString(Opts)) == NULL)
|
||||||
return Respond(550, "Undefined channel \"%s\"", Opts);
|
return Respond(550, "Undefined channel \"%s\"", Opts);
|
||||||
|
|
||||||
return GetDevice(chan, prio) != NULL
|
if (GetDevice(chan, prio)) {
|
||||||
? Respond(220, "Channel available")
|
m_TuneChannel = chan;
|
||||||
: Respond(560, "Channel not available");
|
m_TunePriority = prio;
|
||||||
|
return Respond(220, "Channel available");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_TuneChannel = NULL;
|
||||||
|
return Respond(560, "Channel not available");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cConnectionVTP::CmdPORT(char *Opts)
|
bool cConnectionVTP::CmdPORT(char *Opts)
|
||||||
@ -1047,18 +1061,23 @@ bool cConnectionVTP::CmdTUNE(char *Opts)
|
|||||||
{
|
{
|
||||||
const cChannel *chan;
|
const cChannel *chan;
|
||||||
cDevice *dev;
|
cDevice *dev;
|
||||||
|
int prio = m_TunePriority;
|
||||||
|
|
||||||
if ((chan = ChannelFromString(Opts)) == NULL)
|
if ((chan = ChannelFromString(Opts)) == NULL)
|
||||||
return Respond(550, "Undefined channel \"%s\"", Opts);
|
return Respond(550, "Undefined channel \"%s\"", Opts);
|
||||||
|
|
||||||
if ((dev = GetDevice(chan, 0)) == NULL)
|
if (chan != m_TuneChannel) {
|
||||||
|
esyslog("streamdev-server TUNE %s: Priority unknown - using 0", Opts);
|
||||||
|
prio = 0;
|
||||||
|
}
|
||||||
|
if ((dev = GetDevice(chan, prio)) == NULL)
|
||||||
return Respond(560, "Channel not available");
|
return Respond(560, "Channel not available");
|
||||||
|
|
||||||
if (!dev->SwitchChannel(chan, false))
|
if (!dev->SwitchChannel(chan, false))
|
||||||
return Respond(560, "Channel not available");
|
return Respond(560, "Channel not available");
|
||||||
|
|
||||||
delete m_LiveStreamer;
|
delete m_LiveStreamer;
|
||||||
m_LiveStreamer = new cStreamdevLiveStreamer(1, this);
|
m_LiveStreamer = new cStreamdevLiveStreamer(prio, this);
|
||||||
m_LiveStreamer->SetChannel(chan, m_StreamType);
|
m_LiveStreamer->SetChannel(chan, m_StreamType);
|
||||||
m_LiveStreamer->SetDevice(dev);
|
m_LiveStreamer->SetDevice(dev);
|
||||||
if(m_LiveSocket)
|
if(m_LiveSocket)
|
||||||
@ -1099,6 +1118,22 @@ bool cConnectionVTP::CmdPLAY(char *Opts)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cConnectionVTP::CmdPRIO(char *Opts)
|
||||||
|
{
|
||||||
|
int prio;
|
||||||
|
char *end;
|
||||||
|
|
||||||
|
prio = strtoul(Opts, &end, 10);
|
||||||
|
if (end == Opts || (*end != '\0' && *end != ' '))
|
||||||
|
return Respond(500, "Use: PRIO Priority");
|
||||||
|
|
||||||
|
if (m_LiveStreamer) {
|
||||||
|
m_LiveStreamer->SetPriority(prio);
|
||||||
|
return Respond(220, "Priority changed to %d", prio);
|
||||||
|
}
|
||||||
|
return Respond(550, "Priority not applicable");
|
||||||
|
}
|
||||||
|
|
||||||
bool cConnectionVTP::CmdADDP(char *Opts)
|
bool cConnectionVTP::CmdADDP(char *Opts)
|
||||||
{
|
{
|
||||||
int pid;
|
int pid;
|
||||||
@ -1223,6 +1258,7 @@ bool cConnectionVTP::CmdSUSP(void)
|
|||||||
else if (StreamdevServerSetup.SuspendMode == smOffer
|
else if (StreamdevServerSetup.SuspendMode == smOffer
|
||||||
&& StreamdevServerSetup.AllowSuspend) {
|
&& StreamdevServerSetup.AllowSuspend) {
|
||||||
cControl::Launch(new cSuspendCtl);
|
cControl::Launch(new cSuspendCtl);
|
||||||
|
cControl::Attach();
|
||||||
return Respond(220, "Server is suspended");
|
return Respond(220, "Server is suspended");
|
||||||
} else
|
} else
|
||||||
return Respond(550, "Client may not suspend server");
|
return Respond(550, "Client may not suspend server");
|
||||||
|
@ -31,6 +31,11 @@ private:
|
|||||||
bool m_FiltersSupport;
|
bool m_FiltersSupport;
|
||||||
RecPlayer *m_RecPlayer;
|
RecPlayer *m_RecPlayer;
|
||||||
|
|
||||||
|
// Priority is only known in PROV command
|
||||||
|
// Store in here for later use in TUNE call
|
||||||
|
const cChannel *m_TuneChannel;
|
||||||
|
int m_TunePriority;
|
||||||
|
|
||||||
// Members adopted for SVDRP
|
// Members adopted for SVDRP
|
||||||
cLSTEHandler *m_LSTEHandler;
|
cLSTEHandler *m_LSTEHandler;
|
||||||
cLSTCHandler *m_LSTCHandler;
|
cLSTCHandler *m_LSTCHandler;
|
||||||
@ -59,6 +64,7 @@ public:
|
|||||||
bool CmdREAD(char *Opts);
|
bool CmdREAD(char *Opts);
|
||||||
bool CmdTUNE(char *Opts);
|
bool CmdTUNE(char *Opts);
|
||||||
bool CmdPLAY(char *Opts);
|
bool CmdPLAY(char *Opts);
|
||||||
|
bool CmdPRIO(char *Opts);
|
||||||
bool CmdADDP(char *Opts);
|
bool CmdADDP(char *Opts);
|
||||||
bool CmdDELP(char *Opts);
|
bool CmdDELP(char *Opts);
|
||||||
bool CmdADDF(char *Opts);
|
bool CmdADDF(char *Opts);
|
||||||
|
@ -297,7 +297,7 @@ void cStreamdevPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, i
|
|||||||
if (written != TS_SIZE)
|
if (written != TS_SIZE)
|
||||||
siBuffer.ReportOverflow(TS_SIZE - written);
|
siBuffer.ReportOverflow(TS_SIZE - written);
|
||||||
if (pmtPid != prevPmtPid) {
|
if (pmtPid != prevPmtPid) {
|
||||||
m_Streamer->SetPids(pmtPid);
|
m_Streamer->SetPid(pmtPid, true);
|
||||||
Add(pmtPid, 0x02);
|
Add(pmtPid, 0x02);
|
||||||
pmtVersion = -1;
|
pmtVersion = -1;
|
||||||
}
|
}
|
||||||
@ -442,21 +442,28 @@ bool cStreamdevLiveStreamer::SetPids(int Pid, const int *Pids1, const int *Pids2
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cStreamdevLiveStreamer::SetPriority(int Priority)
|
||||||
|
{
|
||||||
|
m_Priority = Priority;
|
||||||
|
StartReceiver();
|
||||||
|
}
|
||||||
|
|
||||||
void cStreamdevLiveStreamer::StartReceiver(void)
|
void cStreamdevLiveStreamer::StartReceiver(void)
|
||||||
{
|
{
|
||||||
DELETENULL(m_Receiver);
|
if (m_Device != NULL && m_NumPids > 0 && IsRunning()) {
|
||||||
if (m_NumPids > 0) {
|
|
||||||
Dprintf("Creating Receiver to respect changed pids\n");
|
Dprintf("Creating Receiver to respect changed pids\n");
|
||||||
|
cReceiver *current = m_Receiver;
|
||||||
#if VDRVERSNUM < 10500
|
#if VDRVERSNUM < 10500
|
||||||
m_Receiver = new cStreamdevLiveReceiver(this, m_Channel->Ca(), m_Priority, m_Pids);
|
m_Receiver = new cStreamdevLiveReceiver(this, m_Channel->Ca(), m_Priority, m_Pids);
|
||||||
#else
|
#else
|
||||||
m_Receiver = new cStreamdevLiveReceiver(this, m_Channel->GetChannelID(), m_Priority, m_Pids);
|
m_Receiver = new cStreamdevLiveReceiver(this, m_Channel->GetChannelID(), m_Priority, m_Pids);
|
||||||
#endif
|
#endif
|
||||||
if (IsRunning() && m_Device != NULL) {
|
cThreadLock ThreadLock(m_Device);
|
||||||
Dprintf("Attaching new receiver\n");
|
Attach();
|
||||||
Attach();
|
delete current;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
DELETENULL(m_Receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cStreamdevLiveStreamer::SetChannel(const cChannel *Channel, eStreamType StreamType, const int* Apid, const int *Dpid)
|
bool cStreamdevLiveStreamer::SetChannel(const cChannel *Channel, eStreamType StreamType, const int* Apid, const int *Dpid)
|
||||||
|
@ -38,6 +38,7 @@ public:
|
|||||||
bool SetPid(int Pid, bool On);
|
bool SetPid(int Pid, bool On);
|
||||||
bool SetPids(int Pid, const int *Pids1 = NULL, const int *Pids2 = NULL, const int *Pids3 = NULL);
|
bool SetPids(int Pid, const int *Pids1 = NULL, const int *Pids2 = NULL, const int *Pids3 = NULL);
|
||||||
bool SetChannel(const cChannel *Channel, eStreamType StreamType, const int* Apid = NULL, const int* Dpid = NULL);
|
bool SetChannel(const cChannel *Channel, eStreamType StreamType, const int* Apid = NULL, const int* Dpid = NULL);
|
||||||
|
void SetPriority(int Priority);
|
||||||
|
|
||||||
virtual int Put(const uchar *Data, int Count);
|
virtual int Put(const uchar *Data, int Count);
|
||||||
virtual uchar *Get(int &Count);
|
virtual uchar *Get(int &Count);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#include "server/menuHTTP.h"
|
#include "server/menuHTTP.h"
|
||||||
|
|
||||||
//**************************** cChannelIterator **************
|
//**************************** cChannelIterator **************
|
||||||
cChannelIterator::cChannelIterator(cChannel *First): channel(First)
|
cChannelIterator::cChannelIterator(const cChannel *First): channel(First)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
const cChannel* cChannelIterator::Next()
|
const cChannel* cChannelIterator::Next()
|
||||||
@ -19,7 +19,7 @@ cListAll::cListAll(): cChannelIterator(Channels.First())
|
|||||||
const cChannel* cListAll::NextChannel(const cChannel *Channel)
|
const cChannel* cListAll::NextChannel(const cChannel *Channel)
|
||||||
{
|
{
|
||||||
if (Channel)
|
if (Channel)
|
||||||
Channel = Channels.Next(Channel);
|
Channel = SkipFakeGroups(Channels.Next(Channel));
|
||||||
return Channel;
|
return Channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,14 +46,19 @@ const cChannel* cListGroups::NextChannel(const cChannel *Channel)
|
|||||||
}
|
}
|
||||||
//
|
//
|
||||||
// ********************* cListGroup ****************
|
// ********************* cListGroup ****************
|
||||||
cListGroup::cListGroup(const cChannel *Group): cChannelIterator((Group && Group->GroupSep() && Channels.Next(Group) && !Channels.Next(Group)->GroupSep()) ? Channels.Next(Group) : NULL)
|
cListGroup::cListGroup(const cChannel *Group): cChannelIterator(GetNextChannelInGroup(Group))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
const cChannel* cListGroup::GetNextChannelInGroup(const cChannel *Channel)
|
||||||
|
{
|
||||||
|
if (Channel)
|
||||||
|
Channel = SkipFakeGroups(Channels.Next(Channel));
|
||||||
|
return Channel && !Channel->GroupSep() ? Channel : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
const cChannel* cListGroup::NextChannel(const cChannel *Channel)
|
const cChannel* cListGroup::NextChannel(const cChannel *Channel)
|
||||||
{
|
{
|
||||||
if (Channel)
|
return GetNextChannelInGroup(Channel);
|
||||||
Channel = Channels.Next(Channel);
|
|
||||||
return (Channel && !Channel->GroupSep()) ? Channel : NULL;
|
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// ********************* cListTree ****************
|
// ********************* cListTree ****************
|
||||||
@ -68,7 +73,7 @@ const cChannel* cListTree::NextChannel(const cChannel *Channel)
|
|||||||
if (currentGroup == selectedGroup)
|
if (currentGroup == selectedGroup)
|
||||||
{
|
{
|
||||||
if (Channel)
|
if (Channel)
|
||||||
Channel = Channels.Next(Channel);
|
Channel = SkipFakeGroups(Channels.Next(Channel));
|
||||||
if (Channel && Channel->GroupSep())
|
if (Channel && Channel->GroupSep())
|
||||||
currentGroup = Channel;
|
currentGroup = Channel;
|
||||||
}
|
}
|
||||||
|
@ -13,9 +13,10 @@ class cChannelIterator
|
|||||||
const cChannel *channel;
|
const cChannel *channel;
|
||||||
protected:
|
protected:
|
||||||
virtual const cChannel* NextChannel(const cChannel *Channel) = 0;
|
virtual const cChannel* NextChannel(const cChannel *Channel) = 0;
|
||||||
|
static inline const cChannel* SkipFakeGroups(const cChannel *Channel);
|
||||||
public:
|
public:
|
||||||
const cChannel* Next();
|
const cChannel* Next();
|
||||||
cChannelIterator(cChannel *First);
|
cChannelIterator(const cChannel *First);
|
||||||
virtual ~cChannelIterator() {};
|
virtual ~cChannelIterator() {};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -48,6 +49,8 @@ class cListGroups: public cChannelIterator
|
|||||||
|
|
||||||
class cListGroup: public cChannelIterator
|
class cListGroup: public cChannelIterator
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
static const cChannel* GetNextChannelInGroup(const cChannel *Channel);
|
||||||
protected:
|
protected:
|
||||||
virtual const cChannel* NextChannel(const cChannel *Channel);
|
virtual const cChannel* NextChannel(const cChannel *Channel);
|
||||||
public:
|
public:
|
||||||
@ -155,4 +158,11 @@ class cM3uChannelList: public cChannelList
|
|||||||
virtual ~cM3uChannelList();
|
virtual ~cM3uChannelList();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline const cChannel* cChannelIterator::SkipFakeGroups(const cChannel* Group)
|
||||||
|
{
|
||||||
|
while (Group && Group->GroupSep() && !*Group->Name())
|
||||||
|
Group = Channels.Next(Group);
|
||||||
|
return Group;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* See the README file for copyright information and how to reach the author.
|
* See the README file for copyright information and how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: streamdev-client.c,v 1.5.2.1 2010/06/08 05:56:14 schmirl Exp $
|
* $Id: streamdev-client.c,v 1.5.2.2 2010/08/18 10:26:18 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "streamdev-client.h"
|
#include "streamdev-client.h"
|
||||||
@ -56,4 +56,8 @@ bool cPluginStreamdevClient::SetupParse(const char *Name, const char *Value) {
|
|||||||
return StreamdevClientSetup.SetupParse(Name, Value);
|
return StreamdevClientSetup.SetupParse(Name, Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cPluginStreamdevClient::MainThreadHook(void) {
|
||||||
|
cStreamdevDevice::UpdatePriority();
|
||||||
|
}
|
||||||
|
|
||||||
VDRPLUGINCREATOR(cPluginStreamdevClient); // Don't touch this!
|
VDRPLUGINCREATOR(cPluginStreamdevClient); // Don't touch this!
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: streamdev-client.h,v 1.1.1.1.2.1 2010/06/08 05:56:14 schmirl Exp $
|
* $Id: streamdev-client.h,v 1.1.1.1.2.2 2010/08/18 10:26:18 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEVCLIENT_H
|
#ifndef VDR_STREAMDEVCLIENT_H
|
||||||
@ -23,6 +23,7 @@ public:
|
|||||||
virtual cOsdObject *MainMenuAction(void);
|
virtual cOsdObject *MainMenuAction(void);
|
||||||
virtual cMenuSetupPage *SetupMenu(void);
|
virtual cMenuSetupPage *SetupMenu(void);
|
||||||
virtual bool SetupParse(const char *Name, const char *Value);
|
virtual bool SetupParse(const char *Name, const char *Value);
|
||||||
|
virtual void MainThreadHook(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VDR_STREAMDEVCLIENT_H
|
#endif // VDR_STREAMDEVCLIENT_H
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
# VBR video bitrate (kbit)
|
# VBR video bitrate (kbit)
|
||||||
# VOPTS custom video options
|
# VOPTS custom video options
|
||||||
# WIDTH scale video to width
|
# WIDTH scale video to width
|
||||||
|
# HEIGHT scale video to height
|
||||||
|
# FPS output frames per second
|
||||||
# AC audio codec
|
# AC audio codec
|
||||||
# ABR audio bitrate (kbit)
|
# ABR audio bitrate (kbit)
|
||||||
# AOPTS custom audio options
|
# AOPTS custom audio options
|
||||||
@ -42,14 +44,22 @@ ABR_MONO=64
|
|||||||
###
|
###
|
||||||
# mencoder binary
|
# mencoder binary
|
||||||
MENCODER=mencoder
|
MENCODER=mencoder
|
||||||
|
### video part
|
||||||
# Default video codec (e.g. lavc/x264/copy)
|
# Default video codec (e.g. lavc/x264/copy)
|
||||||
MENCODER_VC=lavc
|
MENCODER_VC=lavc
|
||||||
|
# Default video options if lavc is used (-ovc lavc -lavcopts ...)
|
||||||
|
MENCODER_LAVC_VOPTS=vcodec=mpeg4
|
||||||
|
# Default video options if x264 is used (-ovc x264 -x264encopts ...)
|
||||||
|
MENCODER_X264_VOPTS=threads=auto
|
||||||
|
### audio part
|
||||||
# Default audio codec (e.g. lavc/mp3lame/faac/copy)
|
# Default audio codec (e.g. lavc/mp3lame/faac/copy)
|
||||||
MENCODER_AC=mp3lame
|
MENCODER_AC=mp3lame
|
||||||
# Default video codec if lavc is used (-ovc lavc -lavcopts vcodec=)
|
# Default audio options if lavc is used (-oac lavc -lavcopts ...)
|
||||||
MENCODER_LAVC_VC=mpeg4
|
MENCODER_LAVC_AOPTS=acodec=mp2
|
||||||
# Default audio codec if lavc is used (-oac lavc -lavcopts acodec=)
|
# Default audio options if mp3lame is used (-oac mp3lame -lameopts ...)
|
||||||
MENCODER_LAVC_AC=mp2
|
MENCODER_LAME_AOPTS=
|
||||||
|
# Default audio options if faac is used (-oac faac -faacopts ...)
|
||||||
|
MENCODER_FAAC_AOPTS=
|
||||||
###
|
###
|
||||||
### MENCODER CONFIG END
|
### MENCODER CONFIG END
|
||||||
|
|
||||||
@ -63,6 +73,8 @@ OGG_SPEED=1
|
|||||||
OGG_VQUALITY=0
|
OGG_VQUALITY=0
|
||||||
# audioquality - higher value gives better quality but is slower (0..10)
|
# audioquality - higher value gives better quality but is slower (0..10)
|
||||||
OGG_AQUALITY=0
|
OGG_AQUALITY=0
|
||||||
|
# aspect ratio used for scaling if only one of HEIGHT/WIDTH given (16/9 or 4/3)
|
||||||
|
OGG_ASPECT='4 / 3'
|
||||||
###
|
###
|
||||||
### OGG CONFIG END
|
### OGG CONFIG END
|
||||||
|
|
||||||
@ -70,7 +82,19 @@ OGG_AQUALITY=0
|
|||||||
|
|
||||||
function hasOpt { echo "$1" | grep -q "\b${2}\b"; }
|
function hasOpt { echo "$1" | grep -q "\b${2}\b"; }
|
||||||
|
|
||||||
function isNumeric() { echo "$@" | grep -q '^[0-9]\{1,\}$'; }
|
# $1: concatenation of already set option=value pairs
|
||||||
|
# $2-$n: option=value pairs to be echod if the option is not present in $1
|
||||||
|
function addOpts
|
||||||
|
{
|
||||||
|
local opts="$1"
|
||||||
|
shift
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
hasOpt "$opts" ${1%%=*}= || echo $1
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function isNumeric() { echo "$@" | grep -q '^-\?[0-9]\{1,\}$'; }
|
||||||
|
|
||||||
function remux_cat
|
function remux_cat
|
||||||
{
|
{
|
||||||
@ -87,20 +111,31 @@ function remux_mencoder
|
|||||||
# Assemble video options
|
# Assemble video options
|
||||||
VC=${REMUX_PARAM_VC:-$MENCODER_VC}
|
VC=${REMUX_PARAM_VC:-$MENCODER_VC}
|
||||||
VOPTS=${REMUX_PARAM_VOPTS}
|
VOPTS=${REMUX_PARAM_VOPTS}
|
||||||
WIDTH=${REMUX_PARAM_WIDTH:-$WIDTH}
|
FPS=${REMUX_PARAM_FPS:-$FPS}
|
||||||
|
|
||||||
|
# if only one of HEIGHT/WIDTH given:
|
||||||
|
# have mencoder calculate other value depending on actual aspect ratio
|
||||||
|
if [ "$HEIGHT" -a -z "$WIDTH" ]; then
|
||||||
|
WIDTH=-3
|
||||||
|
elif [ "$WIDTH" -a -z "$HEIGHT" ]; then
|
||||||
|
HEIGHT=-3
|
||||||
|
fi
|
||||||
|
|
||||||
case "$VC" in
|
case "$VC" in
|
||||||
lavc)
|
lavc)
|
||||||
LAVCOPTS=(
|
LAVCOPTS=(
|
||||||
${VOPTS}
|
${VOPTS}
|
||||||
$(hasOpt "$VOPTS" vcodec || echo "vcodec=$MENCODER_LAVC_VC")
|
$(IFS=$IFS:; addOpts "$VOPTS" $MENCODER_LAVC_VOPTS)
|
||||||
${VBR:+vbitrate=$VBR}
|
${VBR:+vbitrate=$VBR}
|
||||||
)
|
)
|
||||||
[ ${#LAVCOPTS[*]} -gt 0 ] && VOPTS=$(IFS=:; echo -lavcopts "${LAVCOPTS[*]}")
|
[ ${#LAVCOPTS[*]} -gt 0 ] && VOPTS=$(IFS=:; echo -lavcopts "${LAVCOPTS[*]}")
|
||||||
;;
|
;;
|
||||||
x264)
|
x264)
|
||||||
|
isNumeric "$HEIGHT" && [ $HEIGHT -lt 0 -a $HEIGHT -gt -8 ] && ((HEIGHT-=8))
|
||||||
|
isNumeric "$WIDTH" && [ $WIDTH -lt 0 -a $WIDTH -gt -8 ] && ((WIDTH-=8))
|
||||||
X264OPTS=(
|
X264OPTS=(
|
||||||
${VOPTS}
|
${VOPTS}
|
||||||
$(hasOpt "$VOPTS" threads || echo "threads=auto")
|
$(IFS=$IFS:; addOpts "$VOPTS" $MENCODER_X264_VOPTS)
|
||||||
${VBR:+bitrate=$VBR}
|
${VBR:+bitrate=$VBR}
|
||||||
)
|
)
|
||||||
[ ${#X264OPTS[*]} -gt 0 ] && VOPTS=$(IFS=:; echo -x264encopts "${X264OPTS[*]}")
|
[ ${#X264OPTS[*]} -gt 0 ] && VOPTS=$(IFS=:; echo -x264encopts "${X264OPTS[*]}")
|
||||||
@ -121,7 +156,7 @@ function remux_mencoder
|
|||||||
LAVCOPTS=(
|
LAVCOPTS=(
|
||||||
${LAVCOPTS[*]}
|
${LAVCOPTS[*]}
|
||||||
${AOPTS}
|
${AOPTS}
|
||||||
$(hasOpt "$AOPTS" acodec || echo "acodec=$MENCODER_LAVC_AC")
|
$(IFS=$IFS:; addOpts "$AOPTS" $MENCODER_LAVC_AOPTS)
|
||||||
${ABR:+abitrate=$ABR}
|
${ABR:+abitrate=$ABR}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -133,6 +168,7 @@ function remux_mencoder
|
|||||||
LAMEOPTS=(
|
LAMEOPTS=(
|
||||||
${AOPTS}
|
${AOPTS}
|
||||||
$(isNumeric "${ABR}" && [ "${ABR}" -lt "$ABR_MONO" ] && ! hasOpt "${AOPTS}" mode ] && echo 'mode=3')
|
$(isNumeric "${ABR}" && [ "${ABR}" -lt "$ABR_MONO" ] && ! hasOpt "${AOPTS}" mode ] && echo 'mode=3')
|
||||||
|
$(IFS=$IFS:; addOpts "$AOPTS" $MENCODER_LAME_AOPTS)
|
||||||
${ABR:+preset=$ABR}
|
${ABR:+preset=$ABR}
|
||||||
)
|
)
|
||||||
[ ${#LAMEOPTS[*]} -gt 0 ] && AOPTS=$(IFS=:; echo -lameopts "${LAMEOPTS[*]}")
|
[ ${#LAMEOPTS[*]} -gt 0 ] && AOPTS=$(IFS=:; echo -lameopts "${LAMEOPTS[*]}")
|
||||||
@ -140,6 +176,7 @@ function remux_mencoder
|
|||||||
faac)
|
faac)
|
||||||
FAACOPTS=(
|
FAACOPTS=(
|
||||||
${AOPTS}
|
${AOPTS}
|
||||||
|
$(IFS=$IFS:; addOpts "$AOPTS" $MENCODER_FAAC_AOPTS)
|
||||||
${ABR:+br=$ABR}
|
${ABR:+br=$ABR}
|
||||||
)
|
)
|
||||||
[ ${#FAACOPTS[*]} -gt 0 ] && AOPTS=$(IFS=:; echo -faacopts "${FAACOPTS[*]}")
|
[ ${#FAACOPTS[*]} -gt 0 ] && AOPTS=$(IFS=:; echo -faacopts "${FAACOPTS[*]}")
|
||||||
@ -155,15 +192,17 @@ function remux_mencoder
|
|||||||
|
|
||||||
startReply
|
startReply
|
||||||
exec 3<&0
|
exec 3<&0
|
||||||
echo "$MENCODER" \
|
echo $MENCODER \
|
||||||
-ovc $VC $VOPTS \
|
-ovc $VC $VOPTS \
|
||||||
-oac $AC $AOPTS \
|
-oac $AC $AOPTS \
|
||||||
${WIDTH:+-vf scale -zoom -xy $WIDTH} \
|
${WIDTH:+-vf scale=$WIDTH:$HEIGHT -zoom} \
|
||||||
|
${FPS:+-ofps $FPS} \
|
||||||
-o "$FIFO" -- - >&2
|
-o "$FIFO" -- - >&2
|
||||||
"$MENCODER" \
|
$MENCODER \
|
||||||
-ovc $VC $VOPTS \
|
-ovc $VC $VOPTS \
|
||||||
-oac $AC $AOPTS \
|
-oac $AC $AOPTS \
|
||||||
${WIDTH:+-vf scale -zoom -xy $WIDTH} \
|
${WIDTH:+-vf scale=$WIDTH:$HEIGHT -zoom} \
|
||||||
|
${FPS:+-ofps $FPS} \
|
||||||
-o "$FIFO" -- - 0<&3 >/dev/null &
|
-o "$FIFO" -- - 0<&3 >/dev/null &
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +210,15 @@ function remux_ogg
|
|||||||
{
|
{
|
||||||
VOPTS=${REMUX_PARAM_VOPTS//[:=]/ }
|
VOPTS=${REMUX_PARAM_VOPTS//[:=]/ }
|
||||||
AOPTS=${REMUX_PARAM_AOPTS//[:=]/ }
|
AOPTS=${REMUX_PARAM_AOPTS//[:=]/ }
|
||||||
WIDTH=${REMUX_PARAM_WIDTH:-$WIDTH}
|
|
||||||
|
# if only one of HEIGHT/WIDTH given:
|
||||||
|
# calculate other value depending on configured aspect ratio
|
||||||
|
# trim to multiple of 8
|
||||||
|
if [ "$HEIGHT" -a -z "$WIDTH" ]; then
|
||||||
|
WIDTH=$((HEIGHT * $OGG_ASPECT / 8 * 8))
|
||||||
|
elif [ "$WIDTH" -a -z "$HEIGHT" ]; then
|
||||||
|
HEIGHT=$(($WIDTH * $( echo $OGG_ASPECT | sed 's#^\([0-9]\+\) */ *\([0-9]\+\)$#\2 / \1#') / 8 * 8))
|
||||||
|
fi
|
||||||
|
|
||||||
OGGOPTS=(
|
OGGOPTS=(
|
||||||
${VOPTS}
|
${VOPTS}
|
||||||
@ -187,14 +234,14 @@ function remux_ogg
|
|||||||
|
|
||||||
startReply
|
startReply
|
||||||
exec 3<&0
|
exec 3<&0
|
||||||
echo "$OGG" --format ts \
|
echo $OGG --format ts \
|
||||||
${OGGOPTS[*]} \
|
${OGGOPTS[*]} \
|
||||||
${WIDTH:+--width $WIDTH --height $(($WIDTH * 3 / 4 / 8 * 8))} \
|
${WIDTH:+--width $WIDTH --height $HEIGHT} \
|
||||||
--title "VDR Streamdev: ${REMUX_CHANNEL_NAME}" \
|
--title "VDR Streamdev: ${REMUX_CHANNEL_NAME}" \
|
||||||
--output "$FIFO" -- - 0<&3 >&2
|
--output "$FIFO" -- - 0<&3 >&2
|
||||||
"$OGG" --format ts \
|
$OGG --format ts \
|
||||||
${OGGOPTS[*]} \
|
${OGGOPTS[*]} \
|
||||||
${WIDTH:+--width $WIDTH --height $(($WIDTH * 3 / 4 / 8 * 8))} \
|
${WIDTH:+--width $WIDTH --height $HEIGHT} \
|
||||||
--title "VDR Streamdev: ${REMUX_CHANNEL_NAME}" \
|
--title "VDR Streamdev: ${REMUX_CHANNEL_NAME}" \
|
||||||
--output "$FIFO" -- - 0<&3 >/dev/null &
|
--output "$FIFO" -- - 0<&3 >/dev/null &
|
||||||
}
|
}
|
||||||
@ -254,6 +301,7 @@ esac
|
|||||||
ABR=${REMUX_PARAM_ABR:-$ABR}
|
ABR=${REMUX_PARAM_ABR:-$ABR}
|
||||||
VBR=${REMUX_PARAM_VBR:-$VBR}
|
VBR=${REMUX_PARAM_VBR:-$VBR}
|
||||||
WIDTH=${REMUX_PARAM_WIDTH:-$WIDTH}
|
WIDTH=${REMUX_PARAM_WIDTH:-$WIDTH}
|
||||||
|
HEIGHT=${REMUX_PARAM_HEIGHT:-$HEIGHT}
|
||||||
PROG=${REMUX_PARAM_PROG:-$PROG}
|
PROG=${REMUX_PARAM_PROG:-$PROG}
|
||||||
|
|
||||||
case "$PROG" in
|
case "$PROG" in
|
||||||
|
Loading…
Reference in New Issue
Block a user