Skip to content

Commit 4eb22df

Browse files
committed
- some refactoring
- introduce vlc as additional handler beside ffmepg - new channel parameter H=V or H=F to set the handler to vlc or ffmpeg. Default is ffmpeg.
1 parent 14eeddf commit 4eb22df

31 files changed

+461
-271
lines changed

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ OBJS = $(PLUGIN).o common.o config.o device.o pidscanner.o \
7979
protocolcurl.o protocolext.o protocolfile.o protocolhttp.o \
8080
protocoludp.o sectionfilter.o setup.o sidscanner.o socket.o \
8181
protocolm3u.o protocolradio.o protocolstream.o \
82-
m3u8handler.o process.o process_unix.o ffmpeghandler.o \
83-
source.o statistics.o streamer.o
82+
m3u8handler.o process.o process_unix.o ffmpeghandler.o streambasehandler.o \
83+
vlchandler.o source.o statistics.o streamer.o
8484

8585
### The main target:
8686

README

+15-9
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ Configuration:
8585

8686
- channels.conf
8787

88-
TV8;IPTV:70:S=1|P=0|F=M3U|U=other.cfg|A=2|Y=1:I:0:200:201,202,203,204,205:0:0:11:1:100:0
89-
ST1:IPTV:90:S=1|P=0|F=STREAM|U=http%3A//locahost/stream?id=10|A=1:I:0:514:670:2321:0:5:0:200:0
88+
TV8;IPTV:70:S=1|P=0|F=M3U|U=other.cfg|A=2|Y=1|H=F:I:0:200:201,202,203,204,205:0:0:11:1:100:0
89+
ST1:IPTV:90:S=1|P=0|F=STREAM|U=http%3A//locahost/stream?id=10|A=1|H=V:I:0:514:670:2321:0:5:0:200:0
9090
RD1:IPTV:80:S=1|P=0|F=RADIO|U=http%3A//wdr-1live-live.icecast.wdr.de/wdr/1live/live/mp3/128/stream.mp3|A=8:I:0:270:271,272,273,274,275:0:0:8:1:9:8
9191
TV7;IPTV:70:S=1|P=0|F=M3U|U=list1.cfg|A=5:I:0:200:201,202,203,204,205:0:0:11:1:100:0
9292
TV6;IPTV:60:S=1|P=0|F=EXT|U=iptvstream.sh|A=0:I:0:0:680:0:0:6:0:0:0
@@ -99,13 +99,19 @@ Configuration:
9999
| | | | | | |
100100
| | | | | | Source type ("I")
101101
| | | | | Stream parameter
102-
| | | | | UDP: multicast port
103-
| | | | | CURL: <<to be defined>>
104-
| | | | | HTTP: HTTP port number
105-
| | | | | FILE: file delay (ms)
106-
| | | | | EXT: script parameter
107-
| | | | | M3U: Y=1 uses yt-dlp to determine the video URL
108-
| | | | | Y=2 tries to find the video URL internally
102+
| | | | | UDP: multicast port
103+
| | | | | CURL: <<to be defined>>
104+
| | | | | HTTP: HTTP port number
105+
| | | | | FILE: file delay (ms)
106+
| | | | | EXT: script parameter
107+
| | | | | M3U: Y=1 uses yt-dlp to determine the video URL
108+
| | | | | Y=2 tries to find the video URL internally
109+
| | | | | H=F uses ffmpeg
110+
| | | | | H=V uses vlc
111+
| | | | | STREAM: H=F uses ffmpeg
112+
| | | | | H=V uses vlc
113+
| | | | | RADIO: H=F uses ffmpeg
114+
| | | | | H=V uses vlc
109115
| | | | Stream address
110116
| | | | UDP: multicast [source@]group address
111117
| | | | CURL: HTTP/HTTPS URL; colons (%3A) and pipes (%7C) shall be URL encoded

common.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
*
66
*/
77

8-
#include <ctype.h>
8+
#include <cctype>
9+
#include <memory>
10+
#include <string>
11+
#include <stdexcept>
912
#include <vdr/tools.h>
1013
#include "common.h"
1114

device.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,7 @@ bool cIptvDevice::SetChannelDevice(const cChannel *channelP, bool liveViewP) {
328328
pidScanEnabledM = itp.PidScan()!=0;
329329

330330
if (pIptvStreamerM &&
331-
pIptvStreamerM->SetSource(itp.Address(), itp.Parameter(), deviceIndexM, protocol, channelP->Number(),
332-
itp.UseYtdlp())) {
331+
pIptvStreamerM->SetSource(protocol, { itp.Address(), itp.Parameter(), deviceIndexM, channelP->Number(), itp.UseYtdlp(), itp.HandlerType() })) {
333332
channelM = *channelP;
334333

335334
if (sidScanEnabledM && pSidScannerM && IptvConfig.GetSectionFiltering()) {

ffmpeghandler.cpp

+2-129
Original file line numberDiff line numberDiff line change
@@ -32,40 +32,15 @@
3232
*/
3333

3434
#include <string>
35-
#include <chrono>
3635
#include <iterator>
3736
#include "ffmpeghandler.h"
3837
#include "log.h"
3938
#include "config.h"
4039

41-
/* disabled until a better solution is found
42-
std::thread audioUpdate;
43-
44-
void performAudioInfoUpdate(m3u_stream stream) {
45-
int tries = 10;
46-
47-
auto device = cDevice::PrimaryDevice();
48-
49-
int ms = 500;
50-
while (tries > 0) {
51-
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
52-
53-
for (unsigned long i = 0; i < stream.audio.size(); ++i) {
54-
device->SetAvailableTrack(eTrackType::ttAudio, i, 0, stream.audio[i].language.c_str(), stream.audio[i].name.c_str());
55-
}
56-
57-
tries--;
58-
}
59-
}
60-
*/
61-
62-
FFmpegHandler::FFmpegHandler() {
63-
streamHandler = nullptr;
40+
FFmpegHandler::FFmpegHandler() : StreamBaseHandler() {
6441
}
6542

66-
FFmpegHandler::~FFmpegHandler() {
67-
stop();
68-
}
43+
FFmpegHandler::~FFmpegHandler() = default;
6944

7045
std::vector<std::string> FFmpegHandler::prepareStreamCmdVideo(const m3u_stream &stream) {
7146
// create parameter list
@@ -252,106 +227,4 @@ std::vector<std::string> FFmpegHandler::prepareStreamCmdAudio(const m3u_stream &
252227
debug2("FFmpeg call: %s\n", paramOut.str().c_str());
253228

254229
return callStr;
255-
}
256-
257-
bool FFmpegHandler::streamVideo(const m3u_stream &stream) {
258-
// create parameter list
259-
std::vector<std::string> callStr = prepareStreamCmdVideo(stream);
260-
261-
streamHandler = new TinyProcessLib::Process(callStr, "",
262-
[this](const char *bytes, size_t n) {
263-
debug9("Queue size %ld\n", tsPackets.size());
264-
265-
std::lock_guard<std::mutex> guard(queueMutex);
266-
tsPackets.emplace(bytes, n);
267-
},
268-
269-
[this](const char *bytes, size_t n) {
270-
// TODO: ffmpeg prints many information on stderr
271-
// How to handle this? ignore? filter?
272-
273-
std::string msg = std::string(bytes, n);
274-
debug10("Error: %s\n", msg.c_str());
275-
},
276-
277-
true
278-
);
279-
280-
/*
281-
audioUpdate = std::thread(performAudioInfoUpdate, stream);
282-
audioUpdate.detach();
283-
*/
284-
285-
return true;
286-
}
287-
288-
bool FFmpegHandler::isRunning(int &exit_status) {
289-
return streamHandler->try_get_exit_status(exit_status);
290-
}
291-
292-
bool FFmpegHandler::streamAudio(const m3u_stream &stream) {
293-
// create parameter list
294-
std::vector<std::string> callStr = prepareStreamCmdAudio(stream);
295-
296-
streamHandler = new TinyProcessLib::Process(callStr, "",
297-
[this](const char *bytes, size_t n) {
298-
debug9("Add new packets. Current queue size %ld\n", tsPackets.size());
299-
300-
std::lock_guard<std::mutex> guard(queueMutex);
301-
tsPackets.emplace(bytes, n);
302-
},
303-
304-
[this](const char *bytes, size_t n) {
305-
// TODO: ffmpeg prints many information on stderr
306-
// How to handle this? ignore? filter?
307-
308-
std::string msg = std::string(bytes, n);
309-
debug10("Error: %s\n", msg.c_str());
310-
},
311-
312-
true
313-
);
314-
315-
return true;
316-
}
317-
318-
void FFmpegHandler::stop() {
319-
if (streamHandler!=nullptr) {
320-
streamHandler->kill(true);
321-
streamHandler->get_exit_status();
322-
delete streamHandler;
323-
streamHandler = nullptr;
324-
}
325-
326-
std::lock_guard<std::mutex> guard(queueMutex);
327-
std::queue<std::string> empty;
328-
std::swap(tsPackets, empty);
329-
}
330-
331-
int FFmpegHandler::popPackets(unsigned char *bufferAddrP, unsigned int bufferLenP) {
332-
std::lock_guard<std::mutex> guard(queueMutex);
333-
if (!tsPackets.empty()) {
334-
std::string front = tsPackets.front();
335-
336-
if (bufferLenP < front.size()) {
337-
// this shall never happen. A possible solution is to use a deque instead
338-
// and modify the front element. Unsure, if this is worth the effort, because
339-
// a full buffer points to another problem.
340-
error("WARNING: BufferLen %u < Size %ld\n", bufferLenP, front.size());
341-
342-
// remove packet from queue to prevent queue overload
343-
tsPackets.pop();
344-
345-
return 0;
346-
}
347-
348-
debug9("Read from queue: len %ld, size %ld bytes\n", tsPackets.size(), front.size());
349-
350-
memcpy(bufferAddrP, front.data(), front.size());
351-
352-
tsPackets.pop();
353-
return front.size();
354-
}
355-
356-
return 0;
357230
}

ffmpeghandler.h

+5-18
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,14 @@
55
#include <queue>
66
#include "process.hpp"
77
#include "m3u8handler.h"
8+
#include "streambasehandler.h"
89

9-
class FFmpegHandler {
10-
private:
11-
TinyProcessLib::Process *streamHandler;
12-
10+
class FFmpegHandler : public StreamBaseHandler {
1311
public:
1412
FFmpegHandler();
1513
~FFmpegHandler();
1614

17-
bool streamVideo(const m3u_stream &stream);
18-
bool streamAudio(const m3u_stream &stream);
19-
void stop();
20-
bool isRunning(int &exit_status);
21-
22-
int popPackets(unsigned char *bufferAddrP, unsigned int bufferLenP);
23-
24-
private:
25-
std::queue<std::string> tsPackets;
26-
std::mutex queueMutex;
27-
28-
private:
29-
static std::vector<std::string> prepareStreamCmdVideo(const m3u_stream &stream);
30-
static std::vector<std::string> prepareStreamCmdAudio(const m3u_stream &stream);
15+
protected:
16+
std::vector<std::string> prepareStreamCmdVideo(const m3u_stream &stream) override;
17+
std::vector<std::string> prepareStreamCmdAudio(const m3u_stream &stream) override;
3118
};

protocolcurl.cpp

+8-12
Original file line numberDiff line numberDiff line change
@@ -626,18 +626,14 @@ int cIptvProtocolCurl::Read(unsigned char *bufferAddrP, unsigned int bufferLenP)
626626
}
627627

628628
bool
629-
cIptvProtocolCurl::SetSource(const char *locationP,
630-
const int parameterP,
631-
const int indexP,
632-
int channelNumber,
633-
int useYtDlp) {
634-
debug1("%s (%s, %d, %d)", __PRETTY_FUNCTION__, locationP, parameterP, indexP);
635-
636-
if (!isempty(locationP)) {
629+
cIptvProtocolCurl::SetSource(SourceParameter parameter) {
630+
debug1("%s (%s, %d, %d)", __PRETTY_FUNCTION__, parameter.locationP, parameter.parameterP, parameter.indexP);
631+
632+
if (!isempty(parameter.locationP)) {
637633
// Disconnect
638634
Disconnect();
639635
// Update stream URL
640-
streamUrlM = locationP;
636+
streamUrlM = parameter.locationP;
641637
cString protocol = ChangeCase(streamUrlM, false).Truncate(5);
642638

643639
if (startswith(*protocol, "rtsp")) {
@@ -652,13 +648,13 @@ cIptvProtocolCurl::SetSource(const char *locationP,
652648
modeM = eModeUnknown;
653649
}
654650

655-
debug1("%s (%s, %d, %d) protocol=%s mode=%d", __PRETTY_FUNCTION__, locationP, parameterP, indexP, *protocol, modeM);
651+
debug1("%s (%s, %d, %d) protocol=%s mode=%d", __PRETTY_FUNCTION__, parameter.locationP, parameter.parameterP, parameter.indexP, *protocol, modeM);
656652

657653
// Update stream parameter - force UDP mode for RTSP
658-
streamParamM = (modeM==eModeRtsp) ? 0 : parameterP;
654+
streamParamM = (modeM==eModeRtsp) ? 0 : parameter.parameterP;
659655

660656
// Update listen port
661-
streamPortM = IptvConfig.GetProtocolBasePort() + indexP*2;
657+
streamPortM = IptvConfig.GetProtocolBasePort() + parameter.indexP*2;
662658

663659
// Reconnect
664660
Connect();

protocolcurl.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class cIptvProtocolCurl : public cIptvUdpSocket, public cIptvProtocolIf {
6666
cIptvProtocolCurl();
6767
~cIptvProtocolCurl() override;
6868
int Read(unsigned char *bufferAddrP, unsigned int bufferLenP) override;
69-
bool SetSource(const char *locationP, int parameterP, int indexP, int channelNumber, int useYtDlp) override;
69+
bool SetSource(SourceParameter parameter) override;
7070
bool SetPid(int pidP, int typeP, bool onP) override;
7171
bool Open() override;
7272
bool Close() override;

protocolext.cpp

+7-11
Original file line numberDiff line numberDiff line change
@@ -171,27 +171,23 @@ int cIptvProtocolExt::Read(unsigned char *bufferAddrP, unsigned int bufferLenP)
171171
}
172172

173173
bool
174-
cIptvProtocolExt::SetSource(const char *locationP,
175-
const int parameterP,
176-
const int indexP,
177-
int channelNumber,
178-
int useYtDlp) {
179-
debug1("%s (%s, %d, %d)", __PRETTY_FUNCTION__, locationP, parameterP, indexP);
180-
181-
if (!isempty(locationP)) {
174+
cIptvProtocolExt::SetSource(SourceParameter parameter) {
175+
debug1("%s (%s, %d, %d)", __PRETTY_FUNCTION__, parameter.locationP, parameter.parameterP, parameter.indexP);
176+
177+
if (!isempty(parameter.locationP)) {
182178
struct stat stbuf;
183179
// Update script file and parameter
184-
scriptFileM = cString::sprintf("%s/%s", IptvConfig.GetResourceDirectory(), locationP);
180+
scriptFileM = cString::sprintf("%s/%s", IptvConfig.GetResourceDirectory(), parameter.locationP);
185181

186182
if ((stat(*scriptFileM, &stbuf) != 0) || (strstr(*scriptFileM, "..") != nullptr)) {
187183
error("Non-existent or relative path script '%s'", *scriptFileM);
188184

189185
return false;
190186
}
191187

192-
scriptParameterM = parameterP;
188+
scriptParameterM = parameter.parameterP;
193189
// Update listen port
194-
streamPortM = IptvConfig.GetProtocolBasePort() + indexP*2;
190+
streamPortM = IptvConfig.GetProtocolBasePort() + parameter.indexP*2;
195191
}
196192
return true;
197193
}

protocolext.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class cIptvProtocolExt : public cIptvUdpSocket, public cIptvProtocolIf {
2626
cIptvProtocolExt();
2727
~cIptvProtocolExt() override;
2828
int Read(unsigned char *bufferAddrP, unsigned int bufferLenP) override;
29-
bool SetSource(const char *locationP, int parameterP, int indexP, int channelNumber, int useYtDlp) override;
29+
bool SetSource(SourceParameter parameter) override;
3030
bool SetPid(int pidP, int typeP, bool onP) override;
3131
bool Open() override;
3232
bool Close() override;

protocolfile.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -103,16 +103,16 @@ bool cIptvProtocolFile::Close() {
103103
return true;
104104
}
105105

106-
bool cIptvProtocolFile::SetSource(const char *locationP, const int parameterP, const int indexP, int channelNumber, int useYtDlp) {
107-
debug1("%s (%s, %d, %d)", __PRETTY_FUNCTION__, locationP, parameterP, indexP);
106+
bool cIptvProtocolFile::SetSource(SourceParameter parameter) {
107+
debug1("%s (%s, %d, %d)", __PRETTY_FUNCTION__, parameter.locationP, parameter.parameterP, parameter.indexP);
108108

109-
if (!isempty(locationP)) {
109+
if (!isempty(parameter.locationP)) {
110110
// Close the file stream
111111
CloseFile();
112112

113113
// Update stream address and port
114-
fileLocationM = strcpyrealloc(fileLocationM, locationP);
115-
fileDelayM = parameterP;
114+
fileLocationM = strcpyrealloc(fileLocationM, parameter.locationP);
115+
fileDelayM = parameter.parameterP;
116116

117117
// Open the file for input
118118
OpenFile();

protocolfile.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class cIptvProtocolFile : public cIptvProtocolIf {
2525
cIptvProtocolFile();
2626
~cIptvProtocolFile() override;
2727
int Read(unsigned char *bufferAddrP, unsigned int bufferLenP) override;
28-
bool SetSource(const char *locationP, int parameterP, int indexP, int channelNumber, int useYtDlp) override;
28+
bool SetSource(SourceParameter parameter) override;
2929
bool SetPid(int pidP, int typeP, bool onP) override;
3030
bool Open() override;
3131
bool Close() override;

0 commit comments

Comments
 (0)