summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/backgroundwriter.c500
-rw-r--r--tools/backgroundwriter.h161
-rw-r--r--tools/bitstream.h175
-rw-r--r--tools/cxsocket.c430
-rw-r--r--tools/cxsocket.h195
-rw-r--r--tools/debug_mutex.h206
-rw-r--r--tools/display_message.h73
-rw-r--r--tools/functor.h47
-rw-r--r--tools/functorimpl.h150
-rw-r--r--tools/future.h87
-rw-r--r--tools/general_remote.h27
-rw-r--r--tools/gnome_screensaver.c135
-rw-r--r--tools/gnome_screensaver.h6
-rw-r--r--tools/h264.c224
-rw-r--r--tools/h264.h68
-rw-r--r--tools/http.c434
-rw-r--r--tools/http.h147
-rw-r--r--tools/iso639.h186
-rw-r--r--tools/listiter.h83
-rw-r--r--tools/metainfo_menu.c101
-rw-r--r--tools/metainfo_menu.h38
-rw-r--r--tools/mpeg.c67
-rw-r--r--tools/mpeg.h58
-rw-r--r--tools/pes.c152
-rw-r--r--tools/pes.h120
-rw-r--r--tools/playlist.c1005
-rw-r--r--tools/playlist.h132
-rw-r--r--tools/rle.c171
-rw-r--r--tools/rle.h52
-rw-r--r--tools/rtcp.h134
-rw-r--r--tools/rtp.h100
-rw-r--r--tools/sap.h207
-rw-r--r--tools/sdp.h112
-rw-r--r--tools/time_pts.c172
-rw-r--r--tools/time_pts.h43
-rw-r--r--tools/timer.c288
-rw-r--r--tools/timer.h296
-rw-r--r--tools/ts.c682
-rw-r--r--tools/ts.h173
-rw-r--r--tools/udp_buffer.h144
-rw-r--r--tools/udp_pes_scheduler.c938
-rw-r--r--tools/udp_pes_scheduler.h130
-rw-r--r--tools/vdrdiscovery.c273
-rw-r--r--tools/vdrdiscovery.h81
44 files changed, 0 insertions, 9003 deletions
diff --git a/tools/backgroundwriter.c b/tools/backgroundwriter.c
deleted file mode 100644
index 6b7c8ff4..00000000
--- a/tools/backgroundwriter.c
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- * backgroundwriter.h: Buffered socket/file writing thread
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: backgroundwriter.c,v 1.18 2009-07-24 18:11:20 phintuka Exp $
- *
- */
-
-#define __STDC_FORMAT_MACROS
-#define __STDC_CONSTANT_MACROS
-#include <inttypes.h>
-
-#include <stdint.h>
-#include <unistd.h>
-#include <netinet/tcp.h> // CORK, NODELAY
-
-#include <vdr/tools.h>
-#include <vdr/config.h> // VDRVERSNUM
-
-#include "../logdefs.h"
-#include "../xine_input_vdr_net.h" // stream_tcp_header_t
-#include "ts.h"
-#include "pes.h"
-
-#include "backgroundwriter.h"
-
-
-#define MAX_OVERFLOWS_BEFORE_DISCONNECT 1000 // ~ 1 second
-
-
-//
-// cBackgroundWriterI
-//
-
-cBackgroundWriterI::cBackgroundWriterI(int fd, int Size, int Margin)
- : m_RingBuffer(Size, Margin)
-{
- m_fd = fd;
- m_RingBuffer.SetTimeouts(0, 100);
-
- m_PutPos = 0;
- m_DiscardStart = 0;
- m_DiscardEnd = 0;
-
- m_BufferOverflows = 0;
-
-#if defined(TCP_CORK)
- int iCork = 1;
- if(setsockopt(m_fd, IPPROTO_TCP, TCP_CORK, &iCork, sizeof(int))) {
- if(errno != ENOTSOCK)
- LOGERR("cBackgroundWriter: setsockopt(TCP_CORK) failed");
- m_IsSocket = false;
- errno = 0;
- } else {
- m_IsSocket = true;
- }
-#elif defined(TCP_NOPUSH)
- int iCork = 1;
- if(setsockopt(m_fd, IPPROTO_TCP, TCP_NOPUSH, &iCork, sizeof(int))) {
- if(errno != ENOTSOCK)
- LOGERR("cBackgroundWriter: setsockopt(TCP_NOPUSH) failed");
- m_IsSocket = false;
- errno = 0;
- } else {
- m_IsSocket = true;
- }
-#endif
-
- LOGDBG("cBackgroundWriterI initialized (buffer %d kb)", Size/1024);
-}
-
-cBackgroundWriterI::~cBackgroundWriterI()
-{
- Cancel(3);
-}
-
-int cBackgroundWriterI::Free(void)
-{
- return m_RingBuffer.Free();
-}
-
-void cBackgroundWriterI::Clear(void)
-{
- // Can't just drop buffer contents or PES frames will be broken.
- // Serialize with Put
- LOCK_THREAD;
- m_DiscardEnd = m_PutPos;
-}
-
-void cBackgroundWriterI::Cork(void)
-{
- if (m_IsSocket) {
-#if defined(TCP_CORK)
- int i = 1;
- if(setsockopt(m_fd, IPPROTO_TCP, TCP_NODELAY, &i, sizeof(int))) {
- LOGERR("cBackgroundWriter: setsockopt(TCP_NODELAY) failed");
- errno = 0;
- }
-#elif defined(TCP_NOPUSH)
- int On = 1, Off = 0;
- if(setsockopt(m_fd, IPPROTO_TCP, TCP_NOPUSH, &Off, sizeof(int)) ||
- setsockopt(m_fd, IPPROTO_TCP, TCP_NOPUSH, &On, sizeof(int))) {
- LOGERR("cBackgroundWriter: setsockopt(TCP_NOPUSH) failed");
- errno = 0;
- }
-#endif
- }
-}
-
-bool cBackgroundWriterI::Flush(int TimeoutMs)
-{
- uint64_t WaitEnd = cTimeMs::Now();
-
- // wait for ring buffer to drain
- if(TimeoutMs > 0) {
- WaitEnd += (uint64_t)TimeoutMs;
-
- while(cTimeMs::Now() < WaitEnd &&
- Running() &&
- m_RingBuffer.Available() > 0)
- cCondWait::SleepMs(3);
- }
-
- int Available = m_RingBuffer.Available();
- if(m_IsSocket && Available <= 0) {
- // flush corked data too
- Cork();
- }
-
- return Available <= 0;
-}
-
-
-//
-// cTcpWriter
-//
-
-cTcpWriter::cTcpWriter(int fd, int Size) :
- cBackgroundWriterI(fd, Size, sizeof(stream_tcp_header_t))
-{
- LOGDBG("cTcpWriter initialized (buffer %d kb)", Size/1024);
- Start();
-}
-
-void cTcpWriter::Action(void)
-{
- uint64_t NextHeaderPos = 0;
- uint64_t GetPos = 0;
- cPoller Poller (m_fd, true);
- bool CorkReq = false;
-
- while (Running()) {
-
- if(Poller.Poll(100)) {
-
- if (CorkReq && m_RingBuffer.Available() <= 0) {
- // Force TCP packet to avoid delaying control messages
- Cork();
- CorkReq = false;
- }
-
- uint64_t StartPos;
- int Count = 0;
- int n;
- uchar *Data = m_RingBuffer.Get(Count);
-
- if(Data && Count > 0) {
-
- Lock(); // uint64_t m_DiscardStart can not be read atomically (IA32)
- StartPos = m_DiscardEnd;
- Unlock();
-
- // Discard data ?
- if(StartPos > GetPos) {
- if(NextHeaderPos == GetPos) {
- // we're at frame boundary
- // drop only data packets, not control messages
- uint8_t *pkt = TCP_PAYLOAD(Data);
- if (DATA_IS_PES(pkt) || DATA_IS_TS(pkt)) {
- Count = min(Count, (int)(StartPos - GetPos));
-
- // size of next (complete) packet.
- // drop only one packet at time.
- stream_tcp_header_t *header = (stream_tcp_header_t*)Data;
- int pkt_len = ntohl(header->len) + sizeof(stream_tcp_header_t);
- if (Count >= pkt_len) {
- // drop only complete packets.
- // some packets are not dropped (packets overlapping end of ringbuffer)
- Count = pkt_len;
-
- m_RingBuffer.Del(Count);
- GetPos += Count;
- NextHeaderPos = GetPos;
-
- CorkReq = true; // force sending last frame
-
- continue;
- }
- }
- }
- }
-
- // Next frame ?
- if(GetPos == NextHeaderPos) {
- if(Count < (int)sizeof(stream_tcp_header_t))
- LOGMSG("cBackgroundWriter @NextHeaderPos: Count < header size !");
-
- // limit single write to size of next (complete) packet.
- // (we need to track packet boundaries)
- stream_tcp_header_t *header = (stream_tcp_header_t*)Data;
- int pkt_len = ntohl(header->len) + sizeof(stream_tcp_header_t);
- if (Count > pkt_len)
- Count = pkt_len;
- // next packet start position in stream
- NextHeaderPos = GetPos + pkt_len;
-
- // check for control message
- uint8_t *pkt = TCP_PAYLOAD(Data);
- if (!DATA_IS_PES(pkt) && !DATA_IS_TS(pkt))
- CorkReq = true;
-
- } else {
- Count = min(Count, (int)(NextHeaderPos-GetPos));
- }
-
- errno = 0;
- n = write(m_fd, Data, Count);
-
- if(n == 0) {
- LOGERR("cBackgroundWriter: Client disconnected data stream ?");
- break;
-
- } else if(n < 0) {
-
- if (errno == EINTR || errno == EWOULDBLOCK) {
- TRACE("cBackgroundWriter: EINTR while writing to file handle "
- <<m_fd<<" - retrying");
- continue;
-
- } else {
- LOGERR("cBackgroundWriter: TCP write error");
- break;
- }
- }
-
- GetPos += n;
- m_RingBuffer.Del(n);
- }
- }
- }
-
- m_RingBuffer.Clear();
-}
-
-int cTcpWriter::Put(uint64_t StreamPos,
- const uchar *Data, int DataCount)
-{
- stream_tcp_header_t header;
- header.pos = htonull(StreamPos);
- header.len = htonl(DataCount);
- return Put((uchar*)&header, sizeof(header), Data, DataCount);
-}
-
-int cTcpWriter::Put(const uchar *Header, int HeaderCount,
- const uchar *Data, int DataCount)
-{
- if (Running()) {
-
- // Serialize Put access to keep Data and Header together
- LOCK_THREAD;
-
- if(m_RingBuffer.Free() < HeaderCount+DataCount) {
- //LOGMSG("cXinelibServer: TCP buffer overflow !");
- if(m_BufferOverflows++ > MAX_OVERFLOWS_BEFORE_DISCONNECT) {
- LOGMSG("cXinelibServer: Too many TCP buffer overflows, dropping client");
- m_RingBuffer.Clear();
- Cancel(-1);
- return 0;
- }
- return -HeaderCount-DataCount;
- }
- int n = m_RingBuffer.Put(Header, HeaderCount) +
- m_RingBuffer.Put(Data, DataCount);
- if(n == HeaderCount+DataCount) {
- m_BufferOverflows = 0;
- m_PutPos += n;
- return n;
- }
-
- LOGMSG("cXinelibServer: TCP buffer internal error ?!?");
- m_RingBuffer.Clear();
- Cancel(-1);
- }
-
- return 0;
-}
-
-
-//
-// cRawWriter
-//
-
-cRawWriter::cRawWriter(int fd, int Size) :
- cBackgroundWriterI(fd, Size, 6)
-{
- LOGDBG("cRawWriter initialized (buffer %d kb)", Size/1024);
- Start();
-}
-
-void cRawWriter::Action(void)
-{
- uint64_t NextHeaderPos = 0ULL;
- uint64_t GetPos = 0ULL;
- cPoller Poller(m_fd, true);
-
- while (Running()) {
-
- if(Poller.Poll(100)) {
-
- uint64_t StartPos;
- int Count = 0;
- int n;
- uchar *Data = m_RingBuffer.Get(Count);
-
- if(Data && Count > 0) {
-
- Lock(); // uint64_t m_DiscardStart can not be read atomically (IA32)
- StartPos = m_DiscardEnd;
- Unlock();
-
- // Discard data ?
- if(StartPos > GetPos) {
- if(NextHeaderPos == GetPos) {
- // we're at frame boundary
- Count = min(Count, (int)(StartPos - GetPos));
-
- m_RingBuffer.Del(Count);
- GetPos += Count;
- NextHeaderPos = GetPos;
- continue;
- }
- }
-
- // Next frame ?
- if(GetPos == NextHeaderPos) {
- if(Count < 6)
- LOGMSG("cBackgroundWriter @NextHeaderPos: Count < header size !");
-
- int packlen = DATA_IS_TS(Data) ? TS_SIZE : pes_packet_len(Data, Count);
-
- if(Count < packlen)
- ;//LOGMSG("Count = %d < %d", Count,
- // header->len + sizeof(stream_tcp_header_t));
- else
- Count = packlen;
- NextHeaderPos = GetPos + packlen;
- } else {
- Count = min(Count, (int)(NextHeaderPos-GetPos));
- }
-
- errno = 0;
- n = write(m_fd, Data, Count);
-
- if(n == 0) {
- LOGERR("cBackgroundWriter: Client disconnected data stream ?");
- break;
-
- } else if(n < 0) {
-
- if (errno == EINTR || errno == EWOULDBLOCK) {
- TRACE("cBackgroundWriter: EINTR while writing to file handle "
- <<m_fd<<" - retrying");
- continue;
-
- } else {
- LOGERR("cBackgroundWriter: TCP write error");
- break;
- }
- }
-
- GetPos += n;
- m_RingBuffer.Del(n);
- }
- }
- }
-
- m_RingBuffer.Clear();
-}
-
-int cRawWriter::Put(uint64_t StreamPos,
- const uchar *Data, int DataCount)
-{
- if (Running()) {
-
- // Serialize Put access to keep Data and Header together
- LOCK_THREAD;
-
- if(m_RingBuffer.Free() < DataCount) {
- if(m_BufferOverflows++ > MAX_OVERFLOWS_BEFORE_DISCONNECT) {
- LOGMSG("cXinelibServer: Too many TCP buffer overflows, dropping client");
- m_RingBuffer.Clear();
- Cancel(-1);
- return 0;
- }
- return -DataCount;
- }
- int n = m_RingBuffer.Put(Data, DataCount);
- if(n == DataCount) {
- m_BufferOverflows = 0;
- m_PutPos += n;
- return n;
- }
-
- LOGMSG("cXinelibServer: TCP buffer internal error ?!?");
- m_RingBuffer.Clear();
- Cancel(-1);
- }
-
- return 0;
-}
-
-
-//
-// cTsWriter
-// - Demux PES stream to PS
-//
-
-cTsWriter::cTsWriter(int fd, int Size) :
- cBackgroundWriterI(fd, Size, 6)
-{
- LOGDBG("cTsWriter initialized (buffer %d kb)", Size/1024);
- Start();
-}
-
-
-void cTsWriter::Action(void)
-{
-}
-
-int cTsWriter::Put(uint64_t StreamPos, const uchar *Data, int DataCount)
-{
- return 0;
-}
-
-
-//
-// cRtspMuxWriter
-// - RTSP multiplexed control+data
-// - Each encapsulated PES frame is written atomically to socket buffer
-// - Atomic control data can be written directly to socket
-// from another thread to bypass buffer
-//
-
-cRtspMuxWriter::cRtspMuxWriter(int fd, int Size) :
- cBackgroundWriterI(fd, Size, 6)
-{
- LOGDBG("cRtspMuxWriter initialized (buffer %d kb)", Size/1024);
- Start();
-}
-
-void cRtspMuxWriter::Action(void)
-{
-}
-
-int cRtspMuxWriter::Put(uint64_t StreamPos, const uchar *Data, int DataCount)
-{
- return 0;
-}
-
-
-//
-// cRtspRemuxWriter
-// - RTSP multiplexed control+data
-// - Demux PES stream to independent ES streams
-// - encapsulate ES to RTP/AVP compatible frames
-// - Mux RTP/AVP ES streams to pipelined RTCP control connection
-// - Each encapsulated frame is written atomically to socket buffer
-// - Atomic control data can be written directly to socket
-// from another thread to bypass buffer
-//
-
-cRtspRemuxWriter::cRtspRemuxWriter(int fd, int Size) :
- cBackgroundWriterI(fd, Size, 6)
-{
- LOGDBG("cRtspRemuxWriter initialized (buffer %d kb)", Size/1024);
- Start();
-}
-
-void cRtspRemuxWriter::Action(void)
-{
-}
-
-int cRtspRemuxWriter::Put(uint64_t StreamPos, const uchar *Data, int DataCount)
-{
- return 0;
-}
-
-
diff --git a/tools/backgroundwriter.h b/tools/backgroundwriter.h
deleted file mode 100644
index d0ee5b30..00000000
--- a/tools/backgroundwriter.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * backgroundwriter.h: Buffered socket/file writing thread
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: backgroundwriter.h,v 1.6 2009-07-24 05:24:22 phintuka Exp $
- *
- */
-
-#ifndef __BACKGROUNDWRITER_H
-#define __BACKGROUNDWRITER_H
-
-#include <stdint.h>
-
-#include <vdr/thread.h>
-#include <vdr/ringbuffer.h>
-
-//
-// cBackgroundWriterI
-// - generic interface for buffered output
-//
-class cBackgroundWriterI : public cThread
-{
- protected:
- cRingBufferLinear m_RingBuffer;
-
- int m_fd;
- bool m_IsSocket;
-
- uint64_t m_PutPos;
- uint64_t m_DiscardStart;
- uint64_t m_DiscardEnd;
-
- int m_BufferOverflows;
-
- protected:
- virtual void Action(void) = 0;
- void Cork(void);
-
- public:
- cBackgroundWriterI(int fd, int Size = KILOBYTE(512), int Margin = 0);
- virtual ~cBackgroundWriterI();
-
- // Add PES frame to buffer
- //
- // Return value:
- // Success: Count (all bytes pushed to queue)
- // Error: 0 (write error ; socket disconnected)
- // Buffer full: -Count (no bytes will be pushed to queue)
- //
- virtual int Put(uint64_t StreamPos, const uchar *Data, int DataCount) = 0;
-
- int Free(void); // Return largest possible Put size
- void Clear(void); // Drop all data (only complete frames) from buffer
- bool Flush(int TimeoutMs); // Flush buffer (wait for data to be sent)
-};
-
-
-//
-// cTcpWriter
-// - xineliboutput TCP data steam
-// - stream_tcp_header_t encapsulated PES frames
-//
-class cTcpWriter : public cBackgroundWriterI
-{
- protected:
- virtual void Action(void);
-
- int Put(const uchar *Header, int HeaderCount,
- const uchar *Data, int DataCount);
-
- public:
- cTcpWriter(int fd, int Size = KILOBYTE(512));
- virtual ~cTcpWriter() {};
-
- virtual int Put(uint64_t StreamPos, const uchar *Data, int DataCount);
-};
-
-
-//
-// cRawWriter
-// - Raw PES stream
-// - Used with HTTP
-//
-class cRawWriter : public cBackgroundWriterI
-{
- protected:
- virtual void Action(void);
-
- public:
- cRawWriter(int fd, int Size = KILOBYTE(512));
- virtual ~cRawWriter() {};
-
- virtual int Put(uint64_t StreamPos, const uchar *Data, int DataCount);
-};
-
-
-//
-// cTsWriter
-// - Demux PES stream to PS
-//
-class cTsWriter : public cBackgroundWriterI
-{
- protected:
- virtual void Action(void);
-
- public:
- cTsWriter(int fd, int Size = KILOBYTE(512));
- virtual ~cTsWriter() {};
-
- virtual int Put(uint64_t StreamPos, const uchar *Data, int DataCount);
-};
-
-
-//
-// cRtspMuxWriter
-// - RTSP multiplexed control+data
-// - Each encapsulated PES frame is written atomically to socket buffer
-// - Atomic control data can be written directly to socket
-// from another thread to bypass buffer
-//
-
-class cRtspMuxWriter : public cBackgroundWriterI
-{
- protected:
- virtual void Action(void);
-
- public:
- cRtspMuxWriter(int fd, int Size = KILOBYTE(512));
- virtual ~cRtspMuxWriter() {};
-
- virtual int Put(uint64_t StreamPos, const uchar *Data, int DataCount);
-};
-
-
-//
-// cRtspRemuxWriter
-// - RTSP multiplexed control+data
-// - Demux PES stream to independent ES streams
-// - encapsulate ES to RTP/AVP compatible frames
-// - Mux RTP/AVP ES streams to pipelined RTCP control connection
-// - Each encapsulated frame is written atomically to socket buffer
-// - Atomic control data can be written directly to socket
-// from another thread to bypass buffer
-//
-
-class cRtspRemuxWriter : public cBackgroundWriterI
-{
- protected:
- virtual void Action(void);
-
- public:
- cRtspRemuxWriter(int fd, int Size = KILOBYTE(512));
- virtual ~cRtspRemuxWriter() {};
-
- virtual int Put(uint64_t StreamPos, const uchar *Data, int DataCount);
-};
-
-
-#endif
diff --git a/tools/bitstream.h b/tools/bitstream.h
deleted file mode 100644
index 569c491b..00000000
--- a/tools/bitstream.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * bitstream.h: generic bitstream parsing
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: bitstream.h,v 1.3 2009-02-14 20:44:15 phintuka Exp $
- *
- */
-
-#ifndef _XINELIBOUTPUT_BITSTREAM_H_
-#define _XINELIBOUTPUT_BITSTREAM_H_
-
-
-# ifdef NOCACHE
-
-typedef struct {
- const uint8_t *data;
- int count; /* in bits */
- int index; /* in bits */
-} br_state;
-
-#define BR_INIT(data,bytes) { (data), 8*(bytes), 0 }
-
-#define BR_EOF(br) ((br)->index >= (br)->count)
-
-static inline void br_init(br_state *br, const uint8_t *data, int bytes)
-{
- br->data = data;
- br->count = 8*bytes;
- br->index = 0;
-}
-
-static inline int br_get_bit(br_state *br)
-{
- if(br->index >= br->count)
- return 1; /* -> no infinite colomb's ... */
-
- int r = (br->data[br->index>>3] >> (7 - (br->index&7))) & 1;
- br->index++;
- return r;
-}
-
-static inline uint32_t br_get_bits(br_state *br, uint32_t n)
-{
- uint32_t r = 0;
- while(n--)
- r = r | (br_get_bit(br) << n);
- return r;
-}
-
-#define br_skip_bit(br) br_skip_bits(br,1)
-
-static inline void br_skip_bits(br_state *br, int n)
-{
- br->index += n;
-}
-
-
-# else /* NOCACHE */
-
-
-typedef struct {
- uint8_t *data;
- uint8_t *data_end;
- uint32_t cache;
- uint32_t cache_bits;
-} br_state;
-
-#define BR_INIT(data,bytes) { (data), (data)+(bytes), 0, 0 }
-
-static inline void br_init(br_state *br, const uint8_t *data, int bytes)
-{
- br->data = data;
- br->data_end = data + bytes;
- br->cache = 0;
- br->cache_bits = 0;
-}
-
-#define BR_GET_BYTE(br) \
- (br->data < br->data_end ? *br->data++ : 0xff)
-
-#define BR_EOF(br) ((br)->data >= (br)->data_end)
-
-static inline uint32_t br_get_bits(br_state *br, uint32_t n)
-{
- if(n > 24)
- return (br_get_bits(br, 16) << 16) | br_get_bits(br, n-16);
-
- while (br->cache_bits < 24) {
- br->cache = (br->cache<<8) | BR_GET_BYTE(br);
- br->cache_bits += 8;
- }
-
- br->cache_bits -= n;
- return (br->cache >> br->cache_bits) & ((1<<n) - 1);
-}
-
-static inline int br_get_bit(br_state *br)
-{
- if(!br->cache_bits) {
- br->cache = BR_GET_BYTE(br);
- br->cache_bits = 7;
- } else {
- br->cache_bits--;
- }
- return (br->cache >> br->cache_bits) & 1;
-}
-
-static inline void br_skip_bit(br_state *br)
-{
- if(!br->cache_bits) {
- br->cache = BR_GET_BYTE(br);
- br->cache_bits = 7;
- } else {
- br->cache_bits--;
- }
-}
-
-static inline void br_skip_bits(br_state *br, int n)
-{
- if(br->cache_bits >= n) {
- br->cache_bits -= n;
- } else {
- /* drop cached bits */
- n -= br->cache_bits;
-
- /* drop full bytes */
- br->data += (n >> 3);
- n &= 7;
-
- /* update cache */
- if(n) {
- br->cache = BR_GET_BYTE(br);
- br->cache_bits = 8 - n;
- } else {
- br->cache_bits = 0;
- }
- }
-}
-
-
-# endif /* NOCACHE */
-
-
-#define br_get_u8(br) br_get_bits(br, 8)
-#define br_get_u16(br) ((br_get_bits(br, 8)<<8) | br_get_bits(br, 8))
-
-static inline uint32_t br_get_ue_golomb(br_state *br)
-{
- int n = 0;
- while (!br_get_bit(br) && n < 32)
- n++;
- return n ? ((1<<n) - 1) + br_get_bits(br, n) : 0;
-}
-
-static inline int32_t br_get_se_golomb(br_state *br)
-{
- uint32_t r = br_get_ue_golomb(br) + 1;
- return (r&1) ? -(r>>1) : (r>>1);
-}
-
-static inline void br_skip_golomb(br_state *br)
-{
- int n = 0;
- while (!br_get_bit(br) && n < 32)
- n++;
- br_skip_bits(br, n);
-}
-
-#define br_skip_ue_golomb(br) br_skip_golomb(br)
-#define br_skip_se_golomb(br) br_skip_golomb(br)
-
-
-#endif /* _XINELIBOUTPUT_BITSTREAM_H_ */
diff --git a/tools/cxsocket.c b/tools/cxsocket.c
deleted file mode 100644
index e6a95a72..00000000
--- a/tools/cxsocket.c
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * cxsocket.c: Socket wrapper classes
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: cxsocket.c,v 1.11 2007-03-27 02:45:48 phintuka Exp $
- *
- */
-
-#define __STDC_FORMAT_MACROS
-#include <inttypes.h>
-
-#include <stdlib.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#ifndef __APPLE__
-# include <sys/sendfile.h>
-#endif
-#include <netinet/tcp.h>
-
-#include <vdr/config.h>
-#include <vdr/tools.h>
-
-#include "../logdefs.h"
-
-#include "cxsocket.h"
-
-bool cxSocket::connect(struct sockaddr *addr, socklen_t len)
-{
- return ::connect(m_fd, addr, len) == 0;
-}
-
-bool cxSocket::connect(const char *ip, int port)
-{
- struct sockaddr_in sin;
- sin.sin_family = AF_INET;
- sin.sin_port = htons(port);
- sin.sin_addr.s_addr = inet_addr(ip);
- return connect((struct sockaddr *)&sin, sizeof(sin));
-}
-
-bool cxSocket::set_blocking(bool state)
-{
- int flags = fcntl (m_fd, F_GETFL);
-
- if(flags == -1) {
- LOGERR("cxSocket::SetBlocking: fcntl(F_GETFL) failed");
- return false;
- }
-
- flags = state ? (flags&(~O_NONBLOCK)) : (flags|O_NONBLOCK);
-
- if(fcntl (m_fd, F_SETFL, flags) == -1) {
- LOGERR("cxSocket::SetBlocking: fcntl(F_SETFL) failed");
- return false;
- }
-
- return true;
-}
-
-bool cxSocket::set_buffers(int Tx, int Rx)
-{
- int max_buf = Tx;
- /*while(max_buf) {*/
- errno = 0;
- if(setsockopt(m_fd, SOL_SOCKET, SO_SNDBUF, &max_buf, sizeof(int))) {
- LOGERR("cxSocket: setsockopt(SO_SNDBUF,%d) failed", max_buf);
- /*max_buf >>= 1;*/
- }
- /*else {*/
- int tmp = 0;
- int len = sizeof(int);
- errno = 0;
- if(getsockopt(m_fd, SOL_SOCKET, SO_SNDBUF, &tmp, (socklen_t*)&len)) {
- LOGERR("cxSocket: getsockopt(SO_SNDBUF,%d) failed", max_buf);
- /*break;*/
- } else if(tmp != max_buf) {
- LOGDBG("cxSocket: setsockopt(SO_SNDBUF): got %d bytes", tmp);
- /*max_buf >>= 1;*/
- /*continue;*/
- }
- /*}*/
- /*}*/
-
- max_buf = Rx;
- setsockopt(m_fd, SOL_SOCKET, SO_RCVBUF, &max_buf, sizeof(int));
-
- return true;
-}
-
-bool cxSocket::set_multicast(int ttl)
-{
- int iReuse = 1, iLoop = 1, iTtl = ttl;
-
- errno = 0;
-
- if(setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, &iReuse, sizeof(int)) < 0) {
- LOGERR("cxSocket: setsockopt(SO_REUSEADDR) failed");
- return false;
- }
-
- if(setsockopt(m_fd, IPPROTO_IP, IP_MULTICAST_TTL, &iTtl, sizeof(int))) {
- LOGERR("cxSocket: setsockopt(IP_MULTICAST_TTL, %d) failed", iTtl);
- return false;
- }
-
- if(setsockopt(m_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &iLoop, sizeof(int))) {
- LOGERR("cxSocket: setsockopt(IP_MULTICAST_LOOP) failed");
- return false;
- }
-
- return true;
-}
-
-ssize_t cxSocket::sendfile(int fd_file, off_t *offset, size_t count)
-{
- int r;
-#ifndef __APPLE__
- r = ::sendfile(m_fd, fd_file, offset, count);
- if(r<0 && (errno == ENOSYS || errno == EINVAL)) {
- // fall back to read/write
- LOGERR("sendfile failed - using simple read/write");
-#endif
- cxPoller p(*this, true);
- char buf[0x10000];
- int todor = count, todow, done = 0;
- if(offset)
- if((r=::lseek(fd_file, *offset, SEEK_SET)) < 0)
- return r;
- todow = ::read(fd_file, buf, count>sizeof(buf) ? sizeof(buf) : count);
- if(todow <= 0)
- return todow;
- todor -= todow;
- while(todow > 0) {
- if(p.Poll(100)) {
- r = write(buf+done, todow);
- if(r <= 0)
- return r;
- todow -= r;
- done += r;
- }
- }
- return done;
-#ifndef __APPLE__
- }
- return r;
-#endif
-}
-
-bool cxSocket::set_cork(bool state)
-{
-#ifdef __APPLE__
- return false;
-#else
- int iCork = state ? 1 : 0;
- if(setsockopt(m_fd, IPPROTO_TCP, TCP_CORK, &iCork, sizeof(int))) {
- LOGERR("cxSocket: setsockopt(TCP_CORK) failed");
- return false;
- }
- return true;
-#endif
-}
-
-bool cxSocket::set_nodelay(bool state)
-{
- int i = state ? 1 : 0;
- if(setsockopt(m_fd, IPPROTO_TCP, TCP_NODELAY, &i, sizeof(int))) {
- LOGERR("cxSocket: setsockopt(TCP_NODELAY) failed");
- return false;
- }
- return true;
-}
-
-ssize_t cxSocket::tx_buffer_size(void)
-{
- socklen_t l = sizeof(int);
- int wmem = -1;
- if(getsockopt(m_fd, SOL_SOCKET, SO_SNDBUF, &wmem, &l)) {
- LOGERR("getsockopt(SO_SNDBUF) failed");
- return (ssize_t)-1;
- }
- return (ssize_t)wmem;
-}
-
-ssize_t cxSocket::tx_buffer_free(void)
-{
- int wmem = tx_buffer_size();
- int size = -1;
- if(ioctl(m_fd, TIOCOUTQ, &size)) {
- LOGERR("ioctl(TIOCOUTQ) failed");
- return (ssize_t)-1;
- }
-
- return (ssize_t)(wmem - size);
-}
-
-int cxSocket::getsockname(struct sockaddr *name, socklen_t *namelen)
-{
- return ::getsockname(m_fd, name, namelen);
-}
-
-int cxSocket::getpeername(struct sockaddr *name, socklen_t *namelen)
-{
- return ::getpeername(m_fd, name, namelen);
-}
-
-ssize_t cxSocket::send(const void *buf, size_t size, int flags,
- const struct sockaddr *to, socklen_t tolen)
-{
- return ::sendto(m_fd, buf, size, flags, to, tolen);
-}
-
-ssize_t cxSocket::recv(void *buf, size_t size, int flags,
- struct sockaddr *from, socklen_t *fromlen)
-{
- return ::recvfrom(m_fd, buf, size, flags, from, fromlen);
-}
-
-ssize_t cxSocket::write(const void *buffer, size_t size,
- int timeout_ms)
-{
- ssize_t written = (ssize_t)size;
- const unsigned char *ptr = (const unsigned char *)buffer;
- cPoller poller(m_fd, true);
-
- while (size > 0) {
- errno = 0;
- if(!poller.Poll(timeout_ms)) {
- LOGERR("cxSocket::write: poll() failed");
- return written-size;
- }
-
- errno = 0;
- ssize_t p = ::write(m_fd, ptr, size);
-
- if (p <= 0) {
- if (errno == EINTR || errno == EAGAIN) {
- LOGDBG("cxSocket::write: EINTR during write(), retrying");
- continue;
- }
- LOGERR("cxSocket::write: write() error");
- return p;
- }
-
- ptr += p;
- size -= p;
- }
-
- return written;
-}
-
-ssize_t cxSocket::read(void *buffer, size_t size, int timeout_ms)
-{
- ssize_t missing = (ssize_t)size;
- unsigned char *ptr = (unsigned char *)buffer;
- cPoller poller(m_fd);
-
- while (missing > 0) {
-
- if(!poller.Poll(timeout_ms)) {
- LOGERR("cxSocket::read: poll() failed at %d/%d", (int)(size-missing), (int)size);
- return size-missing;
- }
-
- errno = 0;
- ssize_t p = ::read(m_fd, ptr, missing);
-
- if (p <= 0) {
- if (errno == EINTR || errno == EAGAIN) {
- LOGDBG("cxSocket::read: EINTR/EAGAIN during read(), retrying");
- continue;
- }
- LOGERR("cxSocket::read: read() error at %d/%d", (int)(size-missing), (int)size);
- return size-missing;
- }
-
- ptr += p;
- missing -= p;
- }
-
- return size;
-}
-
-ssize_t cxSocket::printf(const char *fmt, ...)
-{
- va_list argp;
- char buf[1024];
- int r;
-
- va_start(argp, fmt);
- r = vsnprintf(buf, sizeof(buf), fmt, argp);
- if(r<0)
- LOGERR("cxSocket::printf: vsnprintf failed");
- else if(r >= (int)sizeof(buf))
- LOGMSG("cxSocket::printf: vsnprintf overflow (%20s)", buf);
- else
- return write(buf, r);
-
- return (ssize_t)-1;
-}
-
-/* readline return value:
- * <0 : failed
- * >=maxsize : buffer overflow
- * >=0 : if errno = EAGAIN -> line is not complete (there was timeout)
- * if errno = 0 -> succeed
- * (return value 0 indicates empty line "\r\n")
- */
-ssize_t cxSocket::readline(char *buf, int bufsize, int timeout, int bufpos)
-{
- int n = -1, cnt = bufpos;
- cPoller p(m_fd);
-
- do {
- if(timeout>0 && !p.Poll(timeout)) {
- errno = EAGAIN;
- return cnt;
- }
-
- while((n = ::read(m_fd, buf+cnt, 1)) == 1) {
- buf[++cnt] = 0;
-
- if( cnt > 1 && buf[cnt - 2] == '\r' && buf[cnt - 1] == '\n') {
- cnt -= 2;
- buf[cnt] = 0;
- errno = 0;
- return cnt;
- }
-
- if( cnt >= bufsize) {
- LOGMSG("cxSocket::readline: too long control message (%d bytes): %20s", cnt, buf);
- errno = 0;
- return bufsize;
- }
- }
-
- /* connection closed ? */
- if (n == 0) {
- LOGMSG("cxSocket::readline: disconnected");
- if(errno == EAGAIN)
- errno = ENOTCONN;
- return -1;
- }
-
- } while (timeout>0 && n<0 && errno == EAGAIN);
-
- if(errno == EAGAIN)
- return cnt;
-
- LOGERR("cxSocket::readline: read failed");
- return n;
-}
-
-#include <sys/ioctl.h>
-#include <net/if.h>
-
-uint32_t cxSocket::get_local_address(char *ip_address)
-{
- uint32_t local_addr = 0;
- struct ifconf conf;
- struct ifreq buf[3];
- unsigned int n;
-
- struct sockaddr_in sin;
- socklen_t len = sizeof(sin);
-
- if(!getsockname((struct sockaddr *)&sin, &len)) {
- local_addr = sin.sin_addr.s_addr;
-
- } else {
- //LOGERR("getsockname failed");
-
- // scan network interfaces
-
- conf.ifc_len = sizeof(buf);
- conf.ifc_req = buf;
- memset(buf, 0, sizeof(buf));
-
- errno = 0;
- if(ioctl(m_fd, SIOCGIFCONF, &conf) < 0)
- LOGERR("cxSocket: can't obtain socket local address");
- else {
- for(n=0; n<conf.ifc_len/sizeof(struct ifreq); n++) {
- struct sockaddr_in *in = (struct sockaddr_in *) &buf[n].ifr_addr;
-# if 0
- uint32_t tmp = ntohl(in->sin_addr.s_addr);
- LOGMSG("Local address %6s %d.%d.%d.%d",
- conf.ifc_req[n].ifr_name,
- ((tmp>>24)&0xff), ((tmp>>16)&0xff),
- ((tmp>>8)&0xff), ((tmp)&0xff));
-# endif
- if(n==0 || local_addr == htonl(INADDR_LOOPBACK))
- local_addr = in->sin_addr.s_addr;
- else
- break;
- }
- }
- }
-
- if(!local_addr)
- LOGERR("No local address found");
-
- if(ip_address)
- cxSocket::ip2txt(local_addr, 0, ip_address);
-
- return local_addr;
-}
-
-char *cxSocket::ip2txt(uint32_t ip, unsigned int port, char *str)
-{
- // inet_ntoa is not thread-safe (?)
- if(str) {
- unsigned int iph =(unsigned int)ntohl(ip);
- unsigned int porth =(unsigned int)ntohs(port);
- if(!porth)
- sprintf(str, "%d.%d.%d.%d",
- ((iph>>24)&0xff), ((iph>>16)&0xff),
- ((iph>>8)&0xff), ((iph)&0xff));
- else
- sprintf(str, "%u.%u.%u.%u:%u",
- ((iph>>24)&0xff), ((iph>>16)&0xff),
- ((iph>>8)&0xff), ((iph)&0xff),
- porth);
- }
- return str;
-}
diff --git a/tools/cxsocket.h b/tools/cxsocket.h
deleted file mode 100644
index 92954f3c..00000000
--- a/tools/cxsocket.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * cxsocket.h: Socket wrapper classes
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: cxsocket.h,v 1.20 2007-01-20 17:24:40 phintuka Exp $
- *
- */
-
-#ifndef __CXSOCKET_H
-#define __CXSOCKET_H
-
-#include <inttypes.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#define CLOSESOCKET(fd) do { if(fd>=0) { ::close(fd); fd=-1; } } while(0)
-
-class cxSocket {
- private:
- int m_fd;
-
- cxSocket(const cxSocket& s) ;//{ m_fd = s.m_fd>=0 ? dup(s.m_fd) : -1; }
- cxSocket &operator=(const cxSocket &S)
- ;// { close(); m_fd = S.m_fd >= 0 ? dup(S.m_fd) : -1; return *this; };
-
- public:
-
- typedef enum {
- estSTREAM = SOCK_STREAM,
- estDGRAM = SOCK_DGRAM
- } eSockType;
-
- cxSocket() : m_fd(-1) {}
- cxSocket(eSockType type) : m_fd(::socket(PF_INET, (int)type, 0)) {}
-
- ~cxSocket() { CLOSESOCKET(m_fd); }
-
- //operator int () const { return Handle(); }
- //operator bool () const { return open(); }
- //bool operator==(const cxSocket &s) { return m_fd == s.m_fd; }
-
- int handle(bool take_ownership=false)
- { int r=m_fd; if(take_ownership) m_fd=-1; return r; }
- void set_handle(int h) { if(h != m_fd) {close(); m_fd = h;} }
- bool create(eSockType type) { close(); return (m_fd=::socket(PF_INET, (int)type, 0)) >= 0; }
- bool open(void) const { return m_fd>0; }
- void close(void) { CLOSESOCKET(m_fd); }
-
- ssize_t send(const void *buf, size_t size, int flags=0,
- const struct sockaddr *to = NULL, socklen_t tolen = 0);
- ssize_t recv(void *buf, size_t size, int flags = 0,
- struct sockaddr *from = NULL, socklen_t *fromlen = NULL);
- ssize_t sendfile(int fd_file, off_t *offset, size_t count);
-
- ssize_t read(void *buffer, size_t size, int timeout_ms = -1);
- ssize_t write(const void *buffer, size_t size, int timeout_ms = -1);
-
- ssize_t printf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
- ssize_t write_str(const char *str, int timeout_ms=-1, int len=0)
- { return write(str, len ?: strlen(str), timeout_ms); }
- ssize_t write_cmd(const char *str, int len=0)
- { return write(str, len ?: strlen(str), 10); }
-
-/* readline return value:
- * <0 : failed
- * >=maxsize : buffer overflow
- * >=0 : if errno = EAGAIN -> line is not complete (there was timeout)
- * if errno = 0 -> succeed
- * (return value 0 indicates empty line "\r\n")
- */
- ssize_t readline(char *buf, int bufsize, int timeout=0, int bufpos=0);
-
- bool set_buffers(int Tx, int Rx);
- bool set_multicast(int ttl);
- bool set_blocking(bool state);
- bool set_cork(bool state);
- bool flush_cork(void) { return set_nodelay(true); };
- bool set_nodelay(bool state);
- ssize_t tx_buffer_size(void);
- ssize_t tx_buffer_free(void);
- int getsockname(struct sockaddr *name, socklen_t *namelen);
- int getpeername(struct sockaddr *name, socklen_t *namelen);
-
-
- bool connect(struct sockaddr *addr, socklen_t len);
- bool connect(const char *ip, int port);
-
- uint32_t get_local_address(char *ip_address);
-
- static char *ip2txt(uint32_t ip, unsigned int port, char *str);
-};
-
-
-#include <vdr/tools.h>
-
-class cxPoller : public cPoller {
- public:
- cxPoller(cxSocket& Sock, bool Out=false) : cPoller(Sock.handle(), Out) {};
-
- cxPoller(cxSocket* Socks, int count, bool Out=false)
- {
- for(int i=0; i<count; i++)
- Add(Socks[i].handle(), Out);
- }
-};
-
-//
-// Set socket buffers
-//
-static inline void set_socket_buffers(int s, int txbuf, int rxbuf)
-{
- int max_buf = txbuf;
- /*while(max_buf) {*/
- errno = 0;
- if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, &max_buf, sizeof(int))) {
- LOGERR("setsockopt(SO_SNDBUF,%d) failed", max_buf);
- /*max_buf >>= 1;*/
- }
- /*else {*/
- int tmp = 0;
- int len = sizeof(int);
- errno = 0;
- if(getsockopt(s, SOL_SOCKET, SO_SNDBUF, &tmp, (socklen_t*)&len)) {
- LOGERR("getsockopt(SO_SNDBUF,%d) failed", max_buf);
- /*break;*/
- } else if(tmp != max_buf) {
- LOGDBG("setsockopt(SO_SNDBUF): got %d bytes", tmp);
- /*max_buf >>= 1;*/
- /*continue;*/
- }
- /*}*/
- /*}*/
-
- max_buf = rxbuf;
- setsockopt(s, SOL_SOCKET, SO_RCVBUF, &max_buf, sizeof(int));
-}
-
-//
-// Connect data socket to client (take address from fd_control)
-//
-static inline int sock_connect(int fd_control, int port, int type)
-{
- struct sockaddr_in sin;
- socklen_t len = sizeof(sin);
- int s, one = 1;
-
- if(getpeername(fd_control, (struct sockaddr *)&sin, &len)) {
- LOGERR("sock_connect: getpeername failed");
- return -1;
- }
-
- uint32_t tmp = ntohl(sin.sin_addr.s_addr);
- LOGMSG("Client address: %d.%d.%d.%d",
- ((tmp>>24)&0xff), ((tmp>>16)&0xff),
- ((tmp>>8)&0xff), ((tmp)&0xff));
-
-#if 0
- if ((h = gethostbyname(tmp)) == NULL) {
- LOGDBG("sock_connect: unable to resolve host name", tmp);
- }
-#endif
-
- if ((s = socket(PF_INET, type,
- type==SOCK_DGRAM?IPPROTO_UDP:IPPROTO_TCP)) < 0) {
- LOGERR("sock_connect: failed to create socket");
- return -1;
- }
-
- // Set socket buffers: large send buffer, small receive buffer
- set_socket_buffers(s, KILOBYTE(256), 2048);
-
- if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int)) < 0)
- LOGERR("sock_connect: setsockopt(SO_REUSEADDR) failed");
-
- sin.sin_family = AF_INET;
- sin.sin_port = htons(port);
-
- if (connect(s, (struct sockaddr *)&sin, sizeof(sin))==-1 &&
- errno != EINPROGRESS) {
- LOGERR("connect() failed");
- CLOSESOCKET(s);
- }
-
- if (fcntl (s, F_SETFL, fcntl (s, F_GETFL) | O_NONBLOCK) == -1) {
- LOGERR("can't put socket in non-blocking mode");
- CLOSESOCKET(s);
- return -1;
- }
-
- return s;
-}
-
-#endif // __CXSOCKET_H
diff --git a/tools/debug_mutex.h b/tools/debug_mutex.h
deleted file mode 100644
index 0802c7cc..00000000
--- a/tools/debug_mutex.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * debug_mutex.h: debugging wrappers for pthread_mutex_ functions
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: debug_mutex.h,v 1.3 2007-03-14 11:50:08 phintuka Exp $
- *
- */
-
-#ifndef DEBUG_MUTEX_H
-#define DEBUG_MUTEX_H
-
-#ifndef _PTHREAD_H
-# error pthread.h must be included before debug_mutex.h
-#endif
-
-/*
- * Override pthread_mutex_ calls:
- *
- * Change type of each mutex to PTHREAD_MUTEX_ERRORCHECK_NP
- *
- * Store line number of last succeed pthread_mutex_lock call
- * for each initialized mutex
- *
- * Check every pthread_mutex_ call for errors and log all errors
- *
- * To help detecting deadlocks and minimize logging:
- * - Try locking first in pthread_mutex_lock
- * - If pthread_mutex_trylock fails, log a message and retry.
- * - When trylock failed, log another message when lock is acquired.
- *
- *
- * NOTE: debugging itself is not thread-safe and may indicate wrong line numbers !
- *
- */
-
-#define MAX_DBG_MUTEX 64
-static struct {
- pthread_mutex_t *lock;
- int line;
- int tid;
-} dbgdata[MAX_DBG_MUTEX+1] = {{NULL,0}};
-
-static void dbg_setdata(pthread_mutex_t *mutex, int line)
-{
- int i;
- for(i=0; i<MAX_DBG_MUTEX; i++)
- if(dbgdata[i].lock == mutex) {
- dbgdata[i].line = line;
- dbgdata[i].tid = syscall(__NR_gettid);
- return;
- }
-
- LOGMSG("********** dbg_setdata: new entry (0x%lx at %d)", (unsigned long int)mutex, line);
- for(i=0; i<MAX_DBG_MUTEX; i++)
- if(!dbgdata[i].lock) {
- dbgdata[i].lock = mutex;
- dbgdata[i].line = line;
- dbgdata[i].tid = syscall(__NR_gettid);
- return;
- }
-
- LOGMSG("********** dbg_setdata: table full !");
-}
-
-static int dbg_getdata(pthread_mutex_t *mutex, int line)
-{
- int i;
- for(i=0; i<MAX_DBG_MUTEX; i++)
- if(dbgdata[i].lock == mutex)
- return dbgdata[i].line;
-
- LOGMSG("********** dbg_getdata: NO ENTRY ! (%d)", line);
- return -1;
-}
-
-static void dbg_deldata(pthread_mutex_t *mutex, int line)
-{
- int i;
- for(i=0; i<MAX_DBG_MUTEX; i++)
- if(dbgdata[i].lock == mutex) {
- dbgdata[i].lock = NULL;
- return;
- }
-
- LOGMSG("********** dbg_deldata: NO ENTRY ! (%d)", line);
- return;
-}
-
-static int dbg_init(pthread_mutex_t *mutex, pthread_mutexattr_t *pattr, int line)
-{
- int r;
-
- errno = 0;
- if(!pattr) {
- pthread_mutexattr_t attr;
- pthread_mutexattr_init(&attr);
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
- r = pthread_mutex_init(mutex, &attr);
- } else {
- LOGMSG("********** dbg_init: mutex attribute already given !");
- r = pthread_mutex_init(mutex, pattr);
- }
-
- if(r)
- LOGERR("********** dbg_init: pthread_mutex_init FAILED at %d", line);
-
- dbg_setdata(mutex, line);
-
- return r;
-}
-
-static int dbg_free(pthread_mutex_t *mutex, int line)
-{
- int r;
-
- errno = 0;
- r = pthread_mutex_destroy(mutex);
-
- if(r)
- LOGERR("********** dbg_free: pthread_mutex_destroy FAILED at %d ; last lock at %d",
- line, dbg_getdata(mutex, line));
- dbg_deldata(mutex, line);
-
- return r;
-}
-
-static int dbg_lock(pthread_mutex_t *mutex, int line)
-{
- int r;
- /*struct timespec abs_timeout;*/
-
- /* try lock first to reduce logging */
- errno = 0;
- r = pthread_mutex_trylock(mutex);
- if(!r) {
- dbg_setdata(mutex,line);
- return r;
- }
-
- /* try failed - we're going to wait, so log at wait start and end to detect deadlocks */
- LOGERR("********** dbg_lock: pthread_mutex_trylock failed at %d (locked at %d)",
- line, dbg_getdata(mutex, line));
-
- /* int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,
- const struct timespec *restrict abs_timeout); */
-
- errno = 0;
- r = pthread_mutex_lock(mutex);
-
- if(r)
- LOGERR("********** dbg_lock: pthread_mutex_lock FAILED at %d", line);
-
- dbg_setdata(mutex, line);
- LOGMSG("********** dbg_lock: pthread_mutex_lock done at %d", line);
-
- return r;
-}
-
-static int dbg_trylock(pthread_mutex_t *mutex, int line)
-{
- int r;
- /*struct timespec abs_timeout;*/
-
- /* try lock first to reduce logging */
- errno = 0;
- r = pthread_mutex_trylock(mutex);
- if(!r) {
- dbg_setdata(mutex,line);
- return r;
- }
-
- LOGERR("********** dbg_trylock: pthread_mutex_trylock failed at %d (locked at %d)",
- line, dbg_getdata(mutex, line));
-
- return r;
-}
-
-static int dbg_unlock(pthread_mutex_t *mutex, int line)
-{
- int r;
-
- errno = 0;
- r = pthread_mutex_unlock(mutex);
-
- if(r)
- LOGERR("********** dbg_unlock: pthread_mutex_unlock FAILED at %d (last locket at %d)",
- line, dbg_getdata(mutex, line));
-
- //else
- // dbg_setdata(mutex, 0);
-
- return r;
-}
-
-/* override pthread_ functions with own ones */
-#define pthread_mutex_init(l,a) dbg_init(l, a, __LINE__)
-#define pthread_mutex_lock(l) dbg_lock(l, __LINE__)
-#define pthread_mutex_trylock(l) dbg_trylock(l, __LINE__)
-#define pthread_mutex_unlock(l) dbg_unlock(l, __LINE__)
-#define pthread_mutex_destroy(l) dbg_free(l, __LINE__)
-
-#else
-# error debug_mutex.h included twice
-#endif /* DEBUG_MUTEX_H */
diff --git a/tools/display_message.h b/tools/display_message.h
deleted file mode 100644
index 407f07c8..00000000
--- a/tools/display_message.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * display_message.h: Display simple message
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: display_message.h,v 1.2 2007-01-06 04:28:08 phintuka Exp $
- *
- */
-
-#ifndef __DISPLAY_MESSAGE_H
-#define __DISPLAY_MESSAGE_H
-
-#include <vdr/osdbase.h>
-#include <vdr/skins.h>
-
-class cDisplayMessage : public cOsdObject
-{
- cSkinDisplayMessage *displayMessage;
- char *Message;
- int Timer;
- int Timeout;
-
- public:
-
- cDisplayMessage(const char *message, int timeout = 3)
- {
- displayMessage = NULL;
- Message = strdup(message);
- Timer = 0;
- Timeout = timeout;
- }
-
- virtual ~cDisplayMessage()
- {
- delete displayMessage;
- free(Message);
- }
-
- void Update(const char *message)
- {
- Timer = 0;
- free(Message);
- Message = strdup(message);
- Show();
- }
-
- virtual eOSState ProcessKey(eKeys Key)
- {
- if(Key == kNone && Timer++ > Timeout)
- return osEnd;
-
- if(Key != kNone) {
- // put back and close
- cRemote::Put(Key, true);
- return osEnd;
- }
-
- return osContinue;
- }
-
- virtual void Show(void)
- {
- if(!displayMessage)
- displayMessage = Skins.Current()->DisplayMessage();
-
- displayMessage->SetMessage(mtInfo, Message);
- displayMessage->Flush();
- }
-
-};
-
-#endif
diff --git a/tools/functor.h b/tools/functor.h
deleted file mode 100644
index 0dadf1fc..00000000
--- a/tools/functor.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * functor.h:
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: functor.h,v 1.1 2006-08-24 23:25:07 phintuka Exp $
- *
- */
-
-#ifndef __XINELIB_FUNCTOR_H
-#define __XINELIB_FUNCTOR_H
-
-#include <vdr/tools.h>
-
-
-class cFunctor : public cListObject
-{
- public:
- cFunctor() : cListObject() {}
- virtual ~cFunctor() {}
- virtual void Execute(void) = 0;
-};
-
-#if 1 /* gcc 3.3.x (?) does not accept class TRESULT=void */
-template<class TCLASS>
-cFunctor *CreateFunctor(TCLASS *c,
- void (TCLASS::*fp)(void));
-
-template<class TCLASS, class TARG1>
-cFunctor *CreateFunctor(TCLASS *c,
- void (TCLASS::*fp)(TARG1),
- TARG1 arg1);
-#endif
-
-template<class TCLASS, class TRESULT>
-cFunctor *CreateFunctor(TCLASS *c,
- TRESULT (TCLASS::*fp)(void));
-
-template<class TCLASS, class TRESULT, class TARG1>
-cFunctor *CreateFunctor(TCLASS *c,
- TRESULT (TCLASS::*fp)(TARG1),
- TARG1 arg1);
-
-#include "functorimpl.h"
-
-#endif
diff --git a/tools/functorimpl.h b/tools/functorimpl.h
deleted file mode 100644
index 2d3504e6..00000000
--- a/tools/functorimpl.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * functorimpl.h:
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: functorimpl.h,v 1.1 2006-08-24 23:25:07 phintuka Exp $
- *
- */
-
-#ifndef __XINELIB_FUNCTORIMPL_H
-
-#ifndef __XINELIB_FUNCTOR_H
-# error functorimpl.h should not be included, use functor.h instead
-#endif
-
-#if 1 /* gcc 3.3.x (?) does not accept class TRESULT=void */
-template <class TCLASS>
-class cFunctor0 : public cFunctor {
-
- public:
- protected:
-
- typedef void (TCLASS::*TFUNC)(void);
-
- cFunctor0(TCLASS *obj, TFUNC f) : m_obj(obj), m_f(f) {}
- virtual ~cFunctor0() {};
-
- virtual void Execute(void)
- {
- (*m_obj.*m_f)();
- }
-
- private:
- TCLASS *m_obj;
- TFUNC m_f;
-
- friend cFunctor *CreateFunctor<TCLASS>(TCLASS*,TFUNC);
-};
-
-template <class TCLASS, class TARG1>
-class cFunctor1 : public cFunctor {
-
- public:
-
- protected:
- typedef void (TCLASS::*TFUNC)(TARG1);
-
- cFunctor1(TCLASS *obj, TFUNC f, TARG1 arg1) :
- m_obj(obj), m_f(f), m_arg1(arg1) {}
- virtual ~cFunctor1() {};
-
- virtual void Execute(void)
- {
- (*m_obj.*m_f)(m_arg1);
- }
-
- private:
- TCLASS *m_obj;
- TFUNC m_f;
- TARG1 m_arg1;
-
- friend cFunctor *CreateFunctor<TCLASS,TARG1>(TCLASS*,TFUNC,TARG1);
-};
-#endif
-
-template <class TCLASS, class TRESULT>
-class cFunctorR0 : public cFunctor {
-
- public:
- protected:
-
- typedef TRESULT (TCLASS::*TFUNC)(void);
-
- cFunctorR0(TCLASS *obj, TFUNC f) : m_obj(obj), m_f(f) {}
- virtual ~cFunctorR0() {};
-
- virtual void Execute(void)
- {
- // TODO: use future to pass back value
- (void) (*m_obj.*m_f)();
- }
-
- private:
- TCLASS *m_obj;
- TFUNC m_f;
-
- friend cFunctor *CreateFunctor<TCLASS,TRESULT>(TCLASS*,TFUNC);
-};
-
-template <class TCLASS, class TRESULT, class TARG1>
-class cFunctorR1 : public cFunctor {
-
- public:
- protected:
-
- typedef TRESULT (TCLASS::*TFUNC)(TARG1);
-
- cFunctorR1(TCLASS *obj, TFUNC f, TARG1 arg1) :
- m_obj(obj), m_f(f), m_arg1(arg1) {}
- virtual ~cFunctorR1() {};
-
- virtual void Execute(void)
- {
- // TODO: use future to pass back value
- (void) (*m_obj.*m_f)(m_arg1);
- }
-
- private:
- TCLASS *m_obj;
- TFUNC m_f;
- TARG1 m_arg1;
-
- friend cFunctor *CreateFunctor<TCLASS,TRESULT>(TCLASS*,TFUNC,TARG1);
-};
-
-#if 1 /* gcc 3.3.x (?) does not accept class TRESULT=void */
-template<class TCLASS>
-cFunctor *CreateFunctor(TCLASS *c,
- void (TCLASS::*fp)(void))
-{
- return new cFunctor0<TCLASS>(c, fp);
-}
-
-template<class TCLASS, class TARG1>
-cFunctor *CreateFunctor(TCLASS *c,
- void (TCLASS::*fp)(TARG1),
- TARG1 arg1)
-{
- return new cFunctor1<TCLASS,TARG1>(c, fp, arg1);
-}
-#endif
-
-template<class TCLASS, class TRESULT>
-cFunctor *CreateFunctor(TCLASS *c,
- TRESULT (TCLASS::*fp)(void))
-{
- return new cFunctorR0<TCLASS,TRESULT>(c, fp);
-}
-
-template<class TCLASS, class TRESULT, class TARG1>
-cFunctor *CreateFunctor(TCLASS *c,
- TRESULT (TCLASS::*fp)(TARG1),
- TARG1 arg1)
-{
- return new cFunctorR1<TCLASS,TRESULT,TARG1>(c, fp, arg1);
-}
-
-
-#endif
diff --git a/tools/future.h b/tools/future.h
deleted file mode 100644
index bdd0498c..00000000
--- a/tools/future.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * future.h: A variable that gets its value in future.
- * Used to convert asynchronous IPCs to synchronous.
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: future.h,v 1.2 2006-08-19 23:44:07 phintuka Exp $
- *
- */
-
-#ifndef __FUTURE_H
-#define __FUTURE_H
-
-#include <vdr/thread.h>
-
-template <class T>
-class cFuture {
-
- private:
- cMutex mutex;
- cCondVar cond;
- bool m_Ready;
- T m_Value;
-
- public:
-
- cFuture()
- {
- m_Ready = false;
- }
-
- void Reset(void)
- {
- cMutexLock l(&mutex);
- m_Ready = false;
- }
-
- //
- // Producer interface
- //
-
- void Set(T& Value)
- {
- cMutexLock l(&mutex);
- m_Value = Value;
- m_Ready = true;
- cond.Broadcast();
- }
-
- //
- // Consumer interface
- //
-
- bool Wait(int Timeout = -1)
- {
- cMutexLock l(&mutex);
-
- if(Timeout==0 || m_Ready)
- return m_Ready;
-
- if(Timeout >= 0)
- return cond.TimedWait(mutex, Timeout) && m_Ready;
-
- while(!m_Ready)
- cond.Wait(mutex);
-
- return m_Ready;
- }
-
- bool IsReady(void)
- {
- cMutexLock l(&mutex);
- return m_Ready;
- }
-
- T Value(void)
- {
- cMutexLock l(&mutex);
- while(!m_Ready)
- cond.Wait(mutex);
- return m_Value;
- }
-};
-
-
-#endif // __FUTURE_H
diff --git a/tools/general_remote.h b/tools/general_remote.h
deleted file mode 100644
index aed60463..00000000
--- a/tools/general_remote.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * general_remote.h:
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: general_remote.h,v 1.1 2006-06-03 10:04:27 phintuka Exp $
- *
- */
-
-#ifndef __GENERAL_REMOTE_H
-#define __GENERAL_REMOTE_H
-
-
-//----------------------------- cGeneralRemote --------------------------------
-
-#include <vdr/remote.h>
-
-class cGeneralRemote : public cRemote {
- public:
- cGeneralRemote(const char *Name) : cRemote(Name) {};
- bool Put(const char *Code, bool Repeat=false, bool Release=false)
- { return cRemote::Put(Code, Repeat, Release); };
-};
-
-
-#endif
diff --git a/tools/gnome_screensaver.c b/tools/gnome_screensaver.c
deleted file mode 100644
index a23d4236..00000000
--- a/tools/gnome_screensaver.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * gnome_screensaver.c v0.0.7
- *
- * Enable/Disable the GNOME screensaver
- * Supports GNOME screensaver API 2.14 and 2.15
- *
- * Call gnome_screensaver_control(1) to enable and
- * gnome_screensaver_control(0) to disable
- *
- */
-/*
- * Orginally written for mplayer by Piotr Kaczuba
- * (http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/2006-April/042661.html)
- *
- * Modified for xineliboutput by Alex Stansfield
- * (http://www.linuxtv.org/pipermail/vdr/2007-July/013458.html)
- */
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <dbus/dbus-glib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-
-#define LOG_MODULENAME "[vdr-fe] "
-#include "../logdefs.h"
-
-#include "gnome_screensaver.h"
-
-#define GS_SERVICE "org.gnome.ScreenSaver"
-#define GS_PATH "/org/gnome/ScreenSaver"
-#define GS_INTERFACE "org.gnome.ScreenSaver"
-
-#define GS_APPLICATION_NAME "vdr-sxfe"
-#define GS_REASON_FOR_INHIBIT "Watching TV"
-
-/* Log Messages */
-#define MSG_OpenBusConnectionError "Failed to open connection to bus: %s"
-#define MSG_RemoteMethodException "Caught remote method exception %s: %s"
-#define MSG_GnomeAPI215Failed "GNOME screensaver 2.15 API failed, trying 2.14 API"
-#define MSG_GError "Error: %s"
-#define MSG_GNOMEScreensaverEnabled "GNOME screensaver enabled"
-#define MSG_GNOMEScreensaverDisabled "GNOME screensaver disabled"
-
-static guint32 cookie;
-
-void gnome_screensaver_control(int enable)
-{
- DBusGConnection *connection;
- GError *error;
- DBusGProxy *proxy;
- gboolean ret;
-
- g_type_init();
-
- /* Get a connection to the session bus */
- error = NULL;
- connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
- if (!connection) {
- LOGERR(MSG_OpenBusConnectionError, error ? error->message : "<null>");
- g_error_free(error);
- return;
- }
-
- /* Create a proxy object */
- proxy = dbus_g_proxy_new_for_name(connection,
- GS_SERVICE, GS_PATH, GS_INTERFACE);
- if (!proxy) {
- LOGDBG("Failed to get a proxy for gnome-screensaver");
- return;
- }
-
- /* Enable the screensaver */
- if (enable) {
- /* First call the GNOME screensaver 2.15 API method */
- error = NULL;
- ret =
- dbus_g_proxy_call(proxy, "UnInhibit", &error,
- G_TYPE_UINT, cookie,
- G_TYPE_INVALID, G_TYPE_INVALID);
-
- /* If this fails, try the GNOME screensaver 2.14 API */
- if (!ret && error->domain == DBUS_GERROR
- && error->code == DBUS_GERROR_UNKNOWN_METHOD) {
- LOGERR(MSG_GnomeAPI215Failed);
- g_error_free(error);
- error = NULL;
- ret =
- dbus_g_proxy_call(proxy, "AllowActivation", &error,
- G_TYPE_INVALID, G_TYPE_INVALID);
- }
- }
- /* Disable the screensaver */
- else {
- /* First call the GNOME screensaver 2.15 API method */
- error = NULL;
- ret =
- dbus_g_proxy_call(proxy, "Inhibit", &error,
- G_TYPE_STRING, GS_APPLICATION_NAME,
- G_TYPE_STRING, GS_REASON_FOR_INHIBIT,
- G_TYPE_INVALID,
- G_TYPE_UINT, &cookie,
- G_TYPE_INVALID);
-
- /* If this fails, try the GNOME screensaver 2.14 API */
- if (!ret && error->domain == DBUS_GERROR
- && error->code == DBUS_GERROR_UNKNOWN_METHOD) {
- LOGERR(MSG_GnomeAPI215Failed);
- g_error_free(error);
- error = NULL;
- ret =
- dbus_g_proxy_call(proxy, "InhibitActivation", &error,
- G_TYPE_STRING, GS_REASON_FOR_INHIBIT,
- G_TYPE_INVALID, G_TYPE_INVALID);
- }
- }
-
- if (!ret) {
- /* Check if it's a remote exception or a regular GError */
- if (error->domain == DBUS_GERROR
- && error->code == DBUS_GERROR_REMOTE_EXCEPTION) {
- LOGERR(MSG_RemoteMethodException, dbus_g_error_get_name(error), error->message);
- }
- else {
- LOGERR(MSG_GError, error->message);
- }
- g_error_free(error);
- }
- else {
- LOGMSG(enable ? MSG_GNOMEScreensaverEnabled : MSG_GNOMEScreensaverDisabled);
- }
-
- g_object_unref(proxy);
-}
diff --git a/tools/gnome_screensaver.h b/tools/gnome_screensaver.h
deleted file mode 100644
index 84dee38e..00000000
--- a/tools/gnome_screensaver.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _GNOME_SCREENSAVER_H
-#define _GNOME_SCREENSAVER_H
-
-extern void gnome_screensaver_control(int enable);
-
-#endif /* !_GNOME_SCREENSAVER_H */
diff --git a/tools/h264.c b/tools/h264.c
deleted file mode 100644
index a729a289..00000000
--- a/tools/h264.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * h264.c: H.264 bitstream decoding
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: h264.c,v 1.7 2009-03-31 11:33:05 phintuka Exp $
- *
- */
-
-#include <stdint.h>
-#include <string.h>
-
-#ifndef LOG_MODULENAME
-# define LOG_MODULENAME "[h264 ] "
-# define SysLogLevel iSysLogLevel
-# include "../logdefs.h"
-#endif
-
-#define NOCACHE 1
-#include "bitstream.h"
-
-#include "mpeg.h"
-#include "h264.h"
-
-
-int h264_parse_sps(const uint8_t *buf, int len, h264_sps_data_t *sps)
-{
- br_state br = BR_INIT(buf, len);
- int profile_idc, pic_order_cnt_type;
- int frame_mbs_only;
- int i, j;
-
- profile_idc = br_get_u8(&br);
- LOGDBG("H.264 SPS: profile_idc %d", profile_idc);
- /* constraint_set0_flag = br_get_bit(br); */
- /* constraint_set1_flag = br_get_bit(br); */
- /* constraint_set2_flag = br_get_bit(br); */
- /* constraint_set3_flag = br_get_bit(br); */
- /* reserved = br_get_bits(br,4); */
- /* level_idc = br_get_u8(br); */
- br_skip_bits(&br, 16);
- br_skip_ue_golomb(&br); /* seq_parameter_set_id */
- if (profile_idc >= 100) {
- if (br_get_ue_golomb(&br) == 3) /* chroma_format_idc */
- br_skip_bit(&br); /* residual_colour_transform_flag */
- br_skip_ue_golomb(&br); /* bit_depth_luma - 8 */
- br_skip_ue_golomb(&br); /* bit_depth_chroma - 8 */
- br_skip_bit(&br); /* transform_bypass */
- if (br_get_bit(&br)) /* seq_scaling_matrix_present */
- for (i = 0; i < 8; i++)
- if (br_get_bit(&br)) { /* seq_scaling_list_present */
- int last = 8, next = 8, size = (i<6) ? 16 : 64;
- for (j = 0; j < size; j++) {
- if (next)
- next = (last + br_get_se_golomb(&br)) & 0xff;
- last = next ?: last;
- }
- }
- }
-
- br_skip_ue_golomb(&br); /* log2_max_frame_num - 4 */
- pic_order_cnt_type = br_get_ue_golomb(&br);
- if (pic_order_cnt_type == 0)
- br_skip_ue_golomb(&br); /* log2_max_poc_lsb - 4 */
- else if (pic_order_cnt_type == 1) {
- br_skip_bit(&br); /* delta_pic_order_always_zero */
- br_skip_se_golomb(&br); /* offset_for_non_ref_pic */
- br_skip_se_golomb(&br); /* offset_for_top_to_bottom_field */
- j = br_get_ue_golomb(&br); /* num_ref_frames_in_pic_order_cnt_cycle */
- for (i = 0; i < j; i++)
- br_skip_se_golomb(&br); /* offset_for_ref_frame[i] */
- }
- br_skip_ue_golomb(&br); /* ref_frames */
- br_skip_bit(&br); /* gaps_in_frame_num_allowed */
- sps->width /* mbs */ = br_get_ue_golomb(&br) + 1;
- sps->height /* mbs */ = br_get_ue_golomb(&br) + 1;
- frame_mbs_only = br_get_bit(&br);
- LOGDBG("H.264 SPS: pic_width: %u mbs", (unsigned) sps->width);
- LOGDBG("H.264 SPS: pic_height: %u mbs", (unsigned) sps->height);
- LOGDBG("H.264 SPS: frame only flag: %d", frame_mbs_only);
-
- sps->width *= 16;
- sps->height *= 16 * (2-frame_mbs_only);
-
- if (!frame_mbs_only)
- if (br_get_bit(&br)) /* mb_adaptive_frame_field_flag */
- LOGDBG("H.264 SPS: MBAFF");
- br_skip_bit(&br); /* direct_8x8_inference_flag */
- if (br_get_bit(&br)) { /* frame_cropping_flag */
- uint32_t crop_left = br_get_ue_golomb(&br);
- uint32_t crop_right = br_get_ue_golomb(&br);
- uint32_t crop_top = br_get_ue_golomb(&br);
- uint32_t crop_bottom = br_get_ue_golomb(&br);
- LOGDBG("H.264 SPS: cropping %d %d %d %d",
- crop_left, crop_top, crop_right, crop_bottom);
-
- sps->width -= 2*(crop_left + crop_right);
- if (frame_mbs_only)
- sps->height -= 2*(crop_top + crop_bottom);
- else
- sps->height -= 4*(crop_top + crop_bottom);
- }
-
- /* VUI parameters */
- sps->pixel_aspect.num = 0;
- if (br_get_bit(&br)) { /* vui_parameters_present flag */
- if (br_get_bit(&br)) { /* aspect_ratio_info_present */
- uint32_t aspect_ratio_idc = br_get_u8(&br);
- LOGDBG("H.264 SPS: aspect_ratio_idc %d", aspect_ratio_idc);
-
- if (aspect_ratio_idc == 255 /* Extended_SAR */) {
- sps->pixel_aspect.num = br_get_u16(&br); /* sar_width */
- sps->pixel_aspect.den = br_get_u16(&br); /* sar_height */
- LOGDBG("H.264 SPS: -> sar %dx%d", sps->pixel_aspect.num, sps->pixel_aspect.den);
- } else {
- static const mpeg_rational_t aspect_ratios[] =
- { /* page 213: */
- /* 0: unknown */
- {0, 1},
- /* 1...16: */
- { 1, 1}, {12, 11}, {10, 11}, {16, 11}, { 40, 33}, {24, 11}, {20, 11}, {32, 11},
- {80, 33}, {18, 11}, {15, 11}, {64, 33}, {160, 99}, { 4, 3}, { 3, 2}, { 2, 1}
- };
-
- if (aspect_ratio_idc < sizeof(aspect_ratios)/sizeof(aspect_ratios[0])) {
- memcpy(&sps->pixel_aspect, &aspect_ratios[aspect_ratio_idc], sizeof(mpeg_rational_t));
- LOGDBG("H.264 SPS: -> aspect ratio %d / %d", sps->pixel_aspect.num, sps->pixel_aspect.den);
- } else {
- LOGMSG("H.264 SPS: aspect_ratio_idc out of range !");
- }
- }
- }
- }
-
- LOGDBG("H.264 SPS: -> video size %dx%d, aspect %d:%d",
- sps->width, sps->height, sps->pixel_aspect.num, sps->pixel_aspect.den);
-
- if(BR_EOF(&br)) {
- LOGDBG("H.264 SPS: not enough data ?");
- return 0;
- }
- return 1;
-}
-
-static int h264_nal_unescape(uint8_t *dst, const uint8_t *src, int len)
-{
- int s = 0, d = 0;
- while (s < len) {
- if (!src[s] && !src[s+1]) {
- /* hit 00 00 xx */
- dst[d] = dst[d+1] = 0;
- s += 2;
- d += 2;
- if (src[s] == 3) {
- s++; /* 00 00 03 xx --> 00 00 xx */
- /*LOGDBG("h264_nal_unescape: hit 00 00 03 %02x", src[s]);*/
- if (s >= len)
- return d;
- } /* else if (src[s] == 0 || src[s] == 1) {
- LOGDBG("h264_nal_unescape: invalid NAL sequence 00 00 %02x %02x", src[s], src[s+1]);
- return -1;
- }*/
- }
- dst[d++] = src[s++];
- }
- return d;
-}
-
-int h264_get_picture_type(const uint8_t *buf, int len)
-{
- int i;
- for (i = 0; i < len-5; i++) {
- if (buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1 && buf[i + 3] == NAL_AUD) {
- uint8_t type = (buf[i + 4] >> 5);
- switch (type) {
- case 0: case 3: case 5: return I_FRAME;
- case 1: case 4: case 6: return P_FRAME;
- case 2: case 7: return B_FRAME;
- default:;
- }
- }
- }
- return NO_PICTURE;
-}
-
-int h264_get_video_size(const uint8_t *buf, int len, video_size_t *size)
-{
- int i;
-
- /* H.264 detection, search for NAL AUD */
- if (!IS_NAL_AUD(buf))
- return 0;
-
- /* if I-frame, search for NAL SPS */
- if (h264_get_picture_type(buf, len) != I_FRAME)
- return 0;
-
- /* scan video packet for sequence parameter set */
- for (i = 5; i < len-4; i++)
- if (buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1 && (buf[i + 3] & 0x1f) == NAL_SPS) {
-
- uint8_t nal_data[len];
- int nal_len;
-
- LOGDBG("H.264: Found NAL SPS at offset %d/%d", i, len);
-
- if (0 < (nal_len = h264_nal_unescape(nal_data, buf+i+4, len-i-4))) {
-
- h264_sps_data_t sps = {0};
-
- if (h264_parse_sps(nal_data, nal_len, &sps)) {
- size->width = sps.width;
- size->height = sps.height;
- memcpy(&size->pixel_aspect, &sps.pixel_aspect, sizeof(mpeg_rational_t));
- return 1;
- }
- LOGMSG("h264_get_video_size: not enough data ?");
- }
- }
-
- return 0;
-}
-
diff --git a/tools/h264.h b/tools/h264.h
deleted file mode 100644
index df869e96..00000000
--- a/tools/h264.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * h264.h: H.264 bitstream decoding
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: h264.h,v 1.9 2009-06-29 15:49:43 phintuka Exp $
- *
- */
-
-#ifndef _XINELIBOUTPUT_H264_H_
-#define _XINELIBOUTPUT_H264_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "mpeg.h"
-
-
-#define NAL_SPS 0x07 /* Sequence Parameter Set */
-#define NAL_AUD 0x09 /* Access Unit Delimiter */
-#define NAL_END_SEQ 0x0a /* End of Sequence */
-
-
-#if defined(__i386__) || defined(__x86_64__)
-# define IS_NAL_SPS(buf) (*(uint32_t*)(buf) == 0x07010000U)
-# define IS_NAL_AUD(buf) (*(uint32_t*)(buf) == 0x09010000U)
-# define IS_NAL_END_SEQ(buf) (*(uint32_t*)(buf) == 0x0a010000U)
-#else
-# define IS_NAL_SPS(buf) ((buf)[0] == 0 && (buf)[1] == 0 && (buf)[2] == 1 && (buf)[3] == NAL_SPS)
-# define IS_NAL_AUD(buf) ((buf)[0] == 0 && (buf)[1] == 0 && (buf)[2] == 1 && (buf)[3] == NAL_AUD)
-# define IS_NAL_END_SEQ(buf) ((buf)[0] == 0 && (buf)[1] == 0 && (buf)[2] == 1 && (buf)[3] == NAL_END_SEQ)
-#endif
-
-
-typedef struct {
- uint16_t width;
- uint16_t height;
- mpeg_rational_t pixel_aspect;
- /* ... */
-} h264_sps_data_t;
-
-struct video_size_s;
-
-
-/*
- * input: start of NAL SPS (without 00 00 01 07)
- */
-int h264_parse_sps(const uint8_t *buf, int len, h264_sps_data_t *sps);
-
-/*
- * input: start of H.264 video data (not PES)
- */
-int h264_get_picture_type(const uint8_t *buf, int len);
-
-/*
- * input: start of H.264 video data (not PES)
- */
-int h264_get_video_size(const uint8_t *buf, int len, struct video_size_s *size);
-
-
-#ifdef __cplusplus
-} /* extern "C" { */
-#endif
-
-
-#endif /* _XINELIBOUTPUT_H264_H_ */
diff --git a/tools/http.c b/tools/http.c
deleted file mode 100644
index 0e7de26a..00000000
--- a/tools/http.c
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- * http.c: HTTP (/RTSP) helper classes
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: http.c,v 1.7 2009-06-02 08:37:58 phintuka Exp $
- *
- */
-
-#define __STDC_FORMAT_MACROS
-#include <inttypes.h>
-
-#include <string.h>
-
-#include <vdr/config.h>
-#include <vdr/tools.h>
-
-#include "../logdefs.h"
-
-#include "http.h"
-
-//
-// cHttpReq
-//
-
-bool cHttpReq::SetCommand(const char *Command)
-{
- char *tmp = strdup(Command);
- char *pt = strchr(tmp, ' '), *uri;
-
- m_Valid = false;
- if(pt) {
- *pt++ = 0;
- m_Name = tmp;
-
- while(*pt && *pt == ' ') pt++;
-
- uri = pt;
- pt = strrchr(uri, ' ');
- if(pt) {
- m_Version = pt+1;
- while(*pt && *pt == ' ') *pt-- = 0;
- m_Uri = uri;
- m_Valid = true;
- }
- }
-
- free(tmp);
- return m_Valid;
-}
-
-cHeader *cHttpReq::Header(const char *Name)
-{
- for(cHeader *i = m_Headers.First(); i; i = m_Headers.Next(i))
- if(!strcmp(Name, i->Name()))
- return i;
- return NULL;
-}
-
-void cHttpReq::AddHeader(const char *Header, bool Duplicate)
-{
- if(strlen(Header) < 4096) {
- char *name = strdup(Header);
- char *val = strchr(name, ':');
- if(val) {
- *val++ = 0;
- while(*val == ' ') val++;
- AddHeader(name, val, Duplicate);
- }
- free(name);
- } else {
- LOGMSG("cConnState::AddHeader: header length exceeds 4096 !");
- }
-}
-
-void cHttpReq::AddHeader(const char *Name, const char *Value, bool Duplicate)
-{
- if(strlen(Name) > 64 || strlen(Value) > 4096) {
- LOGMSG("cConnState::AddHeader: header length exceeds limit !");
- } else {
- cHeader *h = Header(Name);
- if(!Duplicate && h)
- h->SetValue(Value);
- else {
- if(m_Headers.Count() < 50)
- m_Headers.Add(new cHeader(Name, Value));
- else
- LOGMSG("cConnState::AddHeader: header count exceeds 50 !");
- }
- }
-}
-
-void cHttpReq::Reset(void)
-{
- m_Name = NULL;
- m_Uri = NULL;
- m_Version = NULL;
- m_Valid = false;
- m_Headers.Clear();
-}
-
-//
-// Map file extensions to mime types
-//
-
-static const char *mimetype(const char *ext)
-{
- static const struct {
- const char *ext;
- const char *mime;
- } ext2mime[] = {
- {"avi", "video/avi"},
- {"vob", "video/mpeg"},
- {"mpg", "video/mpeg"},
- {"mpeg", "video/mpeg"},
- {"vdr", "video/mp2p"},
-
- {"mp3", "audio/mp3"},
- {"flac", "audio/flac"},
-
- {"jpg", "image/jpeg"},
- {"jpeg", "image/jpeg"},
- {"gif", "image/gif"},
-
- {NULL, NULL}
- };
-
- int i = -1;
- while(ext2mime[++i].ext)
- if(!strcmp(ext, ext2mime[i].ext))
- return ext2mime[i].mime;
- return NULL;
-}
-
-static char *unescape_uri(const char *uri)
-{
- char *d = strdup(uri), *s = d, *result = d;
- while(*s) {
- if(s[0] == '%' && s[1] && s[2]) {
- unsigned int c;
- if (sscanf(s+1, "%02x", &c) == 1) {
- *d++ = (char)c;
- s += 3;
- continue;
- }
- }
- *d++ = *s++;
- }
- *d = 0;
- return result;
-}
-
-//
-// cHttpStreamer
-//
-
-cList<cHttpStreamer> cHttpStreamer::m_Streamers;
-
-void cHttpStreamer::CloseAll(bool OnlyFinished)
-{
- if(!OnlyFinished) {
- while(m_Streamers.First())
- m_Streamers.Del(m_Streamers.First());
-
- } else {
- /* purge finished streamers from list */
- cHttpStreamer *it = m_Streamers.First();
- while(it) {
- if(it->Active()) {
- it = (cHttpStreamer*)it->Next();
- } else {
- m_Streamers.Del(it);
- it = m_Streamers.First();
- }
- }
- }
-}
-
-cHttpStreamer::cHttpStreamer(int fd_http, const char *filename,
- cConnState *Request) :
- m_Filename(unescape_uri(filename), true)
-{
- m_fds.set_handle(fd_http);
- m_fds.set_cork(true);
- m_fdf = -1;
-
- //m_Filename = filename;
- m_FileSize = -1;
- m_Start = 0;
- m_End = -1;
- m_KeepOpen = true;
-
- m_ConnState = Request;
-
- m_Finished = false;
-
- CloseAll(true);
-
- m_Streamers.Add(this);
-
- if(m_Streamers.Count() > 5) {
- LOGMSG("WARNING: There are %d running HTTP streamers !", m_Streamers.Count());
- if(m_Streamers.Count() > 20) {
- errno = 0;
- LOGERR("ERROR: There are %d running HTTP streamers, cancelling first",
- m_Streamers.Count());
- m_Streamers.Del(m_Streamers.First());
- }
- }
-
- Start();
-}
-
-cHttpStreamer::~cHttpStreamer()
-{
- Cancel(3);
- if(m_ConnState)
- delete m_ConnState;
- if(m_fdf >= 0)
- close(m_fdf);
- m_fdf = -1;
-}
-
-void cHttpStreamer::ParseRange(const char *Range)
-{
- m_Start = 0;
- m_End = -1;
- if(Range) {
- LOGDBG("cHttpStreamer: Request range is \'%s\'", Range);
- switch(sscanf(Range, "bytes=%" PRId64 "-%" PRId64, &m_Start, &m_End)) {
- case 2: LOGMSG(" Range: %s (%" PRId64 " - %" PRId64 ")", Range, m_Start, m_End);
- break;
- case 1: m_End = -1;
- LOGMSG(" Range start: %s (%" PRId64 " - )", Range, m_Start);
- break;
- default:
- case 0: m_Start = 0;
- m_End = -1;
- break;
- }
- }
-}
-
-bool cHttpStreamer::ParseRequest(void)
-{
- cHeader *h;
-
- if((h = m_ConnState->Header("Range")) != NULL)
- ParseRange(h->Value());
-
- m_KeepOpen = false;
- if((h = m_ConnState->Header("Connection")) != NULL) {
- m_KeepOpen = !strcasecmp(h->Value(), "keep-alive");
- if(m_KeepOpen)
- LOGDBG("cHttpStreamer: client wants to keep connection open");
- }
-
- return true;
-}
-
-bool cHttpStreamer::Seek(void)
-{
- if(m_fdf < 0) {
- m_fdf = open(m_Filename, O_RDONLY);
- if(m_fdf < 0) {
- LOGERR("cHttpStreamer: error opening %s", *m_Filename);
- m_fds.write_cmd(HTTP_REPLY_401); // 401 Not Found
- return false;
- }
-
- m_FileSize = lseek(m_fdf, 0, SEEK_END);
- if(m_FileSize <= 0) {
- LOGERR("cHttpStreamer: error seeking %s to end", *m_Filename);
- m_fds.write_cmd(HTTP_REPLY_401); // 401 Not Found
- return false;
- }
- }
-
- if(m_Start >= m_FileSize) {
- LOGERR("cHttpStreamer: Requested range not available "
- "(%s:%" PRId64 "-%" PRId64 " ; len=%" PRIu64 ")",
- *m_Filename, m_Start, m_End, (uint64_t)m_FileSize);
- m_fds.write_cmd(HTTP_REPLY_416); // 416 Requested Range Not Satisfiable
- return false;
- }
-
- if(m_Start > 0) {
- if(m_End >= m_FileSize || m_End < 0)
- m_End = m_FileSize-1;
-
- m_fds.write_cmd("HTTP/1.1 206 Partial Content\r\n");
- m_fds.printf("Content-Range: bytes %" PRId64 "-%" PRId64 "/%" PRIu64 "\r\n",
- m_Start, m_End, (uint64_t)m_FileSize);
- } else {
- m_fds.write_cmd("HTTP/1.1 200 OK\r\n");
- }
-
- /* content type */
- const char *ext = strrchr(m_Filename, '.');
- if(ext) {
- const char *mime = mimetype(ext+1);
- if(mime)
- m_fds.printf("Content-Type: %s\r\n", mime);
- }
-
- /* Content-Length */
- if(m_FileSize >= 0) {
- int64_t len = m_FileSize;
- if(m_End >= 0)
- len = m_End + 1;
- if(m_Start >= 0)
- len -= m_Start;
- m_fds.printf("Content-Length: %" PRId64 "\r\n", len);
- }
-
- /* Connection and end of reply */
- if(m_KeepOpen)
- m_fds.write_cmd("Connection: Keep-Alive\r\n"
- "\r\n");
- else
- m_fds.write_cmd("Connection: Close\r\n"
- "\r\n");
-
- if(m_Start)
- lseek(m_fdf, (off_t)m_Start, SEEK_SET);
- else
- lseek(m_fdf, 0, SEEK_SET);
-
- return true;
-}
-
-bool cHttpStreamer::ReadPipelined(void)
-{
- char buf[2048];
- int r;
-
- if(m_ConnState)
- delete m_ConnState;
- m_ConnState = new cConnState;
-
- do {
- r = m_fds.readline(buf, sizeof(buf), 1000);
- if(r < 0 || errno == EAGAIN || r >= (int)sizeof(buf)) {
- LOGMSG("cHttpStreamer: disconnected");
- return false;
- }
-
- LOGMSG("cHttpStreamer: pipelined request: %s", buf);
-
- if(!*m_ConnState->Name()) {
- if(!m_ConnState->SetCommand(buf) ||
- strcmp(m_ConnState->Name(), "GET") ||
- strncmp(m_ConnState->Uri(), "/PLAYFILE", 9) ||
- strncmp(m_ConnState->Version(), "HTTP/1.", 7)) {
- LOGMSG("Incorrect HTTP request: %s", buf);
- return false;
- }
- }
- else if(r > 0)
- m_ConnState->AddHeader(buf);
- } while(r>0);
-
- return true;
-}
-
-void cHttpStreamer::Action(void)
-{
- int n = 0;
- cxPoller p(m_fds);
- bool Disc = !(ParseRequest() && Seek());
- uint64_t pos = m_Start;
- off_t start = (off_t)m_Start;
-
- while(Running() && !Disc) {
-
- n = m_End>0 ? (m_End-start+1) : m_FileSize - start;
- if(n > 0) {
- errno = 0;
- pthread_testcancel();
- n = m_fds.sendfile(m_fdf, &start, n);
- pthread_testcancel();
- if(n <= 0) {
- if(errno == EAGAIN || errno == EINTR) {
- p.Poll(100);
- pthread_testcancel();
- } else {
- LOGERR("cHttpStreamer: sendfile() failed");
- Disc=true;
- }
- } else if(n == 0) {
- LOGMSG("cHttpStreamer: disconnected at %" PRId64, (int64_t)start);
- Disc = true;
- }
- continue;
- }
-
- LOGDBG("cHttpStreamer: Hit to EOF or end of requested range");
-
- m_fds.flush_cork();
-
- if(!m_KeepOpen) {
- LOGMSG("cHttpStreamer: disconnecting (request complete)");
- Disc = true;
- continue;
- }
-
- // keep connection open for new range for max. 30 sec
- n = 30;
- do {
- pthread_testcancel();
- //cxPoller p(m_fds);
- LOGDBG("cHttpStreamer: Request complete, waiting...");
- if(p.Poll(1000)) {
- LOGDBG("cHttpStreamer: Reading pipelined request");
- pthread_testcancel();
- Disc = !(ReadPipelined() && ParseRequest() && Seek());
- pos = m_Start;
- }
- } while(--n && Running() && !Disc);
-
- if(n <= 0) {
- LOGMSG("cHttpStreamer: Disconnecting (timeout)");
- Disc = true;
- }
- }
-
- close(m_fdf);
- m_fdf = -1;
-
- m_fds.close();
-
- m_Finished = true;
-}
diff --git a/tools/http.h b/tools/http.h
deleted file mode 100644
index 2adcf8e3..00000000
--- a/tools/http.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * http.h: HTTP (/RTSP) helper classes
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: http.h,v 1.5 2007-01-07 09:45:48 phintuka Exp $
- *
- */
-
-#ifndef XINELIBOUTPUT_HTTP_H_
-#define XINELIBOUTPUT_HTTP_H_
-
-#include <vdr/tools.h>
-
-
-#define HTTP_REPLY_401 \
- "HTTP/1.1 401 Unauthorized\r\n" \
- "Connection: Close\r\n" \
- "\r\n"
-
-#define HTTP_REPLY_404 \
- "HTTP/1.1 404 Not Found\r\n" \
- "Connection: Close\r\n" \
- "\r\n"
-
-#define HTTP_REPLY_416 \
- "HTTP/1.1 416 Requested Range Not Satisfiable\r\n" \
- "Connection: Close\r\n" \
- "\r\n"
-
-#define HTTP_REPLY_200_PRIMARY \
- "HTTP/1.1 200 OK\r\n" \
- "Content-Type: video/mpeg\r\n" \
- "Connection: Close\r\n" \
- "\r\n"
-//"Content-Type: video/mp2p\r\n"
-
-
-//
-// cHeader
-//
-
-class cHeader : public cListObject
-{
- protected:
- cString m_Name;
- cString m_Value;
-
- private:
- cHeader();
-
- public:
- cHeader(const char *Name, const char *Value) :
- m_Name(Name), m_Value(Value) {};
-
- const cString& Name(void) { return m_Name; }
- const cString& Value(void) { return m_Value; }
- int IntValue(void) { return *m_Value?atoi(m_Value):-1; }
- void SetValue(const char *Value) { m_Value = Value; }
-};
-
-
-//
-// cHttpReq
-//
-
-class cHttpReq
-{
- private:
- cString m_Name;
- cString m_Uri;
- cString m_Version;
- cList<cHeader> m_Headers;
-
- bool m_Valid;
-
- public:
- cHttpReq() : m_Valid(false) {}
-
- bool SetCommand(const char *Command);
- const cString& Name(void) { return m_Name; }
- const cString& Uri(void) { return m_Uri; }
- const cString& Version(void) { return m_Version; }
- bool Valid(void) { return m_Valid; }
-
- void AddHeader(const char *Header, bool Duplicate=false);
- void AddHeader(const char *Name, const char *Value, bool Duplicate=false);
- cHeader *Header(const char *Name);
-
- void Reset(void);
-};
-
-
-//
-// cConnState
-//
-
-class cConnState : public cHttpReq
-{
- public:
-};
-
-
-//
-// cHttpStreamer
-//
-
-#include <vdr/tools.h>
-#include <vdr/thread.h>
-
-#include "cxsocket.h"
-
-class cHttpStreamer : protected cListObject, cThread
-{
- public:
- cHttpStreamer(int fd_http, const char *filename, cConnState *Request);
- virtual ~cHttpStreamer();
-
- static void CloseAll(bool OnlyFinished = false);
-
- private:
- static cList<cHttpStreamer> m_Streamers;
-
- cxSocket m_fds;
- int m_fdf;
-
- cString m_Filename;
- int64_t m_FileSize;
- int64_t m_Start;
- int64_t m_End;
- bool m_KeepOpen;
-
- cConnState *m_ConnState;
-
- bool m_Finished;
-
- virtual void Action(void);
-
- bool ParseRequest(void);
- void ParseRange(const char *Range);
- bool ReadPipelined(void);
- bool Seek(void);
-};
-
-#endif // XINELIBOUTPUT_HTTP_H_
-
diff --git a/tools/iso639.h b/tools/iso639.h
deleted file mode 100644
index ae30fa0e..00000000
--- a/tools/iso639.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * iso639.h: iso-639-1 <-> iso-639-2 language code translations
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: iso639.h,v 1.4 2009-05-29 14:25:06 phintuka Exp $
- *
- */
-
-#ifndef __ISO_639_H
-#define __ISO_639_H
-
-static const struct {
- const char iso639_2[4];
- const char iso639_1[4];
-} ISO639_map[] =
-{
- {"???", "??"},
- {"abk", "ab"},
- {"aar", "aa"},
- {"afr", "af"},
- {"alb", "sq"},
- {"amh", "am"},
- {"ara", "ar"},
- {"arm", "hy"},
- {"ast", "as"},
- {"aym", "ay"},
- {"aze", "az"},
- {"bak", "ba"},
- {"baq", "eu"},
- {"bel", "be"},
- {"ben", "bn"},
- {"bih", "bh"},
- {"bis", "bi"},
- {"bre", "br"},
- {"bul", "bg"},
- {"bur", "my"},
- {"cat", "ca"},
- {"chi", "zh"},
- {"cos", "co"},
- {"scr", "hr"},
- {"cze", "cs"},
- {"dan", "da"},
- {"dut", "nl"},
- {"dzo", "dz"},
- {"eng", "en"},
- {"epo", "eo"},
- {"est", "et"},
- {"fao", "fo"},
- {"fij", "fj"},
- {"fin", "fi"},
- {"fre", "fr"},
- {"fry", "fy"},
- {"glg", "gl"},
- {"geo", "ka"},
- {"ger", "de"},
- {"gre", "el"},
- {"grn", "gn"},
- {"guj", "gu"},
- {"hau", "ha"},
- {"heb", "he"},
- {"heb", "iw"},
- {"hin", "hi"},
- {"hun", "hu"},
- {"ice", "is"},
- {"ind", "id"},
- {"ina", "ia"},
- {"iku", "iu"},
- {"ipk", "ik"},
- {"gle", "ga"},
- {"ita", "it"},
- {"jpn", "ja"},
- {"jav", "jv"},
- {"kal", "kl"},
- {"kan", "kn"},
- {"kas", "ks"},
- {"kaz", "kk"},
- {"khm", "km"},
- {"kin", "rw"},
- {"kir", "ky"},
- {"kor", "ko"},
- {"kur", "ku"},
- {"lao", "lo"},
- {"lat", "la"},
- {"lav", "lv"},
- {"lin", "ln"},
- {"lit", "lt"},
- {"mac", "mk"},
- {"mlg", "mg"},
- {"may", "ms"},
- {"mlt", "ml"},
- {"mao", "mi"},
- {"mar", "mr"},
- {"mol", "mo"},
- {"mon", "mn"},
- {"nau", "na"},
- {"nep", "ne"},
- {"nor", "no"},
- {"oci", "oc"},
- {"ori", "or"},
- {"orm", "om"},
- {"per", "fa"},
- {"pol", "pl"},
- {"por", "pt"},
- {"pus", "ps"},
- {"que", "qu"},
- {"roh", "rm"},
- {"rum", "ro"},
- {"run", "rn"},
- {"rus", "ru"},
- {"smo", "sm"},
- {"sag", "sg"},
- {"san", "sa"},
- {"srp", "sr"},
- {"scr", "sh"},
- {"sna", "sn"},
- {"snd", "sd"},
- {"sin", "si"},
- {"slo", "sk"},
- {"slv", "sl"},
- {"som", "so"},
- {"sot", "st"},
- {"spa", "es"},
- {"sun", "su"},
- {"swa", "sw"},
- {"ssw", "ss"},
- {"swe", "sv"},
- {"tgl", "tl"},
- {"tgk", "tg"},
- {"tam", "ta"},
- {"tat", "tt"},
- {"tel", "te"},
- {"tha", "th"},
- {"tib", "bo"},
- {"tir", "ti"},
- {"tog", "to"},
- {"tso", "ts"},
- {"tsn", "tn"},
- {"tur", "tr"},
- {"tuk", "tk"},
- {"twi", "tw"},
- {"uig", "ug"},
- {"ukr", "uk"},
- {"urd", "ur"},
- {"uzb", "uz"},
- {"vie", "vi"},
- {"vol", "vo"},
- {"wel", "cy"},
- {"wol", "wo"},
- {"xho", "xh"},
- {"yid", "yi"},
- {"yor", "yo"},
- {"zha", "za"},
- {"zul", "zu"},
-};
-
-static const char *iso639_2_to_iso639_1(const char *lang)
-{
- if (lang && lang[0]) {
- if (lang[1] && !lang[2]) {
- for (unsigned int i = 0 ; i < sizeof(ISO639_map) / sizeof(ISO639_map[0]); i++)
- if (!memcmp(ISO639_map[i].iso639_1, lang, 2))
- return ISO639_map[i].iso639_2;
- LOGMSG("Unknown iso639-2 code: %s", lang);
- }
- return lang;
- }
- return NULL;
-}
-
-static const char *iso639_1_to_iso639_2(const char *lang)
-{
- if (lang && lang[0]) {
- if (lang[1] && lang[2] && !lang[3]) {
- for (unsigned int i = 0 ; i < sizeof(ISO639_map) / sizeof(ISO639_map[0]); i++)
- if (!memcmp(ISO639_map[i].iso639_2, lang, 3))
- return ISO639_map[i].iso639_1;
- LOGMSG("Unknown iso639-1 code: %s", lang);
- }
- return lang;
- }
- return NULL;
-}
-
-#endif
diff --git a/tools/listiter.h b/tools/listiter.h
deleted file mode 100644
index 9c88940e..00000000
--- a/tools/listiter.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * listiter.h:
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: listiter.h,v 1.1 2006-06-03 10:04:27 phintuka Exp $
- *
- */
-
-
-#ifndef _LISTITER_H_
-#define _LISTITER_H_
-
-//------------------------------ list ----------------------------------------
-
-template <class LIST,class ITEM, class RESULT>
-void ForEach(LIST& List, RESULT (ITEM::*f)())
-{
- for(ITEM *it = List.First(); it; it = List.Next(it))
- (*it.*f)();
-}
-
-template <class LIST,class ITEM, class ARG1, class RESULT>
-void ForEach(LIST& List, RESULT (ITEM::*f)(ARG1), ARG1 arg1)
-{
- for(ITEM *it = List.First(); it; it = List.Next(it))
- (*it.*f)(arg1);
-}
-
-template <class LIST,class ITEM, class ARG1, class ARG2>
-void ForEach(LIST& List, void (ITEM::*f)(ARG1,ARG2), ARG1 arg1, ARG2 arg2)
-{
- for(ITEM *it = List.First(); it; it = List.Next(it))
- (*it.*f)(arg1,arg2);
-}
-
-template <class LIST,class ITEM, class ARG1, class RESULT>
-RESULT ForEach(LIST& List, RESULT (ITEM::*f)(ARG1), ARG1 arg1,
- RESULT (*combiner)(RESULT,RESULT), RESULT def)
-{
- RESULT result = def;
- for(ITEM *it = List.First(); it; it = List.Next(it))
- result = (*combiner)((*it.*f)(arg1),result);
- return result;
-}
-
-template <class LIST,class ITEM, class ARG1, class ARG2, class RESULT>
-RESULT ForEach(LIST& List, RESULT (ITEM::*f)(ARG1,ARG2),
- ARG1 arg1, ARG2 arg2,
- RESULT (*combiner)(RESULT,RESULT), RESULT def)
-{
- RESULT result = def;
- for(ITEM *it = List.First(); it; it = List.Next(it))
- result = (*combiner)((*it.*f)(arg1,arg2),result);
- return result;
-}
-
-template <class LIST,class ITEM, class ARG1, class ARG2, class ARG3,
- class RESULT>
-RESULT ForEach(LIST& List, RESULT (ITEM::*f)(ARG1,ARG2,ARG3),
- ARG1 arg1, ARG2 arg2, ARG3 arg3,
- RESULT (*combiner)(RESULT,RESULT), RESULT def)
-{
- RESULT result = def;
- for(ITEM *it = List.First(); it; it = List.Next(it))
- result = (*combiner)((*it.*f)(arg1,arg2,arg3),result);
- return result;
-}
-
-template<class T>
-T mmin(T a, T b) {return a<b ? a : b;}
-
-template<class T>
-T mmax(T a, T b) {return a>b ? a : b;}
-
-template<class T>
-T mand(T a, T b) {return a&&b;}
-
-template<class T>
-T mor(T a, T b) {return a||b;}
-
-#endif
diff --git a/tools/metainfo_menu.c b/tools/metainfo_menu.c
deleted file mode 100644
index 4a31b18c..00000000
--- a/tools/metainfo_menu.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * metainfo_menu.c: Media file info menu
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: metainfo_menu.c,v 1.8 2009-08-18 10:35:45 phintuka Exp $
- *
- */
-
-#include "../features.h"
-
-#ifdef HAVE_LIBEXTRACTOR
-# include <extractor.h>
-#endif
-
-#include <vdr/status.h>
-#include <vdr/i18n.h>
-
-#include "../config.h"
-
-#include "metainfo_menu.h"
-
-
-//
-// cMetainfoMenu
-//
-
-cMetainfoMenu::cMetainfoMenu(cString Filename) :
- cOsdMenu(Filename),
- m_Filename(Filename)
-{
- const char *Title = strrchr(Filename, '/');
- if(Title && *(Title+1))
- SetTitle(Title+1);
-}
-
-cMetainfoMenu::~cMetainfoMenu()
-{
-}
-
-void cMetainfoMenu::Display(void)
-{
- cOsdMenu::Display();
-
- char metadata[4096];
- metadata[0] = 0;
-
-#ifdef HAVE_LIBEXTRACTOR
- EXTRACTOR_ExtractorList * plugins;
- EXTRACTOR_KeywordList * md_list;
- plugins = EXTRACTOR_loadDefaultLibraries();
- md_list = EXTRACTOR_getKeywords(plugins, m_Filename);
- md_list = EXTRACTOR_removeEmptyKeywords (md_list);
- md_list = EXTRACTOR_removeDuplicateKeywords(md_list, 0);
- md_list = EXTRACTOR_removeKeywordsOfType(md_list, EXTRACTOR_THUMBNAILS);
-
- uint pos = 0;
- int n;
- while(md_list) {
- const char *key = EXTRACTOR_getKeywordTypeAsString(md_list->keywordType);
- if(key && pos < sizeof(metadata))
- if(0 < (n = snprintf(metadata+pos, sizeof(metadata)-pos, "%s: %s\n", key, md_list->keyword)))
- pos += n;
- md_list = md_list->next;
- }
- metadata[sizeof(metadata)-1] = 0;
-
- EXTRACTOR_freeKeywords(md_list);
- EXTRACTOR_removeAll(plugins); /* unload plugins */
-#else
- cString cmd;
- if(xc.IsPlaylistFile(m_Filename))
- cmd = cString::sprintf("file -b '%s'; cat '%s'", *m_Filename, *m_Filename);
- else if(xc.IsAudioFile(m_Filename))
- cmd = cString::sprintf("mp3info -x '%s' ; file -b '%s'", *m_Filename, *m_Filename);
- else if(xc.IsVideoFile(m_Filename))
- cmd = cString::sprintf("file -b '%s'; midentify '%s'", *m_Filename, *m_Filename);
- else if(xc.IsImageFile(m_Filename))
- cmd = cString::sprintf("file -b '%s'; identify '%s'", *m_Filename, *m_Filename);
- else
- cmd = cString::sprintf("file -b '%s'", *m_Filename);
-
- cPipe p;
- if(p.Open(*cmd, "r")) {
- int n = fread(metadata, 1, sizeof(metadata)-1, p);
- if(n>0) {
- metadata[n] = 0;
- strreplace(metadata, ',', '\n');
- }
- }
-#endif
- DisplayMenu()->SetText(metadata, false);
- cStatus::MsgOsdTextItem(cString::sprintf("%s\n%s", tr("Metainfo"), *m_Filename));
-}
-
-eOSState cMetainfoMenu::ProcessKey(eKeys Key)
-{
- eOSState state = cOsdMenu::ProcessKey(Key);
- return state;
-}
diff --git a/tools/metainfo_menu.h b/tools/metainfo_menu.h
deleted file mode 100644
index 45d60f22..00000000
--- a/tools/metainfo_menu.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * metainfo_menu.h: Media file info menu
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: metainfo_menu.h,v 1.1 2008-05-07 13:27:15 phintuka Exp $
- *
- */
-
-#ifndef __XINELIB_INFO_MENU_H_
-#define __XINELIB_INFO_MENU_H_
-
-//
-// cMetainfoMenu
-//
-
-#include <vdr/osdbase.h>
-
-class cMetainfoMenu : public cOsdMenu
-{
- protected:
-
- cString m_Filename;
-
- public:
-
- cMetainfoMenu(cString Filename);
- virtual ~cMetainfoMenu();
-
- virtual void Display(void);
-
- // cOsdMenu
- virtual eOSState ProcessKey(eKeys Key);
-
-};
-
-#endif // __XINELIB_INFO_MENU_H_
diff --git a/tools/mpeg.c b/tools/mpeg.c
deleted file mode 100644
index b827e096..00000000
--- a/tools/mpeg.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * mpeg.c:
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: mpeg.c,v 1.3 2009-02-16 16:03:18 phintuka Exp $
- *
- */
-
-#include <inttypes.h>
-#include <string.h>
-
-#include "mpeg.h"
-
-
-const char * const picture_type_str[] = {
- "(none)",
- "I-Frame",
- "B-Frame",
- "P-Frame"
-};
-
-int mpeg2_get_picture_type(const uint8_t *buf, int len)
-{
- int i;
- for (i = 0; i < len-5; i++) {
- if (buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1) {
- switch (buf[i + 3]) {
- case SC_PICTURE:
- return (buf[i + 5] >> 3) & 0x07;
- }
- }
- }
- return NO_PICTURE;
-}
-
-int mpeg2_get_video_size(const uint8_t *buf, int len, video_size_t *size)
-{
- int i;
- for (i = 0; i < len-6; i++) {
- if (buf[i] == 0 && buf[i + 1] == 0 && buf[i + 2] == 1) {
- if (buf[i + 3] == SC_SEQUENCE) {
- static const mpeg_rational_t mpeg2_aspect[16] = {
- {0,1}, {1,1}, {4,3}, {16,9}, {221,100},
- {0,1}, {0,1}, {0,1}, { 0,1}, { 0,1},
- {0,1}, {0,1}, {0,1}, { 0,1}, { 0,1},
- {0,1},
- };
-
- int d = (buf[i+4] << 16) | (buf[i+5] << 8) | buf[i+6];
- int a = buf[i+7] >> 4;
-
- size->width = (d >> 12);
- size->height = (d & 0xfff);
-
- memcpy(&size->pixel_aspect, &mpeg2_aspect[a], sizeof(mpeg_rational_t));
- size->pixel_aspect.num *= size->height;
- size->pixel_aspect.den *= size->width;
-
- return 1;
- }
- }
- }
- return 0;
-}
-
diff --git a/tools/mpeg.h b/tools/mpeg.h
deleted file mode 100644
index 8a9b6493..00000000
--- a/tools/mpeg.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * mpeg.h: MPEG definitions
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: mpeg.h,v 1.6 2009-02-16 16:03:18 phintuka Exp $
- *
- */
-
-#ifndef XINELIBOUTPUT_MPEG_H_
-#define XINELIBOUTPUT_MPEG_H_
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#define SC_PICTURE 0x00 /* picture atart code */
-#define SC_SEQUENCE 0xb3 /* sequence header */
-
-/* Picture types */
-#define NO_PICTURE 0
-#define I_FRAME 1
-#define P_FRAME 2
-#define B_FRAME 3
-
-typedef struct mpeg_rational_s {
- int num;
- int den;
-} mpeg_rational_t;
-
-typedef struct video_size_s {
- uint16_t width;
- uint16_t height;
- mpeg_rational_t pixel_aspect;
-} video_size_t;
-
-extern const char * const picture_type_str[];
-
-/*
- * input: start of MPEG video data (not PES)
- */
-int mpeg2_get_picture_type(const uint8_t *buf, int len);
-
-/*
- * input: start of MPEG video data (not PES)
- */
-int mpeg2_get_video_size(const uint8_t *buf, int len, video_size_t *size);
-
-
-#ifdef __cplusplus
-} /* extern "C" { */
-#endif
-
-
-#endif
diff --git a/tools/pes.c b/tools/pes.c
deleted file mode 100644
index 14773f2e..00000000
--- a/tools/pes.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * pes.h: PES header definitions
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: pes.c,v 1.10 2009-07-01 09:31:17 phintuka Exp $
- *
- */
-
-#include <inttypes.h>
-#include <string.h>
-
-#include "../logdefs.h"
-
-#include "mpeg.h"
-#include "h264.h"
-
-#include "pes.h"
-
-
-int64_t pes_get_pts(const uint8_t *buf, int len)
-{
- /* assume mpeg2 pes header ... */
- if (IS_VIDEO_PACKET(buf) || IS_AUDIO_PACKET(buf)) {
-
- if ((buf[6] & 0xC0) != 0x80)
- return NO_PTS;
- if ((buf[6] & 0x30) != 0)
- return NO_PTS;
-
- if ((len > 13) && (buf[7] & 0x80)) { /* pts avail */
- int64_t pts;
- pts = ((int64_t)(buf[ 9] & 0x0E)) << 29 ;
- pts |= ((int64_t) buf[10]) << 22 ;
- pts |= ((int64_t)(buf[11] & 0xFE)) << 14 ;
- pts |= ((int64_t) buf[12]) << 7 ;
- pts |= ((int64_t)(buf[13] & 0xFE)) >> 1 ;
- return pts;
- }
- }
- return NO_PTS;
-}
-
-int64_t pes_get_dts(const uint8_t *buf, int len)
-{
- if (IS_VIDEO_PACKET(buf) || IS_AUDIO_PACKET(buf)) {
-
- if ((buf[6] & 0xC0) != 0x80)
- return NO_PTS;
- if ((buf[6] & 0x30) != 0)
- return NO_PTS;
-
- if (len > 18 && (buf[7] & 0x40)) { /* dts avail */
- int64_t dts;
- dts = ((int64_t)( buf[14] & 0x0E)) << 29 ;
- dts |= (int64_t)( buf[15] << 22 );
- dts |= (int64_t)((buf[16] & 0xFE) << 14 );
- dts |= (int64_t)( buf[17] << 7 );
- dts |= (int64_t)((buf[18] & 0xFE) >> 1 );
- return dts;
- }
- }
- return NO_PTS;
-}
-
-void pes_change_pts(uint8_t *buf, int len, int64_t new_pts)
-{
- /* assume mpeg2 pes header ... Assume header already HAS pts */
- if (IS_VIDEO_PACKET(buf) || IS_AUDIO_PACKET(buf)) {
-
- if ((buf[6] & 0xC0) != 0x80)
- return;
- if ((buf[6] & 0x30) != 0)
- return;
-
- if ((len > 13) && (buf[7] & 0x80)) { /* pts avail */
- buf[ 9] = ((new_pts >> 29) & 0x0E) | (buf[ 9] & 0xf1);
- buf[10] = ((new_pts >> 22) & 0xFF);
- buf[11] = ((new_pts >> 14) & 0xFE) | (buf[11] & 0x01);
- buf[12] = ((new_pts >> 7 ) & 0xFF);
- buf[13] = ((new_pts << 1 ) & 0xFE) | (buf[13] & 0x01);
- }
- }
-}
-
-int pes_strip_pts_dts(uint8_t *buf, int size)
-{
- if(size > 13 && buf[7] & 0x80) { /* pts avail */
- int n = 5;
- int pes_len = (buf[4] << 8) | buf[5];
- if ((buf[6] & 0xC0) != 0x80)
- return size;
- if ((buf[6] & 0x30) != 0) /* scrambling control */
- return size;
- /* dts too ? */
- if(size > 18 && buf[7] & 0x40)
- n += 5;
- pes_len -= n; /* update packet len */
- buf[4] = pes_len >> 8; /* packet len (hi) */
- buf[5] = pes_len & 0xff; /* packet len (lo) */
- buf[7] &= 0x3f; /* clear pts and dts flags */
- buf[8] -= n; /* update header len */
- memmove(buf+4+n, buf+9+n, size-9-n);
- return size - n;
- }
- return size;
-}
-
-int pes_is_frame_h264(const uint8_t *buf, int len)
-{
- if (len < 9 || len < 9 + buf[8])
- return 0;
- if ( (buf[6] & 0xC0) != 0x80) /* MPEG 2 PES */
- return 0;
-
- buf += 9 + buf[8];
-
- if (IS_NAL_AUD(buf))
- return 1;
- return 0;
-}
-
-uint8_t pes_get_picture_type(const uint8_t *buf, int len)
-{
- int i = PES_HEADER_LEN(buf);
-
- buf += i;
- len -= i;
-
- if (buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x01) {
- if (buf[3] == NAL_AUD)
- return h264_get_picture_type(buf, len);
- return mpeg2_get_picture_type(buf, len);
- }
-
- return NO_PICTURE;
-}
-
-int pes_get_video_size(const uint8_t *buf, int len, video_size_t *size, int h264)
-{
- int i = PES_HEADER_LEN(buf);
-
- buf += i;
- len -= i;
-
- if (h264 || IS_NAL_AUD(buf))
- return h264_get_video_size(buf, len, size);
-
- return mpeg2_get_video_size(buf, len, size);
-}
-
diff --git a/tools/pes.h b/tools/pes.h
deleted file mode 100644
index d25374a7..00000000
--- a/tools/pes.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * pes.h: PES header definitions
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: pes.h,v 1.13 2009-07-01 09:56:26 phintuka Exp $
- *
- */
-
-#ifndef _XINELIBOUTPUT_PES_H_
-#define _XINELIBOUTPUT_PES_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/*
- * Constants
- */
-
-#define PES_CHUNK_SIZE 2048
-
-#define MAX_SCR ((int64_t)0x1ffffffffLL)
-
-#define NO_PTS (INT64_C(-1))
-
-/* PES PIDs */
-#define PRIVATE_STREAM1 0xBD
-#define PADDING_STREAM 0xBE
-#define PRIVATE_STREAM2 0xBF
-#define AUDIO_STREAM_S 0xC0 /* 1100 0000 */
-#define AUDIO_STREAM_E 0xDF /* 1101 1111 */
-#define VIDEO_STREAM_S 0xE0 /* 1110 0000 */
-#define VIDEO_STREAM_E 0xEF /* 1110 1111 */
-
-#define AUDIO_STREAM_MASK 0x1F /* 0001 1111 */
-#define VIDEO_STREAM_MASK 0x0F /* 0000 1111 */
-#define AUDIO_STREAM 0xC0 /* 1100 0000 */
-#define VIDEO_STREAM 0xE0 /* 1110 0000 */
-
-#define ECM_STREAM 0xF0
-#define EMM_STREAM 0xF1
-#define DSM_CC_STREAM 0xF2
-#define ISO13522_STREAM 0xF3
-#define PROG_STREAM_DIR 0xFF
-
-#define IS_VIDEO_PACKET(data) (VIDEO_STREAM == ((data)[3] & ~VIDEO_STREAM_MASK))
-#define IS_MPEG_AUDIO_PACKET(data) (AUDIO_STREAM == ((data)[3] & ~AUDIO_STREAM_MASK))
-#define IS_PS1_PACKET(data) (PRIVATE_STREAM1 == (data)[3])
-#define IS_PADDING_PACKET(data) (PADDING_STREAM == (data)[3])
-#define IS_AUDIO_PACKET(data) (IS_MPEG_AUDIO_PACKET(data) || IS_PS1_PACKET(data))
-
-#define PES_HAS_PTS(data) ((data)[7] & 0x80)
-#define PES_HAS_DTS(data) ((data)[7] & 0x40)
-
-#define DATA_IS_PES(data) (!(data)[0] && !(data)[1] && (data)[2] == 1)
-
-#define PES_HEADER_LEN(data) (8 + (data)[8] + 1)
-
-
-/*
- * timestamps
- */
-
-static inline int pts_to_ms(int64_t pts) { return (int)(pts/INT64_C(90)); }
-static inline int64_t ms_to_pts(int ms) { return ((int64_t)(ms)) * INT64_C(90); }
-
-int64_t pes_get_pts(const uint8_t *buf, int len);
-int64_t pes_get_dts(const uint8_t *buf, int len);
-void pes_change_pts(uint8_t *buf, int len, int64_t new_pts);
-int pes_strip_pts_dts(uint8_t *buf, int len);
-
-/*
- * payload
- */
-
-struct video_size_s;
-
-int pes_is_frame_h264(const uint8_t *buf, int len);
-uint8_t pes_get_picture_type(const uint8_t *buf, int len);
-int pes_get_video_size(const uint8_t *buf, int len, struct video_size_s *size, int h264);
-
-static inline int pes_is_mpeg1(const uint8_t *header)
-{
- if (IS_VIDEO_PACKET(header) || IS_AUDIO_PACKET(header))
- return ((header[6] & 0xC0) != 0x80);
- if (header[3] == 0xBA)
- return ((header[4] & 0x40) == 0); /* mpeg1 */
- return 0;
-}
-
-/*
- * Extract PES packet length
- */
-
-static inline int pes_packet_len(const uint8_t *data, const int len)
-{
- if (IS_VIDEO_PACKET(data) || IS_AUDIO_PACKET(data)) {
- return 6 + (data[4] << 8 | data[5]);
- } else if (data[3] == PADDING_STREAM) {
- return 6 + (data[4] << 8 | data[5]);
- } else if (data[3] == 0xBA) {
- if ((data[4] & 0x40) == 0) /* mpeg1 */
- return 12;
- else /* mpeg 2 */
- return 14 + (data[0xD] & 0x07);
- } else if (data[3] <= 0xB9) {
- return -3;
- }
- return -(6 + (data[4] << 8 | data[5]));
-}
-
-
-#ifdef __cplusplus
-} /* extern "C" { */
-#endif
-
-#endif /* _XINELIBOUTPUT_PES_H_ */
diff --git a/tools/playlist.c b/tools/playlist.c
deleted file mode 100644
index e227b9c9..00000000
--- a/tools/playlist.c
+++ /dev/null
@@ -1,1005 +0,0 @@
-/*
- * playlist.c: Media player playlist
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: playlist.c,v 1.23 2009-06-02 08:36:16 phintuka Exp $
- *
- */
-
-#include "../features.h"
-
-#include <stdlib.h>
-
-#ifdef HAVE_LIBEXTRACTOR
-# include <extractor.h>
- // libextractor 0.5.20 (2008-03-20) adds support for track numbers
-# if EXTRACTOR_VERSION < 0x00052000
-# warning libextractor version too old (0.5.20 required for track numbers)
-# undef HAVE_LIBEXTRACTOR
-# endif
-#endif
-
-#include <vdr/config.h>
-#include <vdr/tools.h>
-#include <vdr/thread.h>
-
-#include "../config.h"
-
-#include "playlist.h"
-
-#include "../logdefs.h"
-
-
-#ifndef PLAYLIST_CACHE
-# define PLAYLIST_CACHE ".xineliboutput-playlist.pls"
-#endif
-
-#define MAX_PLAYLIST_FILES 1024
-
-static void strip_extension(cString& fname)
-{
- const char *ext = strrchr(fname, '.');
- if (ext)
- fname.Truncate(ext - fname);
-}
-
-//
-// cPlaylistItem
-//
-
-cPlaylistItem::cPlaylistItem(const char *filename)
-{
- const char *pt;
-
- Filename = filename;
- Position = -1;
-
- if(NULL != (pt = strrchr(filename, '/')))
- Title = pt + 1;
- else
- Title = filename;
-
- strip_extension(Title);
-}
-
-cPlaylistItem::cPlaylistItem(const char *filename,
- const char *path,
- const char *title,
- int position)
-{
- if(path[strlen(path)-1] != '/')
- Filename = cString::sprintf("%s/%s", path, filename);
- else
- Filename = cString::sprintf("%s%s", path, filename);
- Position = position;
- Title = title ?: filename;
-
- if (!title)
- strip_extension(Title);
-}
-
-int cPlaylistItem::Compare(const cListObject &ListObject) const
-{
- ///< Must return 0 if this object is equal to ListObject, a positive value
- ///< if it is "greater", and a negative value if it is "smaller".
-
- const cPlaylistItem *o = (cPlaylistItem *)&ListObject;
-
- // Use Position (if defined in playlist file)
- // compare as unsigned --> -1 goes to last position
- if(Position != o->Position)
- return ((unsigned int)Position) > ((unsigned int)o->Position) ? 1 : -1;
-
- // same position (or no positions definend) -> alphabetical order
-#if 0
- return strcmp(Title, o->Title);
-#else
- // use filename, because:
- // - implicit playlist has no track names available when sorting
- // (track names are read during playback), so track name is
- // just file name without path.
- // using full path allows sorting of each album and tracks inside albums...
- // - "normal" playlist is ordered using Position,
- // so track names are never compared anyway ...
- return strcmp(Filename, o->Filename);
-#endif
-}
-
-
-//
-// cID3Scanner
-//
-
-#ifndef HAVE_LIBEXTRACTOR
-static const char *shell_escape(char *buf, int buflen, const cString& src, char ch)
-{
- const char *pt = *src;
- int n = 0;
-
- if(pt) {
- while(*pt && n < buflen-2) {
- if(*pt == ch || *pt == '\\' /*|| *pt == '\"' || *pt == '\''*/) {
- buf[n++] = '\\';
- }
- buf[n++] = *pt++;
- }
- buf[n] = 0;
- return buf;
- }
- return "";
-}
-#endif
-
-class cID3Scanner : public cThread
-{
- public:
- cPlaylist& m_List;
- cID3Scanner(cPlaylist& List) : cThread("Metadata scanner"), m_List(List), m_Done(false) {};
-
- void CancelScanner(void) { Cancel(3); }
-
- private:
- bool m_Done;
-
- virtual void Action(void)
- {
- cPlaylistItem *Item = NULL;
- unsigned int Version = 0;
- const int priority = 10;
- errno = 0;
- if((nice(priority) == -1) && errno)
- LOGDBG("ID3Scanner: Can't nice to value: %d", priority);
-
- LOGDBG("ID3Scanner Started");
- while(Running()) {
-
- cMutexLock ml(&m_List.m_Lock);
-
- if(Version < m_List.m_Version) {
- // restart after sort, add, del
- Item = NULL;
- Version = m_List.m_Version;
- }
-
- if(!(Item = m_List.Next(Item)))
- break;
-
- if(xc.IsAudioFile(Item->Filename)) {
- LOGDBG("Scanning metainfo for file %s", *Item->Filename);
-#ifdef HAVE_LIBEXTRACTOR
- EXTRACTOR_ExtractorList * plugins;
- EXTRACTOR_KeywordList * md_list;
- plugins = EXTRACTOR_loadDefaultLibraries();
- md_list = EXTRACTOR_getKeywords(plugins, *Item->Filename);
- const char *key;
- while(md_list) {
- if ((key=EXTRACTOR_getKeywordTypeAsString(md_list->keywordType))) {
- if (!strcasecmp(key,"title"))
- Item->Title = md_list->keyword;
- else if (!strcasecmp(key,"artist"))
- Item->Artist = md_list->keyword;
- else if (!strcasecmp(key,"album"))
- Item->Album = md_list->keyword;
- else if (!strcasecmp(key,"track number"))
- Item->Tracknumber = cString::sprintf("%s%s", strlen(md_list->keyword) == 1 ? "0" : "", md_list->keyword);
- md_list=md_list->next;
- }
- }
- EXTRACTOR_freeKeywords(md_list);
- EXTRACTOR_removeAll(plugins); /* unload plugins */
-#else
- char buf[4096];
- cString Cmd = "";
- if(!strcasecmp((Item->Filename) + strlen(Item->Filename) - 5, ".flac"))
- Cmd = cString::sprintf("metaflac "
- " --show-tag=TITLE "
- " --show-tag=ALBUM "
- " --show-tag=ARTIST "
- " --show-tag=TRACKNUMBER "
- " \"%s\"",
- shell_escape(buf, sizeof(buf)-1, Item->Filename, '\"'));
- else
- Cmd = cString::sprintf("mp3info -p \""
- "ARTIST=%%a\\r\\n"
- "ALBUM=%%l\\r\\n"
- "TITLE=%%t\\r\\n"
- "TRACKNUMBER=%%n\\r\\n\""
- " \"%s\"",
- shell_escape(buf, sizeof(buf)-1, Item->Filename, '\"'));
-
- cPipe p;
- if(p.Open(*Cmd, "r")) {
- cReadLine r;
- char *pt;
- while(NULL != (pt = r.Read(p))) {
- if(!strncasecmp(pt, "ARTIST=", 7) && strlen(pt) > 8)
- Item->Artist = (pt+7);
- else if(!strncasecmp(pt, "ALBUM=", 6) && strlen(pt) > 7)
- Item->Album = (pt+6);
- else if(!strncasecmp(pt, "TITLE=", 6) && strlen(pt) > 7)
- Item->Title = (pt+6);
- else if(!strncasecmp(pt, "TRACKNUMBER=", 12) && strlen(pt) > 12)
- Item->Tracknumber = cString::sprintf("%s%s", strlen(pt) == 13 ? "0" : "", (pt+12));
- }
- }
-#endif
- }
- }
- LOGDBG("ID3Scanner Done.");
-
- m_List.PlaylistChanged(Item);
- m_Done = true;
- }
-};
-
-//
-// cPlaylistReader
-//
-
-class cPlaylistReader
-{
- private:
- cPlaylist& m_Playlist;
-
- protected:
- cString m_Title;
- int m_Position;
-
- cPlaylistItem *Prev(void) { return m_Playlist.Last(); }
-
- public:
- cPlaylistReader(cPlaylist& Playlist) : m_Playlist(Playlist) {}
- virtual ~cPlaylistReader() {}
-
- virtual char *Parse(char *line) = 0;
-
- void ResetCache(void) { m_Title = NULL; m_Position = -1; }
- const char *Title(void) { return m_Title; }
- int Position(void) { return m_Position; }
-};
-
-class cM3uReader : public cPlaylistReader
-{
- public:
- cM3uReader(cPlaylist& Playlist) : cPlaylistReader(Playlist), m_Next(1) {}
-
- protected:
- int m_Next;
- virtual char *Parse(char *line) {
- if(!*line)
- return NULL;
- if(*line == '#') {
- if(!strncmp(line, "#EXTINF:", 8)) {
- int len = -1;
- sscanf(line+8,"%d", &len);
- while(*line && *line != ',')
- line++;
- m_Title = *line ? (line+1) : NULL;
- m_Position = m_Next++;
- }
- return NULL;
- }
- return *line ? line : NULL;
- }
-};
-
-class cPlsReader : public cPlaylistReader
-{
- public:
- cPlsReader(cPlaylist& Playlist) : cPlaylistReader(Playlist), m_Current(0) {}
-
- protected:
- int m_Current;
- virtual char *Parse(char *line) {
- char *t = strchr(line, '=');
- if(t) {
- int n;
- if(!strncasecmp(line, "file", 4) &&
- 1 == sscanf(line + 4, "%d=", &n)) {
- m_Current = n;
- m_Position = n;
- if(*(t+1))
- return t+1;
- }
- else if(!strncasecmp(line, "title", 5) &&
- 1 == sscanf(line + 5, "%d=", &n)) {
- if(*(t+1)) {
- if(n == m_Current)
- Prev()->Title = t;
- else
- m_Title = t;
- }
- }
- //else if(!strncasecmp(line, "length", 6) &&
- // 1 == sscanf(line + 4, "%d=", &n)) {
- //}
- }
- return NULL;
- }
-};
-
-class cAsxReader : public cPlaylistReader
-{
- public:
- cAsxReader(cPlaylist& Playlist) : cPlaylistReader(Playlist) {}
-
- protected:
- virtual char *Parse(char *line) {
- char *pt = strstr(line, "<REF HREF");
- if(!pt)
- pt = strstr(line, "<ref href");
- if(!pt)
- pt = strstr(line, "<ENTRY HREF");
- if(!pt)
- pt = strstr(line, "<entry href");
- if(pt) {
- pt = strchr(pt, '=');
- if(pt) {
- pt = strchr(pt, '\"');
- if(pt) {
- pt++;
- if(strchr(pt, '\"'))
- *strchr(pt, '\"') = 0;
- return pt;
- }
- }
- }
-
- pt = strstr(line, "<TITLE>");
- if(!pt)
- pt = strstr(line, "<title>");
- if(pt) {
- pt += 7;
- if(strstr(line, "</"))
- *strstr(line, "</") = 0;
- m_Title = pt;
- }
-
- if(*m_Title) {
- pt = strstr(line, "<ENTRY>");
- if(!pt)
- pt = strstr(line, "<entry>");
- if(pt) {
- if(*m_Title && Prev()) {
- Prev()->Title = m_Title;
- m_Title = NULL;
- }
- }
- }
- return NULL;
- }
-};
-
-
-//
-// cPlaylist
-//
-
-cPlaylist::cPlaylist()
-{
- m_Origin = eImplicit;
- m_Menu = NULL;
- m_Scanner = NULL;
- m_Current = NULL;
- m_Version = 1;
-}
-
-cPlaylist::~cPlaylist()
-{
- if(m_Scanner) {
- m_Scanner->CancelScanner();
- delete m_Scanner;
- }
-
- if(m_Origin == eImplicit)
- StoreCache();
-}
-
-void cPlaylist::Listen(cPlaylistChangeNotify *Menu)
-{
- cMutexLock ml(&m_Lock);
- m_Menu = Menu;
-}
-
-void cPlaylist::PlaylistChanged(const cPlaylistItem *Item)
-{
- cMutexLock ml(&m_Lock);
- /*if(m_Origin == eImplicit)*/
- Sort();
- if(m_Menu)
- m_Menu->PlaylistChanged(Item);
-}
-
-void cPlaylist::Sort(void)
-{
- cMutexLock ml(&m_Lock);
- cListBase::Sort();
- m_Version++;
-}
-
-int cPlaylist::Count(void) const
-{
- return cListBase::Count();
-}
-
-cPlaylistItem *cPlaylist::Next(const cPlaylistItem *i)
-{
- cMutexLock ml(&m_Lock);
- return i ? cList<cPlaylistItem>::Next(i) : cList<cPlaylistItem>::First();
-}
-
-cPlaylistItem *cPlaylist::Current(void)
-{
- cMutexLock ml(&m_Lock);
- return m_Current ?: First();
-}
-
-void cPlaylist::Del(cPlaylistItem *it)
-{
- cMutexLock ml(&m_Lock);
-
- if(!it || Count() < 2)
- return;
-
- if(m_Current == it)
- m_Current = cList<cPlaylistItem>::Next(Current()) ?:
- cList<cPlaylistItem>::Prev(Current());
-
- cListBase::Del(it);
- m_Version++;
-}
-
-void cPlaylist::SetCurrent(cPlaylistItem *current)
-{
- cMutexLock ml(&m_Lock);
- m_Current = current;
-}
-
-cPlaylistItem *cPlaylist::Next(void)
-{
- cMutexLock ml(&m_Lock);
- if(Current())
- return m_Current = (cList<cPlaylistItem>::Next(Current()) ?: First());
- return NULL;
-}
-
-cPlaylistItem *cPlaylist::Prev(void)
-{
- cMutexLock ml(&m_Lock);
- if(Current())
- return m_Current = (cList<cPlaylistItem>::Prev(Current()) ?: Last());
- return NULL;
-}
-
-bool cPlaylist::StoreCache(void)
-{
- if(!xc.cache_implicit_playlists ||
- m_Origin != eImplicit ||
- !*m_Folder)
- return false;
-
- cString Name = cString::sprintf("%s%s", *m_Folder, PLAYLIST_CACHE);
- int len = strlen(m_Folder), entries = 0;
- FILE *f = NULL;
-
- for(cPlaylistItem *i = First(); i; i=Next(i)) {
- // store only items in "current" root folder
- if(!strncmp(i->Filename, m_Folder, len)) {
- if(/**i->Title ||*/ *i->Artist || *i->Album) {
- cString Filename = ((*i->Filename) + len); // relative
- if(entries < 1) {
- f = fopen(Name, "w");
- if(!f) {
- LOGERR("creation of metadata cache %s%s failed",
- *m_Folder, PLAYLIST_CACHE);
- return false;
- }
- fprintf(f, "[playlist]\r\n");
- }
- entries++;
- fprintf(f, "File%d=%s\r\n", entries, *Filename);
- if(*i->Title && (*i->Title)[0])
- fprintf(f, "Title%d=%s\r\n", entries, *i->Title);
- if(*i->Tracknumber && (*i->Tracknumber)[0])
- fprintf(f, "Tracknumber%d=%s\r\n", entries, *i->Tracknumber);
- if(*i->Artist && (*i->Artist)[0])
- fprintf(f, "Artist%d=%s\r\n", entries, *i->Artist);
- if(*i->Album && (*i->Album)[0])
- fprintf(f, "Album%d=%s\r\n", entries, *i->Album);
- }
- }
- }
-
- if(entries > 0) {
- fprintf(f, "NumberOfEntries=%d\r\nVersion=2\r\n", entries);
- fclose(f);
- return true;
- }
-
- return false;
-}
-
-static const char *strchrnext(const char *s, char c)
-{
- return (s = strchr(s, c)) ? ((*(s+1))?(s+1):NULL) : NULL;
-}
-
-bool cPlaylist::ReadCache(void)
-{
- if(xc.cache_implicit_playlists && m_Origin == eImplicit && *m_Folder) {
-
- cString Name = cString::sprintf("%s%s", *m_Folder, PLAYLIST_CACHE);
- FILE *f = fopen(Name, "r");
- if(f) {
- int len = strlen(m_Folder);
- cPlaylistItem *it = NULL;
- cReadLine r;
- const char *pt;
- while(NULL != (pt = r.Read(f))) {
- if(!strncmp(pt, "File", 4)) {
- it = NULL;
- const char *Filename = strchrnext(pt+4, '=');
- if(Filename && *Filename) {
- for(cPlaylistItem *i = First(); i; i=Next(i)) {
- if(!strncmp(i->Filename, m_Folder, len)) {
- if(!strcmp(*i->Filename + len, Filename)) {
- it = i;
- break;
- }
- }
- }
- }
- } else if(it && !strncmp(pt, "Title", 5)) {
- it->Title = strchrnext(pt, '=');
- } else if(it && !strncmp(pt, "Tracknumber", 11)) {
- it->Tracknumber = strchrnext(pt, '=');
- } else if(it && !strncmp(pt, "Artist", 6)) {
- it->Artist = strchrnext(pt, '=');
- } else if(it && !strncmp(pt, "Album", 5)) {
- it->Album = strchrnext(pt, '=');
- } else {
- /*it = NULL;*/
- }
- }
- fclose(f);
- return true;
- }
- }
-
- return false;
-}
-
-#if 0
-static FILE *open_http(const char *PlaylistFile)
-{
- char file[1024] = "", host[128] = "", pt;
- int fd, port = 80;
-
- strn0cpy(host, PlaylistFile+strlen("http://"), sizeof(host)-1);
- pt = strchr(host, '/');
- if(pt) {
- strn0cpy(file, pt, sizeof(file)-1);
- *pt = 0;
- }
- pt = strchr(host, ':');
- if(pt) {
- *pt++ = 0;
- port = atoi(pt);
- }
-
- fd = tcp_connect(host, port);
- if(fd < 0) {
- LOGERR("TCP connect failed");
- return NULL;
- }
-
- int len = asprintf(&pt,
- "GET %s HTTP/1.1" "\r\n"
- "Host: %s" "\r\n"
- "\r\n",
- file, host);
- if(len != write(fd, pt, len)) {
- LOGERR("HTTP request write failed");
- free(pt);
- close(fd);
- return NULL;
- }
- free(pt);
-
- int state = 0;
- FILE *f = fdopen(fd, "r");
- cReadLine r;
- while(state >= 0 && NULL != (pt = r.Read(f))) {
- switch(state) {
- case 0: if(!strncmp(pt, "HTTP/1", 6) || !strstr(pt, " 200 ")) {
- LOGERR("HTTP error: %s", pt);
- fclose(f);
- return NULL;
- }
- state = 1;
- break;
- case 1: if(strcmp(pt, "\r\n"))
- break;
- return f;
- default: break;
- }
- }
-
- fclose(f);
- return NULL;
-}
-#endif
-
-int cPlaylist::ScanFolder(const char *FolderName,
- bool Recursive,
- bool (config_t::*Filter)(const char *))
-{
- cMutexLock ml(&m_Lock);
- static int depth = 0;
-
- DIR *d = opendir(FolderName);
-
- if (d) {
- LOGDBG("ScanFolder(%s)", FolderName);
- struct dirent *e;
- int n = 0, warn = -1;
- while ((e = readdir(d)) != NULL) {
- cString Buffer = cString::sprintf("%s%s", FolderName, e->d_name);
- struct stat st;
- if (stat(Buffer, &st) == 0) {
- if(S_ISDIR(st.st_mode)) {
- if (Recursive && !S_ISLNK(st.st_mode)) { /* don't want to loop ... */
- if(depth > 4) {
- LOGMSG("ScanFolder: Too deep directory tree");
- } else if(e->d_name[0]=='.') {
- } else {
- if(n<MAX_PLAYLIST_FILES) {
- depth++; /* limit depth */
- Buffer = cString::sprintf("%s/", *Buffer);
- n += ScanFolder(Buffer, Recursive, Filter);
- depth--;
- } else {
- if(!++warn)
- LOGMSG("ScanFolder: Found over %d matching files, list truncated!", n);
- break;
- }
- }
- }
- } else /* == if(!S_ISDIR(st.st_mode))*/ {
- // check symlink destination
- if (S_ISLNK(st.st_mode)) {
- Buffer = ReadLink(Buffer);
- if (!*Buffer)
- continue;
- if (stat(Buffer, &st) != 0)
- continue;
- }
- if((xc.*Filter)(Buffer)) {
- /* TODO: Should ScanDir add contents of playlist files ... ? */
- if(Filter == &config_t::IsPlaylistFile || !xc.IsPlaylistFile(Buffer)) {
- n++;
- if(n<MAX_PLAYLIST_FILES) {
- Add(new cPlaylistItem(e->d_name, FolderName));
- //LOGDBG("ScanFolder: %s", e->d_name);
- } else {
- if(!++warn)
- LOGMSG("ScanFolder: Found over %d matching files, list truncated!", n);
- break;
- }
- }
- }
- }
- }
- }
- LOGDBG("ScanFolder: Found %d matching files from %s", n, FolderName);
- closedir(d);
-
- return n;
- }
-
- LOGERR("ScanFolder: Error opening %s", FolderName);
- return 0;
-}
-
-void cPlaylist::StartScanner(void)
-{
- cMutexLock ml(&m_Lock);
-
- if(m_Scanner) {
- if(m_Scanner->Active())
- return;
- delete m_Scanner;
- m_Scanner = NULL;
- }
-
- /* check if cache is already up-to-date */
- cString CacheName = cString::sprintf("%s%s", *m_Folder, PLAYLIST_CACHE);
- struct stat stf, stc;
- if(!stat(m_Folder, &stf)) {
- if(!stat(CacheName, &stc)) {
- //LOGDBG("ID3 Cache modified %d, folder modified %d, diff %d",
- // (unsigned int)stc.st_mtime, (unsigned int)stf.st_mtime,
- // (unsigned int)(stc.st_mtime - stf.st_mtime));
- if(stc.st_mtime >= stf.st_mtime) {
- if(ReadCache()) {
- LOGDBG("cPlaylist: using up-to-date ID3 cache");
- //LOGMSG(" Cache read OK.");
- return;
- }
- LOGMSG("cPlaylist: ID3 cache read FAILED");
- } else {
- LOGDBG("cPlaylist: ID3 cache not up-to-date, using old cache and scanning for changes");
- ReadCache();
- }
- }
- //else LOGERR("cPlaylist: stat(%s) failed");
- }
- //else LOGERR("cPlaylist: stat(%s) failed");
-
- if(xc.enable_id3_scanner) {
- m_Scanner = new cID3Scanner(*this);
- m_Scanner->Start();
- }
-}
-
-int cPlaylist::ReadPlaylist(const char *file)
-{
- static int depth = 0; /* limit recursion */
- cPipe p;
- cPlaylistReader *parser = NULL;
- FILE *f;
-
- if(strncmp(file, "http:", 5) && strncmp(file, "https:", 6)) {
- f = fopen(file, "r");
- } else {
- // fetch playlist from server using curl
- LOGDBG("cPlaylist: fetching remote playlist from %s", file);
- cString Cmd = cString::sprintf("curl %s", file);
- if(!p.Open(Cmd, "r")) {
- LOGERR("cPlaylist: CURL command (%s) failed", *Cmd);
- return false;
- }
- // process as normal file
- f = p;
- }
-
- if(f) {
- LOGDBG("cPlaylist: parsing %s", file);
- const char *ext = strrchr(file, '.');
- if(!strcasecmp(ext, ".pls"))
- parser = new cPlsReader(*this);
- else if(!strcasecmp(ext, ".asx"))
- parser = new cAsxReader(*this);
- else /*if(!strcasecmp(ext, ".m3u"))*/
- parser = new cM3uReader(*this); /* parses plain lists (.ram, ...) too ...*/
-
- /* get folder */
- cString Folder = file;
- const char *folder = strrchr(Folder, '/');
- if (folder)
- Folder.Truncate(folder - Folder + 1);
-
- int n = 0;
- cReadLine r;
- char *pt;
- while(NULL != (pt = r.Read(f)) && n < MAX_PLAYLIST_FILES) {
- if(NULL != (pt = parser->Parse(pt))) {
-
- if(xc.IsPlaylistFile(pt)) {
- parser->ResetCache();
- LOGDBG("cPlaylist: found playlist inside playlist");
- if(depth > 4)
- LOGMSG("cPlaylist: recursion too deep, skipped %s", pt);
- else {
- depth++;
- if(*pt == '/' ||
- (strstr(pt,"://")+1 == strchr(pt,'/') &&
- strchr(pt,'/') - pt < 8))
- n += ReadPlaylist(pt);
- else
- n += ReadPlaylist(cString::sprintf("%s%s", *Folder, pt));
- depth--;
- }
-
- } else {
- if(*pt == '/' ||
- (strstr(pt,"://")+1 == strchr(pt,'/') &&
- strchr(pt,'/') - pt < 8)) {
- // absolute path
- Add(new cPlaylistItem(pt));
- if(parser->Title())
- Last()->Title = parser->Title();
- } else {
- // relative path
- Add(new cPlaylistItem(pt, Folder, parser->Title()));
- }
- Last()->Position = parser->Position();
- parser->ResetCache();
- //LOGDBG("read_playlist: %s", pt);
- n++;
- }
- }
- }
-
- if(! (FILE*) p)
- fclose(f);
-
- if(n >= MAX_PLAYLIST_FILES)
- LOGMSG("cPlaylist: Found over %d matching files, list truncated!", n);
- LOGDBG("cPlaylist: Found %d matching files", n);
- return n;
- }
-
- LOGERR("cPlaylist: Error opening %s", file);
- return 0;
-}
-
-static cString LastDir(cString& path)
-{
- cString tmp = path;
- const char *pt = strrchr(tmp, '/');
- if(pt && pt > *tmp) {
- tmp.Truncate(pt - tmp);
- pt = strrchr(tmp, '/');
- if(pt)
- return cString(pt+1);
- }
- return cString(NULL);
-}
-
-bool cPlaylist::Read(const char *PlaylistFile, bool Recursive)
-{
- cMutexLock ml(&m_Lock);
- bool Result = true;
-
- // extract playlist root folder
- if(!*m_Folder) {
- const char *pt;
- m_Folder = PlaylistFile;
- if (NULL != (pt=strrchr(m_Folder, '/')))
- m_Folder.Truncate(pt - m_Folder + 1);
- }
-
- if(xc.IsPlaylistFile(PlaylistFile)) {
- // Read playlist file
- Result = ReadPlaylist(PlaylistFile);
- m_Origin = ePlaylist;
-
- cString dir = LastDir(m_Folder);
- const char *name = strrchr(PlaylistFile, '/');
- name = name ? name+1 : NULL;
- if(*dir && name)
- m_Name = cString::sprintf("%s - %s", *dir, name);
- else
- m_Name = name ?: "";
-
- strip_extension(m_Name);
-
- } else if(PlaylistFile[ 0] == '/' &&
- PlaylistFile[strlen(PlaylistFile)-1] == '/') {
- // Scan folder
- Result = ScanFolder(PlaylistFile, Recursive) > 0;
- m_Origin = eImplicit;
- Sort();
-
- if(!*m_Name) {
- m_Name = PlaylistFile;
- m_Name.Truncate( strrchr(m_Name, '/') - m_Name);
- if(strrchr(m_Name, '/')) {
- cString dir = LastDir(m_Name);
- if(*dir)
- m_Name = cString::sprintf("%s - %s", *dir, strrchr(m_Name, '/')+1);
- else
- m_Name = strrchr(m_Name, '/')+1;
- }
- }
-
- } else {
- // Single file
- Add(new cPlaylistItem(PlaylistFile));
- m_Origin = eImplicit;
-
- if(!*m_Name) {
- m_Name = LastDir(m_Folder);
- if(!*m_Name)
- m_Name = "";
- }
- }
-
- if(Count() < 1) {
- LOGMSG("Empty playlist %s !", PlaylistFile);
- Add(new cPlaylistItem(PlaylistFile));
- }
-
- m_Version++;
- return Result;
-}
-
-cString cPlaylist::EscapeMrl(const char *mrl)
-{
- static const uint8_t hex[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
- const uint8_t *fn = (const uint8_t*)mrl;
- int size = strlen(mrl) + 16;
- char *buf = (char *)malloc(size);
- int i = 0, found = 0;
- LOGDBG("cPlaylist::EscapeMrl('%s')", fn);
-
- // Wait for first '/' (do not escape mrl start dvd:/, http://a@b/, ...)
- if (*fn == '/')
- found = 3;
-
- while (*fn) {
- if(size-7 < i)
- buf = (char *)realloc(buf, (size=size+16));
- switch (*fn) {
- case 1 ... ' ':
- case 127 ... 255:
- case '#':
- case '%':
- case ':':
- case ';':
- case '\'':
- case '\"':
- case '(':
- case ')':
- if (found > 2) {
- buf[i++] = '%';
- buf[i++] = hex[(*fn & 0xf0)>>4];
- buf[i++] = hex[(*fn & 0x0f)];
- break;
- }
- default:
- // file:/... -> only one '/' before escaping
- // http://.../ --> three '/' before escaping
- if(!found && (fn[0] == ':' && fn[1] == '/')) {
- if(fn[2] == '/') {
- // ex. http://user:pass@host/... --> wait for third '/'
- buf[i++] = *fn++;
- buf[i++] = *fn++;
- found += 2;
- } else {
- // ex. file:/local_file
- buf[i++] = *fn++;
- found += 3;
- }
- } else if(*fn == '/') {
- found++;
- }
- buf[i++] = *fn;
- break;
- }
- fn++;
- }
-
- buf[i] = 0;
- LOGDBG(" --> '%s'", buf);
- return cString(buf, true);
-}
-
-cString cPlaylist::GetEntry(cPlaylistItem *i, bool isPlaylist, bool isCurrent)
-{
-
- cString Entry = "";
- if ((*i->Artist && xc.playlist_artist) || (*i->Album && xc.playlist_album)) {
- Entry = cString::sprintf("%s%s%s%s%s%s(%s%s%s)",
- isPlaylist ? (isCurrent ? "*" : " ") : "",
- isPlaylist ? "\t" : " ",
- xc.playlist_tracknumber ? (*i->Tracknumber ?: "") : "",
- xc.playlist_tracknumber ? (*i->Tracknumber ? " - " : "") : "",
- *i->Title,
- isPlaylist ? "\t" : " ",
- xc.playlist_artist ? (*i->Artist ?: "") : "",
- xc.playlist_artist && xc.playlist_album ? (*i->Artist && *i->Album ? ":" : "") : "",
- xc.playlist_album ? (*i->Album ?: "") : "");
- } else {
- Entry = cString::sprintf("%s%s%s%s%s",
- isPlaylist ? (isCurrent ? "*" : " ") : "",
- isPlaylist ? "\t" : " ",
- xc.playlist_tracknumber ? (*i->Tracknumber ?: "") : "",
- xc.playlist_tracknumber ? (*i->Tracknumber ? " - " : "") : "",
- *i->Title);
- }
- return Entry;
-}
diff --git a/tools/playlist.h b/tools/playlist.h
deleted file mode 100644
index 50c3d97a..00000000
--- a/tools/playlist.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * playlist.h: Media player playlist
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: playlist.h,v 1.8 2008-02-19 04:24:34 phintuka Exp $
- *
- */
-
-#ifndef __XINELIBOUTPUT_PLAYLIST_H
-#define __XINELIBOUTPUT_PLAYLIST_H
-
-#include <vdr/tools.h> // cString, cListObject, cList<>
-#include <vdr/thread.h> // cMutex
-
-
-//
-// cPlaylistItem
-//
-
-class cPlaylistItem : public cListObject
-{
- private:
- cPlaylistItem();
-
- virtual int Compare(const cListObject &ListObject) const;
-
- public:
- cPlaylistItem(const char *filename); /* file name with full path */
- cPlaylistItem(const char *filename, /* file name without path */
- const char *path,
- const char *title = NULL,
- int position = -1);
-
- cString Filename; /* file name and full path */
-
- // Metainfo (ID3 etc.)
- cString Title;
- cString Tracknumber;
- cString Artist;
- cString Album;
-
- // position in playlist (if given in playlist file)
- int Position;
-};
-
-
-//
-// cPlaylistChangeNotify interface
-//
-
-class cPlaylistChangeNotify
-{
- public:
- virtual void PlaylistChanged(const cPlaylistItem *Item) = 0;
-
- virtual ~cPlaylistChangeNotify() {}
-};
-
-
-//
-// cPlaylist
-//
-
-
-class cID3Scanner;
-
-class cPlaylist : protected cList<cPlaylistItem>
-{
- private:
-
- cMutex m_Lock;
- cString m_Name; // playlist (or folder) name
- cString m_Folder; // path to "root" of playlist
- cPlaylistItem *m_Current; // now playing
- unsigned int m_Version;
-
- enum { ePlaylist, eImplicit } m_Origin;
-
- cPlaylistChangeNotify *m_Menu;
- cID3Scanner *m_Scanner;
-
- protected:
-
- bool StoreCache(void);
- bool ReadCache(void);
-
- int ReadPlaylist(const char *PlaylistFile);
- int ScanFolder(const char *FolderName,
- bool Recursive = false,
- bool (config_t::*Filter)(const char *) = &config_t::IsAudioFile);
-
- friend class cID3Scanner;
- friend class cPlaylistReader;
- void PlaylistChanged(const cPlaylistItem *Item);
- cPlaylistItem *Last(void) { return cList<cPlaylistItem>::Last(); }
-
- public:
-
- cPlaylist();
- virtual ~cPlaylist();
-
- const cString& Name(void) const { return m_Name; }
-
- // listen for changes in playlist
- void Listen(cPlaylistChangeNotify *Menu = NULL);
-
- // read playlist from file or create playlist from directory tree
- bool Read(const char *PlaylistFile, bool Recursive = false);
- void StartScanner(void);
- void Del(cPlaylistItem *it);
-
- void Sort(void);
- int Count(void) const;
-
- // access/iterate playlist items
- cPlaylistItem *First(void) { return Next(NULL); }
- cPlaylistItem *Next(const cPlaylistItem *i);
-
- // get/set current (now playing) item
- cPlaylistItem *Current(void);
- void SetCurrent(cPlaylistItem *current);
- cPlaylistItem *Next(void);
- cPlaylistItem *Prev(void);
-
- static cString EscapeMrl(const char *name);
- static cString GetEntry(cPlaylistItem *i, bool isPlaylist = false, bool isCurrent = false);
-};
-
-
-#endif // __XINELIBOUTPUT_PLAYLIST_H
diff --git a/tools/rle.c b/tools/rle.c
deleted file mode 100644
index 2425630b..00000000
--- a/tools/rle.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * rle.c: RLE utils
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: rle.c,v 1.3 2009-02-16 16:14:58 phintuka Exp $
- *
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-
-#include "../xine_osd_command.h"
-
-#include "rle.h"
-
-
-#undef MAX
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-
-/*
- * rle_compress()
- *
- */
-int rle_compress(xine_rle_elem_t **rle_data, const uint8_t *data, uint w, uint h)
-{
- xine_rle_elem_t rle, *rle_p = 0, *rle_base;
- int x, y, num_rle = 0, rle_size = 8128;
- const uint8_t *c;
-
- rle_p = (xine_rle_elem_t*)malloc(4*rle_size);
- rle_base = rle_p;
-
- for (y = 0; y < h; y++) {
- rle.len = 0;
- rle.color = 0;
- c = data + y * w;
- for (x = 0; x < w; x++, c++) {
- if (rle.color != *c) {
- if (rle.len) {
- if ( (num_rle + h-y+1) > rle_size ) {
- rle_size *= 2;
- rle_base = (xine_rle_elem_t*)realloc( rle_base, 4*rle_size );
- rle_p = rle_base + num_rle;
- }
- *rle_p++ = rle;
- num_rle++;
- }
- rle.color = *c;
- rle.len = 1;
- } else {
- rle.len++;
- }
- }
- *rle_p++ = rle;
- num_rle++;
- }
-
- *rle_data = rle_base;
- return num_rle;
-}
-
-/*
- * rle_scale_nearest()
- *
- * - Simple nearest-neighbour scaling for RLE-compressed image
- * - fast scaling in compressed form without decompression
- */
-xine_rle_elem_t *rle_scale_nearest(const xine_rle_elem_t *old_rle, int *rle_elems,
- uint w, uint h, uint new_w, uint new_h)
-{
- #define FACTORBASE 0x100
- #define FACTOR2PIXEL(f) ((f)>>8)
- #define SCALEX(x) FACTOR2PIXEL(factor_x*(x))
- #define SCALEY(y) FACTOR2PIXEL(factor_y*(y))
-
- uint old_w = w, old_h = h;
- uint old_y = 0, new_y = 0;
- uint factor_x = FACTORBASE*new_w/old_w;
- uint factor_y = FACTORBASE*new_h/old_h;
- uint rle_size = MAX(8128, *rle_elems * new_h/h ); /* guess ... */
- uint num_rle = 0;
- xine_rle_elem_t *new_rle = (xine_rle_elem_t*)malloc(sizeof(xine_rle_elem_t)*rle_size);
- xine_rle_elem_t *new_rle_start = new_rle;
-
- /* we assume rle elements are breaked at end of line */
- while (old_y < old_h) {
- uint elems_current_line = 0;
- uint old_x = 0, new_x = 0;
-
- while (old_x < old_w) {
- uint new_x_end = SCALEX(old_x + old_rle->len);
-
- if (new_x_end > new_w) {
- new_x_end = new_w;
- }
-
- new_rle->len = new_x_end - new_x;
- new_rle->color = old_rle->color;
-
- old_x += old_rle->len;
- old_rle++; /* may be incremented to last element + 1 (element is not accessed anymore) */
-
- if (new_rle->len > 0) {
- new_x += new_rle->len;
- new_rle++;
-
- num_rle++;
- elems_current_line++;
-
- if ( (num_rle + 1) >= rle_size ) {
- rle_size *= 2;
- new_rle_start = (xine_rle_elem_t*)realloc( new_rle_start, 4*rle_size);
- new_rle = new_rle_start + num_rle;
- }
- }
- }
- if (new_x < new_w)
- (new_rle-1)->len += new_w - new_x;
- old_y++;
- new_y++;
-
- if (factor_y > FACTORBASE) {
- /* scale up -- duplicate current line ? */
- int dup = SCALEY(old_y) - new_y;
-
- /* if no lines left in (old) rle, copy all lines still missing from new */
- if (old_y == old_h)
- dup = new_h - new_y - 1;
-
- while (dup-- && (new_y+1<new_h)) {
- xine_rle_elem_t *prevline;
- uint n;
- if ( (num_rle + elems_current_line + 1) >= rle_size ) {
- rle_size *= 2;
- new_rle_start = (xine_rle_elem_t*)realloc( new_rle_start, 4*rle_size);
- new_rle = new_rle_start + num_rle;
- }
-
- /* duplicate previous line */
- prevline = new_rle - elems_current_line;
- for (n = 0; n < elems_current_line; n++) {
- *new_rle++ = *prevline++;
- num_rle++;
- }
- new_y++;
- }
-
- } else if (factor_y < FACTORBASE) {
- /* scale down -- drop next line ? */
- uint skip = new_y - SCALEY(old_y);
- if (old_y == old_h-1) {
- /* one (old) line left ; don't skip it if new rle is not complete */
- if (new_y < new_h)
- skip = 0;
- }
- while (skip-- &&
- old_y<old_h /* rounding error may add one line, filter it out */) {
- for (old_x = 0; old_x < old_w;) {
- old_x += old_rle->len;
- old_rle++;
- }
- old_y++;
- }
- }
- }
-
- *rle_elems = num_rle;
- return new_rle_start;
-}
diff --git a/tools/rle.h b/tools/rle.h
deleted file mode 100644
index d6900e8f..00000000
--- a/tools/rle.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * rle.h: RLE utils
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: rle.h,v 1.2 2009-02-16 16:14:58 phintuka Exp $
- *
- */
-
-#ifndef XINELIBOUTPUT_RLE_H_
-#define XINELIBOUTPUT_RLE_H_
-
-#if defined __cplusplus
-extern "C" {
-#endif
-
-typedef enum {
- scale_fast = 0, /* simple pixel doubling/dropping */
- scale_good_BW = 1, /* linear interpolation, palette re-generation */
-} scale_mode_t;
-
-
-struct xine_rle_elem_s;
-struct xine_clut_s;
-
-
-int rle_compress(struct xine_rle_elem_s **rle_data, const uint8_t *data, uint w, uint h);
-
-void rle_uncompress_lut8(const struct xine_rle_elem_s *rle_data,
- uint8_t *data, uint w, uint h);
-void rle_uncompress_argb(uint32_t *dst,
- const struct xine_rle_elem_s *rle_data, uint num_rle,
- uint w, uint h, uint stride,
- struct xine_clut_s *palette);
-
-/*
- * rle_scale_nearest()
- *
- * - Simple nearest-neighbour scaling for RLE-compressed image
- * - fast scaling in compressed form without decompression
- */
-struct xine_rle_elem_s *rle_scale_nearest(const struct xine_rle_elem_s *old_rle,
- int *rle_elems,
- uint w, uint h, uint new_w, uint new_h);
-
-
-#if defined __cplusplus
-}
-#endif
-
-#endif /* XINELIBOUTPUT_RLE_H_ */
diff --git a/tools/rtcp.h b/tools/rtcp.h
deleted file mode 100644
index 608f2daf..00000000
--- a/tools/rtcp.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * rtcp.h: RFC1889: RTCP
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: rtcp.h,v 1.3 2007-03-29 14:22:31 phintuka Exp $
- *
- */
-
-#ifndef XINELIBOUTPUT_RTCP_H_
-#define XINELIBOUTPUT_RTCP_H_
-
-#ifdef __APPLE__
-# include <machine/endian.h>
-#else
-# include <endian.h>
-#endif
-
-
-#ifndef PACKED
-# define PACKED __attribute__((packed))
-#endif
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-#elif __BYTE_ORDER == __LITTLE_ENDIAN
-#else
-# error __BYTE_ORDER not defined
-#endif
-
-#if defined __cplusplus
-extern "C" {
-#endif
-
-
-/* RTCP packet types */
-typedef enum {
- RTCP_SR = 200,
- RTCP_RR = 201,
- RTCP_SDES = 202,
- RTCP_BYE = 203,
- RTCP_APP = 204
-} rtcp_type_t;
-
-/* RTCP SDES types */
-typedef enum {
- RTCP_SDES_END = 0,
- RTCP_SDES_CNAME = 1,
-
- RTCP_SDES_NAME = 2,
- RTCP_SDES_EMAIL = 3,
- RTCP_SDES_PHONE = 4,
- RTCP_SDES_LOC = 5,
- RTCP_SDES_TOOL = 6,
- RTCP_SDES_NOTE = 7,
- RTCP_SDES_PRIV = 8
-} rtcp_sdes_type_t;
-
-/* RTCP common header word */
-typedef struct {
- union {
- uint8_t raw[4];
- struct {
-#if __BYTE_ORDER == __BIG_ENDIAN
- unsigned int version:2; /* protocol version */
- unsigned int padding:1; /* padding flag */
- unsigned int count:5; /* varies by packet type */
-#else
- unsigned int count:5; /* varies by packet type */
- unsigned int padding:1; /* padding flag */
- unsigned int version:2; /* protocol version */
-#endif
- unsigned int ptype:8; /* RTCP packet type */
-
- uint16_t length; /* pkt len in words, w/o this word */
- } PACKED;
- } PACKED;
-} PACKED rtcp_common_t;
-
-/* RTCP RR (Reception report) */
-typedef struct {
- uint32_t ssrc; /* data source being reported */
- unsigned int fraction:8; /* fraction lost since last SR/RR */
- int lost:24; /* cumul. no. pkts lost (signed!) */
- uint32_t last_seq; /* extended last seq. no. received */
- uint32_t jitter; /* interarrival jitter */
- uint32_t lsr; /* last SR packet from this source */
- uint32_t dlsr; /* delay since last SR packet */
-} PACKED rtcp_rr_t;
-
-/* RTCP SR (Sender report) */
-typedef struct {
- uint32_t ssrc;
- uint32_t ntp_sec; /* NTP timestamp, most significant word / seconds */
- uint32_t ntp_frac;
- uint32_t rtp_ts;
- uint32_t psent; /* packets sent */
- uint32_t osent; /* octets sent */
- rtcp_rr_t rr[0]; /* variable-length list */
-} PACKED rtcp_sr_t;
-
-/* RTCP SDES item */
-typedef struct {
- uint8_t type; /* type of item (rtcp_sdes_type_t) */
- uint8_t length; /* length of item (in octets) */
- char data[0]; /* text, not null-terminated */
-} PACKED rtcp_sdes_item_t;
-
-/* RTCP packet */
-typedef struct {
- rtcp_common_t hdr;
- union {
- rtcp_sr_t sr;
- struct {
- uint32_t ssrc;
- rtcp_rr_t rr[0];
- } PACKED rr;
- struct {
- uint32_t ssrc; /* first SSRC/CSRC */
- rtcp_sdes_item_t item[0]; /* list of SDES items */
- } PACKED sdes;
- struct {
- uint32_t src[0]; /* list of sources */
- /* can't express trailing text for reason */
- } PACKED bye;
- } PACKED;
-} PACKED rtcp_packet_t;
-
-
-#if defined __cplusplus
-};
-#endif
-
-#endif /* XINELIBOUTPUT_RTCP_H_ */
diff --git a/tools/rtp.h b/tools/rtp.h
deleted file mode 100644
index fa2ccf63..00000000
--- a/tools/rtp.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * rtp.h: RFC1889: RTP - A Transport Protocol for Real-Time Applications
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: rtp.h,v 1.3 2007-03-29 14:22:31 phintuka Exp $
- *
- */
-
-#ifndef XINELIBOUTPUT_RTP_H_
-#define XINELIBOUTPUT_RTP_H_
-
-#ifdef __APPLE__
-# include <machine/endian.h>
-#else
-# include <endian.h>
-#endif
-
-
-#ifndef PACKED
-# define PACKED __attribute__((packed))
-#endif
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-#elif __BYTE_ORDER == __LITTLE_ENDIAN
-#else
-# error __BYTE_ORDER not defined
-#endif
-
-#if defined __cplusplus
-extern "C" {
-#endif
-
-
-/* Generic RTP header extension */
-typedef struct stream_rtp_header_ext {
-
- union {
- uint8_t raw[4];
- uint32_t rawd;
-
- struct {
- uint16_t type;
- uint16_t size; /* Size of ext_data field in DWORDS */
- } PACKED;
- } PACKED;
-
- uint8_t ext_data[0];
-
-} PACKED stream_rtp_header_ext_t;
-
-
-/* Common RTP data header */
-typedef struct stream_rtp_header {
-
- union {
- uint8_t raw[12];
-
- struct {
-#if __BYTE_ORDER == __BIG_ENDIAN
- unsigned int version:2; /* protocol version */
- unsigned int padding:1; /* padding flag */
- unsigned int ext:1; /* header extension flag */
- unsigned int cc:4; /* CSRC count */
-
- unsigned int marker:1; /* marker bit */
- unsigned int paytype:7; /* payload type */
-#else
- unsigned int cc:4; /* CSRC count */
- unsigned int ext:1; /* header extension flag */
- unsigned int padding:1; /* padding flag */
- unsigned int version:2; /* protocol version */
-
- unsigned int paytype:7; /* payload type */
- unsigned int marker:1; /* marker bit */
-#endif
- uint16_t seq; /* sequence number */
- uint32_t ts; /* timestamp */
- uint32_t ssrc; /* synchronization source */
-
- /*uint32_t csrc[0];*/ /* optional CSRC list */
- } PACKED;
- } PACKED;
-
-
- union {
- stream_rtp_header_ext_t hdr_ext[0];
- uint8_t payload[0];
- } PACKED;
-
-
-} PACKED stream_rtp_header_t;
-
-#if defined __cplusplus
-};
-#endif
-
-#endif /* XINELIBOUTPUT_RTP_H_ */
-
diff --git a/tools/sap.h b/tools/sap.h
deleted file mode 100644
index 6b341efc..00000000
--- a/tools/sap.h
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * sap.h: RFC2974 Session Announcement Protocol (SAP) version 2
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: sap.h,v 1.8 2007-03-29 14:22:30 phintuka Exp $
- *
- */
-
-#ifndef XINELIBOUTPUT_SAP_H_
-#define XINELIBOUTPUT_SAP_H_
-
-#include <arpa/inet.h>
-#ifdef __APPLE__
-# include <machine/endian.h>
-#else
-# include <endian.h>
-#endif
-
-
-#ifndef PACKED
-# define PACKED __attribute__((packed))
-#endif
-
-/*#define LOG_SAP*/
-
-/* SAP IPv4 multicast addresses */
-#define SAP_IP_ADDRESS_GLOBAL "224.2.127.254" /* SAPv1 IP4 global scope multicast address */
-#define SAP_IP_ADDRESS_ORG "239.195.255.255" /* organization-local */
-#define SAP_IP_ADDRESS_LOCAL "239.255.255.255" /* local */
-#define SAP_IP_ADDRESS_LINK "224.0.0.255" /* link-local */
-
-#define SAP_IP_TTL 255
-#define SAP_UDP_PORT 9875
-
-
-typedef struct {
-
- /* RFC2974: SAP (Session Announcement Protocol) version 2 PDU */
-
- union {
- uint8_t raw0;
- struct {
-#if __BYTE_ORDER == __BIG_ENDIAN
- uint8_t version : 3;
- uint8_t addr_type : 1;
- uint8_t reserved : 1;
- uint8_t msg_type : 1;
- uint8_t encrypted : 1;
- uint8_t compressed : 1;
-#else
- uint8_t compressed : 1;
- uint8_t encrypted : 1;
- uint8_t msg_type : 1;
- uint8_t reserved : 1;
- uint8_t addr_type : 1;
- uint8_t version : 3;
-#endif
- } PACKED;
- } PACKED;
-
- uint8_t auth_len;
- uint16_t msgid_hash;
-
- union {
- uint8_t u8[4];
- uint32_t u32;
- } PACKED ip4_source;
-
- char payload[0];
-
-} PACKED sap_pdu_t;
-
-
-static inline sap_pdu_t *sap_create_pdu(uint32_t src_ip,
- uint16_t msgid,
- int announce,
- const char *payload_type,
- const char *payload)
-{
- sap_pdu_t *pdu;
- int length = sizeof(sap_pdu_t) + strlen(payload) + 3;
-
- if(payload_type)
- length += strlen(payload_type);
-
- if(! (pdu = (sap_pdu_t*)malloc(length)))
- return NULL;
-
- memset(pdu, 0, sizeof(sap_pdu_t));
- pdu->version = 1; /* SAP v1 / v2 */
- pdu->msg_type = announce ? 0 : 1;
- pdu->msgid_hash = msgid;
- pdu->ip4_source.u32 = src_ip;
-
- if(payload_type) {
- char *tmp = &pdu->payload[0];
- strcpy(tmp, payload_type);
- tmp += strlen(tmp) + 1;
- strcpy(tmp, payload);
- } else {
- /* payload type defaults to application/sdp */
- sprintf(&pdu->payload[0], "%s%c%c", payload, 0, 0);
- }
-
- return pdu;
-}
-
-static inline int sap_compress_pdu(sap_pdu_t *pdu)
-{
-#ifdef HAVE_ZLIB_H
-
- /* zlib compression */
-
- Compress();
-
- /*pdu->compressed = 1;*/
-
-#endif
-
- /* not implemented */
-
- pdu->compressed = 0;
- return -1;
-}
-
-static inline int sap_send_pdu(int *pfd, sap_pdu_t *pdu, uint32_t dst_ip)
-{
- int len = 0, r;
- int iReuse = 1, iLoop = 1, iTtl = SAP_IP_TTL;
- int fd;
-
- if(!pfd || *pfd < 0) {
- fd = socket(AF_INET, SOCK_DGRAM, 0);
-
- if(fd < 0) {
- LOGERR("socket() failed (UDP/SAP multicast)");
- return -1;
- }
-
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &iReuse, sizeof(int));
- setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &iTtl, sizeof(int));
- setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &iLoop, sizeof(int));
-
- // Connect to multicast address
- struct sockaddr_in sin;
- sin.sin_family = AF_INET;
- sin.sin_port = htons(SAP_UDP_PORT);
- sin.sin_addr.s_addr = dst_ip ? dst_ip : inet_addr(SAP_IP_ADDRESS_GLOBAL);
-
- if(connect(fd, (struct sockaddr *)&sin, sizeof(sin))==-1)
- LOGERR("UDP/SAP multicast connect() failed.");
-
- // Set to non-blocking mode
- fcntl (fd, F_SETFL, fcntl (fd, F_GETFL) | O_NONBLOCK);
-
- if(pfd)
- *pfd = fd;
-
- } else {
- fd = *pfd;
- }
-
- // size of PDU
- len += strlen(&pdu->payload[0]);
- if(!strstr(&pdu->payload[0], "\r\n")) {
- /* assume mime content type is present */
- len += 1;
- len += strlen(&pdu->payload[len]);
- len += sizeof(sap_pdu_t);
- }
-
- // network order
- pdu->msgid_hash = htons(pdu->msgid_hash);
-
- // send
- r = send(fd, pdu, len, 0);
- if(r < 0)
- LOGERR("UDP/SAP multicast send() failed.");
-
- if(!pfd)
- close(fd);
-
-#ifdef LOG_SAP
- /* log PDU */
- for(int i=0; i<len;) {
- char x[4096]="", a[4096]="";
- for(int j=0; j<16 && i<len; i++, j++) {
- char t[8], ch = ((char*)pdu)[i];
- sprintf(t, "%02X ", ((unsigned int)ch)&0xff);
- strcat(x, t);
- sprintf(t, "%c", (ch>=32 && ch<127) ? ch : '.');
- strcat(a, t);
- }
- LOGMSG("SAP: 0x%02x: %-50s%-18s", i/16-1, x, a);
- }
-#endif
-
- // back to host order
- pdu->msgid_hash = ntohs(pdu->msgid_hash);
-
- return r == len ? len : -1;
-}
-
-
-#endif /* XINELIBOUTPUT_SAP_H_ */
diff --git a/tools/sdp.h b/tools/sdp.h
deleted file mode 100644
index 514c29c1..00000000
--- a/tools/sdp.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * sdp.h: RFC2974 Session Description Protocol (SDP)
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: sdp.h,v 1.5 2009-02-10 12:42:38 phintuka Exp $
- *
- */
-
-#ifndef XINELIBOUTPUT_SDP_H_
-#define XINELIBOUTPUT_SDP_H_
-
-
-#define SDP_MIME_TYPE "application/sdp"
-
-#define SDP_PAYLOAD_MPEG_PES 96
-#define SDP_PAYLOAD_MPEG_TS 33
-
-static const char *vdr_sdp_description(const char *vdr_ip,
- int vdr_svdrp_port,
- int vdr_xineliboutput_port,
- const char *rtp_ip,
- uint32_t rtp_ssrc,
- uint32_t payload_type,
- int rtp_port,
- int rtp_ttl)
-{
- static uint8_t s_serial = 0;
- static cString s_data;
- static char s_hostname[257] = {0};
-
- uint64_t serial = (time(NULL) << 2) + ((s_serial++) & 0x03);
- cString payload;
-
- if (!s_hostname[0])
- gethostname(s_hostname, 256);
-
- if (payload_type == SDP_PAYLOAD_MPEG_PES) {
- payload = cString::sprintf(
- /* video/mp2p udp/rtp */
- /* media */ "m=video %d RTP/AVP 96"
- /* */ "\r\n" "a=rtpmap:96 MP2P/90000"
- , rtp_port
- );
- } else {
- payload = cString::sprintf(
- /* video/mp2t udp/rtp */
- /* media */ "m=video %d RTP/AVP 33"
- , rtp_port
- );
- }
-
- s_data = cString::sprintf(
- /*** session ***/
- /* version */ "v=0"
- /* origin */ "\r\n" "o=%s %u %"PRIu64" IN IP4 %s"
- /* name */ "\r\n" "s=%s@%s (multicast %s:%d)"
- /* opt:info */ /*"\r\n" "i=vdr-xineliboutput primary device output"*/
- /* time */ "\r\n" "t=0 0"
-
- /*** data stream(s) ***/
- /* connection */ "\r\n" "c=IN IP4 %s/%d"
- /* */ "\r\n" "a=recvonly"
- /* */ "\r\n" "a=type:broadcast"
- /* */ "\r\n" "a=x-plgroup:vdr"
- /* *media */ "\r\n" "%s"
-
- /* media */ /*"\r\n" "m=video %d udp MP2P"*/
- /* */ /*"\r\n" "a=mux:ps"*/
- /* */ /*"\r\n" "a=packetformat:RAW"*/
-#if 0
- /*** rtsp control port ***/
- /* connection */ "\r\n" "c=IN IP4 %s"
- /* media */ "\r\n" "m=control %d tcp/http rtsp"
-#endif
- /*** xineliboutput control port ***/
- /* connection */ "\r\n" "c=IN IP4 %s"
- /* media */ "\r\n" "m=control %d tcp x-vdr-xineliboutput"
-
- /*** SVDRP control port ***/
- /* connection */ "\r\n" "c=IN IP4 %s"
- /* media */ "\r\n" "m=control %d tcp x-svdrp"
-
- /* origin */
- , "vdr", rtp_ssrc, serial, vdr_ip
-
- /* name */
- , "vdr", s_hostname, rtp_ip, rtp_port
-
- /* media */
- , rtp_ip, rtp_ttl
- , *payload
-
-#if 0
- /* tcp/http control/rtsp */
- , vdr_ip
- , vdr_xineliboutput_port
-#endif
- /* tcp control/x-vdr-xineliboutput */
- , vdr_ip
- , vdr_xineliboutput_port
-
- /* tcp control/x-svdrp */
- , vdr_ip
- , vdr_svdrp_port
- );
- return s_data;
-}
-
-
-#endif /* XINELIBOUTPUT_SDP_H_ */
diff --git a/tools/time_pts.c b/tools/time_pts.c
deleted file mode 100644
index 81ee7c73..00000000
--- a/tools/time_pts.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * time_pts.c: Adjustable clock in PTS units
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: time_pts.c,v 1.4 2008-04-28 20:48:05 phintuka Exp $
- *
- */
-
-#define __STDC_FORMAT_MACROS
-#define __STDC_CONSTANT_MACROS
-#include <inttypes.h>
-#include <time.h>
-
-#include <vdr/config.h>
-
-#include "../logdefs.h" // logging
-
-#include "time_pts.h"
-
-
-#define MAX_SCR ((int64_t)0x1ffffffffLL)
-
-#if _POSIX_TIMERS > 0 && defined(_POSIX_MONOTONIC_CLOCK)
-#else
-# warning Posix monotonic clock not available
-#endif
-
-int cTimePts::m_Monotonic = -1;
-
-void cTimePts::Init(void)
-{
-#if _POSIX_TIMERS > 0 && defined(_POSIX_MONOTONIC_CLOCK)
- if(m_Monotonic >= 0)
- return;
-
- m_Monotonic = 0;
-
- struct timespec resolution;
- if(clock_getres(CLOCK_MONOTONIC, &resolution)) {
- LOGERR("cTimePts: clock_getres(CLOCK_MONOTONIC) failed");
- return;
- }
-
- LOGDBG("cTimePts: clock_gettime(CLOCK_MONOTONIC): clock resolution %d us",
- ((int)resolution.tv_nsec) / 1000);
-
- if( resolution.tv_sec == 0 && resolution.tv_nsec <= 1000000 ) {
- struct timespec tp;
- if(clock_gettime(CLOCK_MONOTONIC, &tp)) {
- LOGERR("cTimePts: clock_gettime(CLOCK_MONOTONIC) failed");
- } else {
- LOGDBG("cTimePts: using monotonic clock");
- m_Monotonic = 1;
- }
- }
-#endif
-}
-
-cTimePts::cTimePts(void)
-{
- m_Paused = false;
- m_ScrSpeed = 90000;
- m_Multiplier = 90000;
-
- Init();
-
- Set();
-}
-
-int64_t cTimePts::Now(void) const
-{
- if(m_Paused)
- return begin;
-
- struct timeval t;
-
-#if _POSIX_TIMERS > 0 && defined(_POSIX_MONOTONIC_CLOCK)
- if(m_Monotonic) {
- struct timespec tp;
-
- if(clock_gettime(CLOCK_MONOTONIC, &tp)) {
- LOGERR("cTimePts: clock_gettime(CLOCK_MONOTONIC) failed");
- return -1;
- }
-
- t.tv_sec = tp.tv_sec;
- t.tv_usec = tp.tv_nsec/1000;
-
- } else if (gettimeofday(&t, NULL)) {
- LOGERR("cTimePts: gettimeofday() failed");
- return -1;
- }
-#else
- if (gettimeofday(&t, NULL)) {
- LOGERR("cTimePts: gettimeofday() failed");
- return -1;
- }
-#endif
-
- t.tv_sec -= tbegin.tv_sec;
- if(t.tv_usec < tbegin.tv_usec) {
- t.tv_sec--;
- t.tv_usec += 1000000;
- }
- t.tv_usec -= tbegin.tv_usec;
-
- int64_t pts = 0;
- pts += (int64_t)t.tv_sec * (int64_t)m_ScrSpeed;
- pts += (int64_t)t.tv_usec * (int64_t)m_ScrSpeed / INT64_C(1000000);
-
- if(m_Multiplier != 90000)
- pts = pts * m_Multiplier / INT64_C(90000);
-
- return ( pts + begin ) & MAX_SCR;
-}
-
-void cTimePts::Set(int64_t Pts)
-{
- begin = Pts;
-
-#if _POSIX_TIMERS > 0 && defined(_POSIX_MONOTONIC_CLOCK)
- if(m_Monotonic) {
- struct timespec tp;
-
- if(!clock_gettime(CLOCK_MONOTONIC, &tp)) {
- tbegin.tv_sec = tp.tv_sec;
- tbegin.tv_usec = tp.tv_nsec/1000;
- return;
- }
-
- LOGERR("cTimePts: clock_gettime(CLOCL_MONOTONIC) failed");
- m_Monotonic = 0;
- }
-#endif
-
- gettimeofday(&tbegin, NULL);
-}
-
-void cTimePts::Pause(void)
-{
- Set(Now());
- m_Paused = true;
-}
-
-void cTimePts::Resume(void)
-{
- if(m_Paused) {
- Set(begin);
- m_Paused = false;
- }
-}
-
-void cTimePts::TrickSpeed(const int Multiplier)
-{
- Set(Now());
-
- if(Multiplier < 0)
- m_Multiplier = 90000 * (-Multiplier);
- else if(Multiplier > 0)
- m_Multiplier = 90000 / Multiplier;
- else
- LOGERR("cTimePts::SetSpeed: Multiplier=%d", Multiplier);
-}
-
-void cTimePts::SetScrSpeed(const int ScrSpeed)
-{
- Set(Now());
-
- m_ScrSpeed = ScrSpeed;
-}
diff --git a/tools/time_pts.h b/tools/time_pts.h
deleted file mode 100644
index fafc7199..00000000
--- a/tools/time_pts.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * time_pts.h: Adjustable clock in PTS units
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: time_pts.h,v 1.4 2008-04-28 20:48:05 phintuka Exp $
- *
- */
-
-#ifndef __TIME_PTS_H
-#define __TIME_PTS_H
-
-#include <stdint.h> // int64_t
-#include <sys/time.h> // struct timeval
-
-
-class cTimePts
-{
- private:
- int64_t begin; /* Start time (PTS) */
- struct timeval tbegin; /* Start time (real time) */
- bool m_Paused;
- int m_Multiplier;
- int m_ScrSpeed;
-
- static int m_Monotonic;
- static void Init(void);
-
- public:
- cTimePts(void);
-
- int64_t Now(void) const;
- void Set(int64_t Pts = 0LL);
-
- void Pause(void);
- void Resume(void);
- void TrickSpeed(const int Multiplier);
-
- void SetScrSpeed(const int ScrSpeed = 90000);
-};
-
-#endif // __TIME_PTS_H
diff --git a/tools/timer.c b/tools/timer.c
deleted file mode 100644
index f24e925a..00000000
--- a/tools/timer.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * timer.c: Threaded timer class
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: timer.c,v 1.2 2007-10-15 00:15:07 phintuka Exp $
- *
- */
-
-#include <sys/time.h>
-
-#include <vdr/config.h>
-#include <vdr/tools.h>
-#include <vdr/thread.h>
-
-#include "timer.h"
-
-//#define XINELIBOUTPUT_DEBUG
-//#define XINELIBOUTPUT_DEBUG_STDOUT
-#ifdef XINELIBOUTPUT_DEBUG
-# include "logdefs.h"
-#else
-# define TRACE(x)
-# define TRACEF(x)
-#endif
-
-// ---------------------------- cTimerThreadEvent ----------------------------
-
-class cTimerThreadEvent : public cListObject {
- public:
- cTimerThreadEvent(cTimerCallback *Handler, unsigned int TimeoutMs,
- bool DeleteOnCancel = false) :
- m_Handler(Handler),
- m_DeleteOnCancel(DeleteOnCancel),
- m_TimeoutMs(TimeoutMs)
- {
- m_NextEventTime = cTimeMs::Now();
- UpdateEventTime();
- }
-
- ~cTimerThreadEvent()
- {
- if(m_DeleteOnCancel && m_Handler)
- delete m_Handler;
- }
-
- void UpdateEventTime()
- {
- m_NextEventTime += m_TimeoutMs;
- }
-
- int TimeToNextEvent(void)
- {
- return m_NextEventTime - cTimeMs::Now();
- }
-
- virtual bool operator< (const cListObject &ListObject)
- {
- const cTimerThreadEvent *o = (cTimerThreadEvent *)&ListObject;
- return m_NextEventTime<o->m_NextEventTime;
- }
-
- virtual int Compare(const cListObject &ListObject) const
- {
- const cTimerThreadEvent *o = (cTimerThreadEvent *)&ListObject;
- if(m_NextEventTime<o->m_NextEventTime)
- return -1;
- else if(m_NextEventTime>o->m_NextEventTime)
- return 1;
- return 0;
- }
-
- cTimerCallback *m_Handler;
-
- protected:
- bool m_DeleteOnCancel;
- unsigned int m_TimeoutMs;
- int64_t m_NextEventTime;
-};
-
-// ------------------------------- cTimerThread ------------------------------
-
-class cTimerThread : public cThread {
- private:
- cTimerThread(cTimerThread&); // copy not allowed
-
- static cMutex m_InstanceLock;
- static cTimerThread *m_Instance; // singleton
-
- cMutex m_Lock;
- cCondVar m_Signal;
- cList<cTimerThreadEvent> m_Events;
- cTimerThreadEvent *m_RunningEvent;
- bool m_Finished;
- bool m_HandlerRunning;
-
- cTimerThread() :
- m_RunningEvent(NULL),
- m_Finished(false),
- m_HandlerRunning(false)
- {
- }
-
- virtual ~cTimerThread()
- {
- m_Lock.Lock();
- cTimerThreadEvent *ev;
- while(NULL != (ev = m_Events.First())) {
- m_Events.Del(ev,true);
- }
- m_Lock.Unlock();
- m_Signal.Broadcast();
- Cancel(1);
- }
-
- protected:
-
- virtual void Action()
- {
- TRACEF("cTimerThread::Action");
- m_Lock.Lock();
- while(m_Events.First()) {
- m_Signal.TimedWait(m_Lock,
- max(1, m_Events.First()->TimeToNextEvent()));
- TRACE("cTimerThread::Action waked up");
- while(NULL != (m_RunningEvent = m_Events.First()) &&
- m_RunningEvent->TimeToNextEvent() <= 0) {
- TRACE("cTimerThread::Action calling handler");
- m_HandlerRunning=true;
-// m_Lock.Unlock();
-// - can't unlock or running timer handler may be deleted while
-// executing (or thread may be killed by Delete)
- bool result = m_RunningEvent->m_Handler->TimerEvent();
-// m_Lock.Lock();
- m_HandlerRunning=false;
- if(!result) {
- if(m_RunningEvent) { // check if event was cancelled in handler...
- TRACE("cTimerThread::Action handler cancelled timer");
- m_Events.Del(m_RunningEvent, true);
- }
- } else {
- if(m_RunningEvent) {
- TRACE("cTimerThread::Action timer re-scheduled");
- m_RunningEvent->UpdateEventTime();
- m_Events.Sort();
- }
- }
- m_RunningEvent = NULL;
- }
- }
- m_Finished = true;
- m_Lock.Unlock();
- }
-
- void Add(cTimerThreadEvent *Event)
- {
- TRACEF("cTimerThread::Add");
- //m_Events.Del(Event, false);
- Event->Unlink();
- Del(Event->m_Handler);
- m_Events.Add(Event);
- m_Events.Sort();
- }
-
- bool Del(cTimerCallback *Handler, void *TargetId=NULL,
- bool inDestructor=false)
- {
- TRACEF("cTimerThread::Del");
- cTimerThreadEvent *ev = m_Events.First();
- while(ev) {
- if(ev->m_Handler == Handler ||
- (TargetId && ev->m_Handler->TargetId() == TargetId) ||
- (Handler && ev->m_Handler->is(Handler,Handler->size()))) {
- cTimerThreadEvent *nev = m_Events.Next(ev);
- if(inDestructor) ev->m_Handler=NULL;
- m_Events.Del(ev, true);
- ev = nev;
- } else
- ev = m_Events.Next(ev);
- }
- if(m_RunningEvent &&
- (m_RunningEvent->m_Handler == Handler ||
- m_RunningEvent->m_Handler->TargetId() == TargetId))
- m_RunningEvent = NULL;
- return !m_HandlerRunning && !m_RunningEvent && !m_Events.First();
- }
-
- public:
-
- static void AddEvent(cTimerCallback *Handler, unsigned int TimeoutMs,
- bool DeleteOnCancel=false)
- {
- TRACEF("cTimerThread::AddEvent");
- m_InstanceLock.Lock();
- if(m_Instance && m_Instance->m_Finished) {
- delete m_Instance;
- m_Instance = NULL;
- }
- if(!m_Instance) {
- m_Instance = new cTimerThread;
- m_Instance->m_Lock.Lock();
- m_Instance->Start();
- } else {
- m_Instance->m_Lock.Lock();
- m_Instance->m_Signal.Broadcast();
- }
- m_Instance->Add(new cTimerThreadEvent(Handler, max(1U,TimeoutMs),
- DeleteOnCancel));
- m_Instance->m_Lock.Unlock();
- m_InstanceLock.Unlock();
- }
-
- static void CancelEvent(cTimerCallback *Handler, void *TargetId = NULL,
- bool inDestructor=false)
- {
- TRACEF("cTimerThread::CancelEvent");
- m_InstanceLock.Lock();
- if(m_Instance && !m_Instance->m_Finished) {
- m_Instance->m_Lock.Lock();
- if(m_Instance->Del(Handler, TargetId, inDestructor) && !inDestructor) {
- m_Instance->m_Lock.Unlock();
- delete m_Instance;
- m_Instance = NULL;
- } else
- m_Instance->m_Lock.Unlock();
- }
- m_InstanceLock.Unlock();
- }
-
-};
-
-cMutex cTimerThread::m_InstanceLock;
-cTimerThread *cTimerThread::m_Instance = NULL;
-
-// ------------------------------ cTimerCallback -----------------------------
-
-cTimerCallback::~cTimerCallback()
-{
- TRACEF("cTimerCallback::~cTimerCallback");
- cTimerThread::CancelEvent(this, NULL, true);
-}
-
-void cTimerCallback::Set(cTimerCallback *handler, unsigned int TimeoutMs)
-{
- TRACEF("cTimerCallback::Set");
- cTimerThread::AddEvent(handler, TimeoutMs);
-}
-
-void cTimerCallback::Cancel(cTimerCallback *handler)
-{
- TRACEF("cTimerCallback::Cancel");
- cTimerThread::CancelEvent(handler);
-}
-
-// ------------------------------- cTimerEvent -------------------------------
-
-//cTimerEvent::cTimerEvent(unsigned int TimeoutMs)
-//{
-// TRACEF("cTimerEvent::cTimerEvent");
-//// cTimerThread::AddEvent(this, TimeoutMs, true);
-//}
-
-void cTimerEvent::AddEvent(unsigned int TimeoutMs)
-{
- TRACEF("cTimerEvent::AddEvent");
- cTimerThread::AddEvent(this, TimeoutMs, true);
-}
-
-void cTimerEvent::Cancel(cTimerEvent *&event)
-{
- TRACEF("cTimerEvent::Cancel");
- cTimerThread::CancelEvent(event);
- event = NULL;
-}
-
-void cTimerEvent::CancelAll(void *Target)
-{
- TRACEF("cTimerEvent::CancelAll");
- cTimerThread::CancelEvent(NULL, Target);
-}
-
-
-
-
-
-
-
diff --git a/tools/timer.h b/tools/timer.h
deleted file mode 100644
index 2ee8724b..00000000
--- a/tools/timer.h
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * timer.h: Threaded timer class
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: timer.h,v 1.1 2006-06-03 10:04:28 phintuka Exp $
- *
- */
-
-#ifndef __XINELIBOUTPUT_TIMER_H
-#define __XINELIBOUTPUT_TIMER_H
-
-//
-// cTimerCallback : timer callback handler interface
-//
-class cTimerCallback {
- protected:
- virtual bool TimerEvent() = 0; // return false to cancel timer
-
- virtual void *TargetId() { return (void*)this; }
- virtual int size() { return sizeof(*this); }
- virtual bool is(void *data, int len)
- {
- return len==sizeof(*this) && TargetId()==data;
- }
-
- friend class cTimerThread;
-
- public:
- static void Set(cTimerCallback *, unsigned int TimeoutMs);
- static void Cancel(cTimerCallback *);
-
- virtual ~cTimerCallback();
-};
-
-//
-// cTimerEvent : base class for timer events
-//
-class cTimerEvent : protected cTimerCallback {
- private:
- cTimerEvent(cTimerEvent&);
-
- protected:
- cTimerEvent() {};
-
- virtual void AddEvent(unsigned int TimeoutMs);
-
- static void CancelAll(void *Target);
-
- template<class TCLASS> friend void CancelTimerEvents(TCLASS*);
- friend class cTimerThread;
-
- public:
- static void Cancel(cTimerEvent *&);
-};
-
-//
-// make gcc 3.4.5 happy
-//
-template<class TCLASS, class TRESULT>
-cTimerEvent *CreateTimerEvent(TCLASS *c, TRESULT (TCLASS::*fp)(void),
- unsigned int TimeoutMs);
-template<class TCLASS, class TRESULT, class TARG1>
-cTimerEvent *CreateTimerEvent(TCLASS *c, TRESULT (TCLASS::*fp)(TARG1),
- TARG1 arg1,
- unsigned int TimeoutMs);
-template<class TCLASS>
-cTimerEvent *CreateTimerEvent(TCLASS *c, void (TCLASS::*fp)(void),
- unsigned int TimeoutMs, bool runOnce = true);
-template<class TCLASS, class TARG1>
-cTimerEvent *CreateTimerEvent(TCLASS *c, void (TCLASS::*fp)(TARG1),
- TARG1 arg1,
- unsigned int TimeoutMs, bool runOnce = true);
-
-//
-// Timer event templates
-//
-
-template <class TCLASS, class TRESULT>
-class cTimerFunctorR0 : public cTimerEvent {
-
- public:
-
- protected:
- typedef TRESULT (TCLASS::*TFUNC)(void);
-
- cTimerFunctorR0(TCLASS *obj, TFUNC f, unsigned int TimeoutMs) :
- m_obj(obj), m_f(f)
- {
- AddEvent(TimeoutMs);
- }
-
- virtual ~cTimerFunctorR0() {};
-
- virtual bool TimerEvent(void)
- {
- return (*m_obj.*m_f)();
- }
-
- virtual void *TargetId() { return (void*)m_obj; }
- virtual int size() { return sizeof(*this); }
- virtual bool is(void *data, int len)
- {
- return sizeof(*this)==len && !memcmp(this,data,len);
- }
-
- private:
- TCLASS *m_obj;
- TFUNC m_f;
-
- friend cTimerEvent *CreateTimerEvent<TCLASS,TRESULT>(TCLASS*,TFUNC,unsigned int);
-};
-
-template <class TCLASS, class TRESULT, class TARG1>
-class cTimerFunctorR1 : public cTimerEvent {
-
- public:
-
- protected:
- typedef TRESULT (TCLASS::*TFUNC)(TARG1);
-
- cTimerFunctorR1(TCLASS *obj, TFUNC f, TARG1 arg1, unsigned int TimeoutMs) :
- m_obj(obj), m_f(f), m_arg1(arg1)
- {
- AddEvent(TimeoutMs);
- }
-
- virtual ~cTimerFunctorR1() {};
-
- virtual bool TimerEvent(void)
- {
- return (*m_obj.*m_f)(m_arg1);
- }
-
- virtual void *TargetId() { return (void*)m_obj; }
- virtual int size() { return sizeof(*this); }
- virtual bool is(void *data, int len)
- {
- return sizeof(*this)==len && !memcmp(this,data,len);
- }
-
- private:
- TCLASS *m_obj;
- TFUNC m_f;
- TARG1 m_arg1;
-
- friend cTimerEvent *CreateTimerEvent<TCLASS,TRESULT,TARG1>(TCLASS*,TFUNC,TARG1,unsigned int);
-};
-
-template <class TCLASS>
-class cTimerFunctor0 : public cTimerEvent {
-
- public:
-
- protected:
- typedef void (TCLASS::*TFUNC)(void);
-
- cTimerFunctor0(TCLASS *obj, TFUNC f,
- unsigned int TimeoutMs, bool runOnce) :
- m_obj(obj), m_f(f), m_runAgain(!runOnce)
- {
- AddEvent(TimeoutMs);
- }
-
- virtual ~cTimerFunctor0() {};
-
- virtual bool TimerEvent(void)
- {
- (*m_obj.*m_f)();
- return m_runAgain;
- }
-
- virtual void *TargetId() { return (void*)m_obj; }
- virtual int size() { return sizeof(*this); }
- virtual bool is(void *data, int len)
- {
- return sizeof(*this)==len && !memcmp(this,data,len);
- }
-
- private:
- TCLASS *m_obj;
- TFUNC m_f;
- bool m_runAgain;
-
- friend cTimerEvent *CreateTimerEvent<TCLASS>(TCLASS*,TFUNC,unsigned int,bool);
-};
-
-template <class TCLASS, class TARG1>
-class cTimerFunctor1 : public cTimerEvent {
-
- public:
-
- protected:
- typedef void (TCLASS::*TFUNC)(TARG1);
-
- cTimerFunctor1(TCLASS *obj, TFUNC f, TARG1 arg1,
- unsigned int TimeoutMs, bool runOnce) :
- m_obj(obj), m_f(f), m_arg1(arg1), m_runAgain(!runOnce)
- {
- AddEvent(TimeoutMs);
- }
-
- virtual ~cTimerFunctor1() {};
-
- virtual bool TimerEvent(void)
- {
- (*m_obj.*m_f)(m_arg1);
- return m_runAgain;
- }
-
- virtual void *TargetId() { return (void*)m_obj; }
- virtual int size() { return sizeof(*this); }
- virtual bool is(void *data, int len)
- {
- return sizeof(*this)==len && !memcmp(this,data,len);
- }
-
- private:
- TCLASS *m_obj;
- TFUNC m_f;
- TARG1 m_arg1;
- bool m_runAgain;
-
- friend cTimerEvent *CreateTimerEvent<TCLASS,TARG1>(TCLASS*,TFUNC,TARG1,unsigned int,bool);
-};
-
-//
-// Function templates for timer event creation and cancellation
-//
-
-template<class TCLASS, class TRESULT>
-cTimerEvent *CreateTimerEvent(TCLASS *c, TRESULT (TCLASS::*fp)(void),
- unsigned int TimeoutMs)
-{
- return new cTimerFunctorR0<TCLASS,TRESULT>(c,fp,TimeoutMs);
-}
-
-template<class TCLASS, class TRESULT, class TARG1>
-cTimerEvent *CreateTimerEvent(TCLASS *c, TRESULT (TCLASS::*fp)(TARG1),
- TARG1 arg1,
- unsigned int TimeoutMs)
-{
- return new cTimerFunctorR1<TCLASS,TRESULT,TARG1>(c,fp,arg1,TimeoutMs);
-}
-
-template<class TCLASS>
-cTimerEvent *CreateTimerEvent(TCLASS *c, void (TCLASS::*fp)(void),
- unsigned int TimeoutMs, bool runOnce = true)
-{
- return new cTimerFunctor0<TCLASS>(c,fp,TimeoutMs,runOnce);
-}
-
-template<class TCLASS, class TARG1>
-cTimerEvent *CreateTimerEvent(TCLASS *c, void (TCLASS::*fp)(TARG1),
- TARG1 arg1,
- unsigned int TimeoutMs, bool runOnce = true)
-{
- return new cTimerFunctor1<TCLASS,TARG1>(c,fp,arg1,TimeoutMs,runOnce);
-}
-
-template<class TCLASS>
-void CancelTimerEvents(TCLASS *c)
-{
- cTimerEvent::CancelAll((void*)c);
-}
-
-
-// usage:
-//
-// 'this' derived from cTimerHandler:
-// Set timer:
-// cTimerCallback::Set(this, TimeoutMs);
-// Cancel timer:
-// - return false from handler or
-// - call cTimerCallback::Cancel(this); or
-// - delete 'this' object
-//
-// any function of any class:
-// Set timer:
-// - cTimerEvent *event = CreateTimerEvent(...);
-// example:
-// CreateTimerEvent(this, &cXinelibDevice::TimerEvent, 1, 1000);
-// -> calls this->cXinelibDevice::TimerEvent(1) every second until stopped.
-// Cancel timer:
-// - if handler returns bool: return false from handler
-// - handler is type of void: timer runs only once
-// - call cTimerEvent::Cancel(event)
-// Cancel all timers for object:
-// - Call CancelTimerEvents(object)
-// - Call CancelTimerEvents(this)
-
-
-#endif // __XINELIBOUTPUT_TIMER_H
-
-
diff --git a/tools/ts.c b/tools/ts.c
deleted file mode 100644
index 0f6e2576..00000000
--- a/tools/ts.c
+++ /dev/null
@@ -1,682 +0,0 @@
-/*
- * ts.c: MPEG-TS
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: ts.c,v 1.14 2009-09-09 11:58:40 phintuka Exp $
- *
- */
-
-/*#define LOG_PCR*/
-/*#define LOG_PMT*/
-
-#include <inttypes.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifndef LOG_MODULENAME
-# define LOG_MODULENAME "[mpeg-ts ] "
-# define SysLogLevel iSysLogLevel
-# include "../logdefs.h"
-#endif
-
-#include "mpeg.h"
-#include "ts.h"
-#include "pes.h"
-
-#ifdef LOG_PMT
-# define LOGPMT LOGMSG
-#else
-# define LOGPMT(x...)
-#endif
-
-#ifdef LOG_PCR
-# define LOGPCR LOGMSG
-#else
-# define LOGPCR(x...)
-#endif
-
-
-/*
- * ts_compute_crc32()
- *
- * taken from xine-lib demux_ts.c
- */
-static uint32_t ts_compute_crc32(const uint8_t *data, uint32_t length, uint32_t crc32)
-{
- static uint32_t crc32_table[256];
- static uint init_done = 0;
-
- if (!init_done) {
- uint32_t i, j, k;
- init_done = 1;
- for (i = 0 ; i < 256 ; i++) {
- k = 0;
- for (j = (i << 24) | 0x800000 ; j != 0x80000000 ; j <<= 1)
- k = (k << 1) ^ (((k ^ j) & 0x80000000) ? 0x04c11db7 : 0);
- crc32_table[i] = k;
- }
- }
-
- uint32_t i;
- for(i = 0; i < length; i++)
- crc32 = (crc32 << 8) ^ crc32_table[(crc32 >> 24) ^ data[i]];
-
- return crc32;
-}
-
-/*
- * parse_pat()
- *
- * - parse PAT for PMT pid and program number
- *
- * modified from xine-lib demux_ts.c
- */
-int ts_parse_pat(pat_data_t *pat, const uint8_t *pkt)
-{
- const uint8_t *original_pkt = pkt;
-
- if (! ts_PAYLOAD_START(pkt)) {
- LOGMSG ("parse_pat: PAT without payload unit start indicator");
- return 0;
- }
-
- /* jump to payload */
- pkt += pkt[4]; /* pointer */
- if (pkt - original_pkt > TS_SIZE) {
- LOGMSG("parse_pat: PAT with invalid pointer");
- return 0;
- }
-
- uint section_syntax_indicator = ((pkt[6] >> 7) & 0x01) ;
- uint section_length = ((pkt[6] & 0x03) << 8) | pkt[7];
-/*uint transport_stream_id = (pkt[8] << 8) | pkt[9];*/
-/*uint version_number = (pkt[10] >> 1) & 0x1f;*/
- uint current_next_indicator = pkt[10] & 0x01;
- uint section_number = pkt[11];
- uint last_section_number = pkt[12];
- uint32_t crc32, calc_crc32;
-
- crc32 = pkt[section_length + 4] << 24;
- crc32 |= pkt[section_length + 5] << 16;
- crc32 |= pkt[section_length + 6] << 8;
- crc32 |= pkt[section_length + 7] ;
-
- if ((section_syntax_indicator != 1) || !(current_next_indicator)) {
- LOGMSG("parse_pat: ssi error");
- return 0;
- }
-
- if (pkt - original_pkt > TS_SIZE - 4 - 1 - 3 - (int)section_length) {
- LOGMSG("parse_pat: unsupported PAT does not fit to single TS packet");
- return 0;
- }
-
- if ((section_number != 0) || (last_section_number != 0)) {
- LOGMSG("parse_pat: unsoupported PAT consists of multiple (%d) sections", last_section_number);
- return 0;
- }
-
- /* Check CRC */
- calc_crc32 = ts_compute_crc32 (pkt + 5, section_length + 3 - 4, 0xffffffff);
- if (crc32 != calc_crc32) {
- LOGMSG("parse_pat: invalid CRC");
- return 0;
- }
-
- /*
- * Process all programs in the program loop
- */
-
- const uint8_t *program;
- uint program_count;
-
- program_count = 0;
- for (program = pkt + 13;
- program < pkt + 13 + section_length - 9;
- program += 4) {
- uint program_number = (program[0] << 8) | program[1];
- uint pmt_pid = ((program[2] & 0x1f) << 8) | program[3];
-
- /* skip NIT pids */
- if (program_number == 0x0000)
- continue;
-
- pat->program_number[program_count] = program_number;
- pat->pmt_pid[program_count] = pmt_pid;
-
- LOGPMT("PAT acquired count=%d programNumber=0x%04x pmtPid=0x%04x",
- program_count,
- pat->program_number[program_count],
- pat->pmt_pid[program_count]);
-
- program_count++;
- }
-
- pat->program_number[program_count] = 0;
-
- return program_count;
-}
-
-/*
- * ts_get_reg_desc()
- *
- * Find the registration code (tag=5) and return it as a uint32_t
- * This should return "AC-3" or 0x41432d33 for AC3/A52 audio tracks.
- *
- * taken from xine-lib demux_ts.c
- */
-static void ts_get_reg_desc(uint32_t *dest, const uint8_t *data, int length)
-{
- const unsigned char *d = data;
-
- while (d < (data + length)) {
- if (d[0] == 5 && d[1] >= 4) {
- *dest = (d[2] << 24) | (d[3] << 16) | (d[4] << 8) | d[5];
- LOGPMT("parse_pmt: found registration format identifier 0x%.4x", *dest);
- return;
- }
- d += 2 + d[1];
- }
- LOGPMT("pare_pmt: found no format id");
- *dest = 0;
-}
-
-static int find_audio_track(pmt_data_t *pmt, uint pid)
-{
- int i;
- for (i = 0; i < pmt->audio_tracks_count; i++) {
- if (pmt->audio_tracks[i].pid == pid)
- return i;
- }
- return -1;
-}
-
-/*
- * ts_parse_pmt()
- *
- * modified from xine-lib demux_ts.c
- */
-int ts_parse_pmt (pmt_data_t *pmt, uint program_no, const uint8_t *pkt)
-{
- const uint8_t *originalPkt = pkt;
- const uint8_t *ptr = NULL;
- uint pusi = ts_PAYLOAD_START(pkt);
-
- uint32_t section_syntax_indicator;
- uint32_t section_length = 0; /* to calm down gcc */
- uint32_t program_number;
- uint32_t version_number;
- uint32_t current_next_indicator;
- uint32_t section_number;
- uint32_t last_section_number;
- uint32_t program_info_length;
- uint32_t crc32;
- uint32_t calc_crc32;
- uint32_t coded_length;
- uint pid;
- uint8_t *stream;
- uint i;
- int count;
- uint8_t len;
- uint offset = 0;
-
- /*
- * A new section should start with the payload unit start
- * indicator set. We allocate some mem (max. allowed for a PM section)
- * to copy the complete section into one chunk.
- */
- if (pusi) {
- pkt += pkt[4]; /* pointer */
- offset = 1;
-
- if (pmt->pmt != NULL)
- free(pmt->pmt);
- pmt->pmt = (uint8_t *) calloc(4096, sizeof(uint8_t));
- pmt->pmt_write_ptr = pmt->pmt;
-
- section_syntax_indicator = (pkt[6] >> 7) & 0x01;
- section_length = ((pkt[6] << 8) | pkt[7]) & 0x03ff;
- program_number = (pkt[8] << 8) | pkt[9];
- version_number = (pkt[10] >> 1) & 0x1f;
- current_next_indicator = pkt[10] & 0x01;
- section_number = pkt[11];
- last_section_number = pkt[12];
-
- LOGPMT("PMT: section_syntax: %d", section_syntax_indicator);
- LOGPMT(" section_length: %d", section_length);
- LOGPMT(" program_number: %#.4x", program_number);
- LOGPMT(" version_number: %d", version_number);
- LOGPMT(" c/n indicator: %d", current_next_indicator);
- LOGPMT(" section_number: %d", section_number);
- LOGPMT(" last_section_number: %d", last_section_number);
-
- if ((section_syntax_indicator != 1) || !current_next_indicator) {
- LOGMSG("parse_pmt: ssi error");
- return 0;
- }
-
- if (program_number != program_no) {
- /* several programs can share the same PMT pid */
- LOGMSG("parse_pmt: program number %i, looking for %i", program_number, program_no);
- return 0;
- }
-
- if ((section_number != 0) || (last_section_number != 0)) {
- LOGMSG("parse_pmt: unsupported PMT (%d sections)", last_section_number);
- return 0;
- }
- }
-
- if (!pusi) {
- section_length = (pmt->pmt[1] << 8 | pmt->pmt[2]) & 0x03ff;
- version_number = (pkt[10] >> 1) & 0x1f;
- }
-
- count = ts_PAYLOAD_SIZE(originalPkt);
-
- ptr = originalPkt + offset + (TS_SIZE - count);
- len = count - offset;
- memcpy(pmt->pmt_write_ptr, ptr, len);
- pmt->pmt_write_ptr += len;
-
- if (pmt->pmt_write_ptr < pmt->pmt + section_length) {
- LOGPMT("parse_pmt: didn't get all PMT TS packets yet...");
- return 0;
- }
-
- if (!section_length) {
- free(pmt->pmt);
- pmt->pmt = NULL;
- LOGMSG("parse_pmt: zero-length section");
- return 0;
- }
-
- LOGPMT("parse_pmt: have all TS packets for the PMT section");
-
- crc32 = (uint32_t) pmt->pmt[section_length+3-4] << 24;
- crc32 |= (uint32_t) pmt->pmt[section_length+3-3] << 16;
- crc32 |= (uint32_t) pmt->pmt[section_length+3-2] << 8;
- crc32 |= (uint32_t) pmt->pmt[section_length+3-1] ;
-
- /* Check CRC. */
- calc_crc32 = ts_compute_crc32 (pmt->pmt, section_length + 3 - 4, 0xffffffff);
- if (crc32 != calc_crc32) {
- LOGMSG("parse_pmt: invalid CRC32");
- return 0;
- }
-
- if (crc32 == pmt->crc32 && version_number == pmt->version_number) {
- LOGPMT("parse_pmt: PMT with CRC32=%d already parsed. Skipping.", crc32);
- return 0;
- }
-
- LOGPMT("parse_pmt: new PMT, parsing...");
- pmt->crc32 = crc32;
- pmt->version_number = version_number;
-
- /* reset PIDs */
- pmt->audio_tracks_count = 0;
- pmt->spu_tracks_count = 0;
- pmt->video_pid = INVALID_PID;
-
- /* ES definitions start here */
- program_info_length = ((pmt->pmt[10] << 8) | pmt->pmt[11]) & 0x0fff;
-
- stream = &pmt->pmt[12] + program_info_length;
- coded_length = 13 + program_info_length;
- if (coded_length > section_length) {
- LOGMSG("parse_pmt: PMT with inconsistent progInfo length");
- return 0;
- }
- section_length -= coded_length;
-
-
- /*
- * Extract the elementary streams.
- */
- while (section_length > 0) {
- unsigned int stream_info_length;
-
- pid = ((stream[1] << 8) | stream[2]) & 0x1fff;
- stream_info_length = ((stream[3] << 8) | stream[4]) & 0x0fff;
- coded_length = 5 + stream_info_length;
- if (coded_length > section_length) {
- LOGMSG("parse_pmt: PMT with inconsistent streamInfo length");
- return 0;
- }
-
- switch (stream[0]) {
- case ISO_11172_VIDEO:
- case ISO_13818_VIDEO:
- case ISO_14496_PART2_VIDEO:
- case ISO_14496_PART10_VIDEO:
- LOGPMT("parse_pmt: video pid 0x%.4x type %2.2x", pid, stream[0]);
- if (pmt->video_pid == INVALID_PID) {
- pmt->video_pid = pid;
- pmt->video_type = (ts_stream_type)stream[0];
- }
- break;
-
- case ISO_11172_AUDIO:
- case ISO_13818_AUDIO:
- case ISO_13818_PART7_AUDIO:
- case ISO_14496_PART3_AUDIO:
- if (pmt->audio_tracks_count < TS_MAX_AUDIO_TRACKS) {
- if (find_audio_track(pmt, pid) < 0) {
- LOGPMT("parse_pmt: audio pid 0x%.4x type %2.2x", pid, stream[0]);
- pmt->audio_tracks[pmt->audio_tracks_count].pid = pid;
- pmt->audio_tracks[pmt->audio_tracks_count].type = (ts_stream_type)stream[0];
- /* ts_get_lang_desc(pmt->audio_tracks[pmt->audio_tracks_count].lang, */
- /* stream + 5, stream_info_length); */
- pmt->audio_tracks_count++;
- }
- }
- break;
-
- case ISO_13818_PRIVATE:
- case ISO_13818_TYPE_C:
- break;
- case ISO_13818_PES_PRIVATE:
- for (i = 5; i < coded_length; i += stream[i+1] + 2) {
- if ((stream[i] == STREAM_DESCR_AC3) && (pmt->audio_tracks_count < TS_MAX_AUDIO_TRACKS)) {
- if (find_audio_track(pmt, pid) < 0) {
- LOGPMT("parse_pmt: AC3 audio pid 0x%.4x type %2.2x", pid, stream[0]);
- pmt->audio_tracks[pmt->audio_tracks_count].pid = pid;
- pmt->audio_tracks[pmt->audio_tracks_count].type = STREAM_AUDIO_AC3;
- /* demux_ts_get_lang_desc(pmt->audio_tracks[pmt->audio_tracks_count].lang, */
- /* stream + 5, stream_info_length); */
- pmt->audio_tracks_count++;
- break;
- }
- }
- /* DVBSUB */
- else if (stream[i] == STREAM_DESCR_DVBSUB) {
- uint pos;
- for (pos = i + 2;
- pos + 8 <= i + 2 + stream[i + 1]
- && pmt->spu_tracks_count < TS_MAX_SPU_TRACKS;
- pos += 8) {
- int no = pmt->spu_tracks_count;
-
- pmt->spu_tracks_count++;
-
- memcpy(pmt->spu_tracks[no].lang, &stream[pos], 3);
- pmt->spu_tracks[no].lang[3] = 0;
- pmt->spu_tracks[no].comp_page_id = (stream[pos + 4] << 8) | stream[pos + 5];
- pmt->spu_tracks[no].aux_page_id = (stream[pos + 6] << 8) | stream[pos + 7];
- pmt->spu_tracks[no].pid = pid;
-
- LOGPMT("parse_pmt: DVBSUB pid 0x%.4x: %s page %d %d type %2.2x", pid,
- pmt->spu_tracks[no].lang, pmt->spu_tracks[no].comp_page_id,
- pmt->spu_tracks[no].aux_page_id, stream[0]);
- }
- }
- }
- break;
-
- default:
-
- /* This following section handles all the cases where the audio track info is stored
- * in PMT user info with stream id >= 0x80
- * We first check that the stream id >= 0x80, because all values below that are
- * invalid if not handled above, then we check the registration format identifier
- * to see if it holds "AC-3" (0x41432d33) and if is does, we tag this as an audio stream.
- */
- if ((pmt->audio_tracks_count < TS_MAX_AUDIO_TRACKS) && (stream[0] >= 0x80) ) {
- if (find_audio_track(pmt, pid) < 0) {
- uint32_t format_identifier = 0;
- ts_get_reg_desc(&format_identifier, stream + 5, stream_info_length);
- /* If no format identifier, assume A52 */
- if ((format_identifier == 0x41432d33) || (format_identifier == 0)) {
- pmt->audio_tracks[pmt->audio_tracks_count].pid = pid;
- pmt->audio_tracks[pmt->audio_tracks_count].type = (ts_stream_type)stream[0];
- /* ts_get_lang_desc(pmt->audio_tracks[pmt->audio_tracks_count].lang, */
- /* stream + 5, stream_info_length); */
- pmt->audio_tracks_count++;
- break;
- }
- }
- } else {
- LOGPMT("parse_pmt: unknown stream_type: 0x%.2x pid: 0x%.4x", stream[0], pid);
- }
- break;
- }
- stream += coded_length;
- section_length -= coded_length;
- }
-
-
- /*
- * Get the current PCR PID.
- */
- pid = ((pmt->pmt[8] << 8) | pmt->pmt[9]) & 0x1fff;
- if (pmt->pcr_pid != pid) {
-
- if (pmt->pcr_pid == INVALID_PID)
- LOGPMT("parse_pmt: pcr pid 0x%.4x", pid);
- else
- LOGPMT("parse_pmt: pcr pid changed 0x%.4x", pid);
-
- pmt->pcr_pid = pid;
- }
-
- return 1;
-}
-
-/*
- * ts_get_pcr()
- */
-static int ts_get_pcr_1(const uint8_t *pkt, int64_t *ppcr)
-{
- if (!ts_ADAPT_FIELD_EXISTS(pkt)) {
- return 0;
- }
-
- if (ts_HAS_ERROR(pkt)) {
- LOGMSG("ts_get_pcr: transport error");
- return 0;
- }
-
- /* pcr flag ? */
- if (! (pkt[5] & 0x10))
- return 0;
-
- int64_t pcr;
- uint epcr;
-
- pcr = ((int64_t) pkt[6]) << 25;
- pcr += (int64_t) (pkt[7] << 17);
- pcr += (int64_t) (pkt[8] << 9);
- pcr += (int64_t) (pkt[9] << 1);
- pcr += (int64_t) ((pkt[10] & 0x80) >> 7);
-
- epcr = ((pkt[10] & 0x1) << 8) | pkt[11];
-
- LOGPCR("ts_get_pcr: PCR: %"PRId64", EPCR: %u", pcr, epcr);
- *ppcr = pcr;
- return 1;
-}
-
-int64_t ts_get_pcr(const uint8_t *pkt)
-{
- int64_t pcr = NO_PTS;
- ts_get_pcr_1(pkt, &pcr);
- return pcr;
-}
-
-int ts_get_pcr_n(const uint8_t *pkt, int npkt, int64_t *pcr)
-{
- pkt += TS_SIZE * npkt;
- while (npkt > 0) {
- npkt--;
- pkt -= TS_SIZE;
- if (ts_get_pcr_1(pkt, pcr))
- return 1;
- }
- return 0;
-}
-
-
-/*
- * ts_state_t
- */
-
-struct ts_state_s {
-
- uint8_t pusi_seen;
-
- uint8_t inside_pes; /* Scanning ES (PES start code seen and skipped) */
-
- uint32_t buf_len; /* bytes queued */
- uint32_t buf_size; /* buffer size */
- uint8_t buf[0]; /* payload: partial PES / video stream header etc. */
-};
-
-ts_state_t *ts_state_init(int buffer_size)
-{
- if (buffer_size < 8 * TS_SIZE)
- buffer_size = 8 * TS_SIZE;
-
- ts_state_t *ts = (ts_state_t*)calloc(1, sizeof(ts_state_t) + buffer_size);
- ts->buf_size = buffer_size;
- return ts;
-}
-
-void ts_state_reset(ts_state_t *ts)
-{
- int buf_size = ts->buf_size;
- memset(ts, 0, sizeof(ts_state_t));
- ts->buf_size = buf_size;
-}
-
-void ts_state_dispose(ts_state_t *ts)
-{
- free(ts);
-}
-
-/*
- * ts_add_payload()
- *
- * Add TS packet payload to buffer.
- * - PUSI resets the buffer
- * - all data before first PUSI is discarded
- */
-static int ts_add_payload(ts_state_t *ts, const uint8_t *data)
-{
- /* start from PUSI */
- if (!ts->pusi_seen) {
- if (!ts_PAYLOAD_START(data))
- return 0;
- ts->pusi_seen = 1;
- ts->buf_len = 0;
- }
-
- if (ts->buf_len >= ts->buf_size - TS_SIZE) {
- LOGMSG("ts_add_payload: buffer full");
- ts->buf_len -= TS_SIZE;
- memcpy(ts->buf, ts->buf+TS_SIZE, ts->buf_len);
- }
-
- int len = ts_PAYLOAD_SIZE(data);
- if (len > 0) {
- memcpy(ts->buf + ts->buf_len, ts_GET_PAYLOAD(data), len);
- ts->buf_len += len;
- }
-
- return ts->buf_len;
-}
-
-/*
- * ts_skip_payload()
- */
-static void ts_skip_payload(ts_state_t *ts, unsigned int n)
-{
- if (n < ts->buf_len) {
- ts->buf_len -= n;
- memcpy(ts->buf, ts->buf + n, ts->buf_len);
- } else {
- ts->buf_len = 0;
- }
-}
-
-/*
- * ts_scan_startcode()
- *
- * - discard all data until startcode (00 00 01) is found
- * - returns number of bytes left
- */
-static int ts_scan_startcode(ts_state_t *ts)
-{
- if (ts->buf_len > 2) {
- /* scan for PES or MPEG 00 00 01 */
- unsigned int i = 0, n = ts->buf_len - 2;
- while (i < n) {
- if (ts->buf[i+2] != 1)
- i += 3;
- else if(ts->buf[i+1])
- i += 2;
- else if(ts->buf[i])
- i++;
- else
- break;
- }
-
- /* skip data until start code */
- ts_skip_payload(ts, i);
- }
-
- return ts->buf_len;
-}
-
-/*
- * ts_get_pes()
- *
- * - scan for PES start
- * - return (PES) bytes queued
- */
-static int ts_get_pes(ts_state_t *ts, const uint8_t *data)
-{
- if (ts_add_payload(ts, data) > 0)
- return ts_scan_startcode(ts);
- return 0;
-}
-
-/*
- * ts_get_pts()
- */
-
-int64_t ts_get_pts(ts_state_t *ts, const uint8_t *data)
-{
- int64_t pts = NO_PTS;
- int cnt = ts_get_pes(ts, data);
-
- if (cnt > 14) {
- pts = pes_get_pts(ts->buf, ts->buf_len);
-
- if (pts < 0 && cnt > 2*TS_SIZE)
- ts_state_reset(ts);
- }
-
- return pts;
-}
-
-/*
- * ts_get_picture_type()
- */
-
-int ts_get_picture_type(ts_state_t *ts, const uint8_t *data, int h264)
-{
- int pic = NO_PICTURE;
- return pic;
-}
-
-/*
- * ts_get_video_size()
- */
-
-int ts_get_video_size(ts_state_t *ts, const uint8_t *data, video_size_t *size, int h264)
-{
- return 0;
-}
diff --git a/tools/ts.h b/tools/ts.h
deleted file mode 100644
index 98fa3f9e..00000000
--- a/tools/ts.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * ts.h: MPEG-TS header definitions
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: ts.h,v 1.12 2009-09-09 11:51:21 phintuka Exp $
- *
- */
-
-#ifndef _XINELIBOUTPUT_TS_H_
-#define _XINELIBOUTPUT_TS_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* Avoid warnings when included to VDR plugin */
-#undef TS_SYNC_BYTE
-#undef TS_SIZE
-#undef TS_PAYLOAD_EXISTS
-#undef TS_ADAPT_FIELD_EXISTS
-#undef TS_PAYLOAD_START
-#undef TS_ERROR
-#undef TS_PID_MASK_HI
-
-/*
- * Constants
- */
-
-#define TS_SYNC_BYTE 0x47
-#define TS_SIZE 188
-#define TS_ADAPT_FIELD_EXISTS 0x20
-#define TS_PAYLOAD_EXISTS 0x10
-#define TS_PAYLOAD_START 0x40
-#define TS_ERROR 0x80
-#define TS_PID_MASK_HI 0x1F
-
-#define ts_HAS_PAYLOAD(ts) ((ts)[3] & TS_PAYLOAD_EXISTS)
-#define ts_PAYLOAD_START(ts) ((ts)[1] & TS_PAYLOAD_START)
-#define ts_HAS_ERROR(ts) ((ts)[1] & TS_ERROR)
-#define ts_PID(ts) ((((ts)[1] & TS_PID_MASK_HI) << 8) + (ts)[2])
-#define ts_PAYLOAD_OFFSET(ts) (((ts)[3] & TS_ADAPT_FIELD_EXISTS) ? (ts)[4] + 5 : 4)
-
-#define ts_GET_PAYLOAD(ts) ((ts) + ts_PAYLOAD_OFFSET(ts))
-#define ts_PAYLOAD_SIZE(ts) (TS_SIZE - ts_PAYLOAD_OFFSET(ts))
-
-#define ts_ADAPT_FIELD_EXISTS(ts) ((ts)[3] & TS_ADAPT_FIELD_EXISTS)
-#define ts_ADAPT_FIELD_LENGTH(ts) (ts_ADAPT_FIELD_EXISTS(ts) ? (ts)[4] : 0)
-
-
-#define DATA_IS_TS(data) ((data)[0] == TS_SYNC_BYTE)
-
-/*
- * stream types (PMT)
- */
-
-typedef enum {
- ISO_11172_VIDEO = 0x01, /* ISO/IEC 11172 Video */
- ISO_13818_VIDEO = 0x02, /* ISO/IEC 13818-2 Video */
- ISO_11172_AUDIO = 0x03, /* ISO/IEC 11172 Audio */
- ISO_13818_AUDIO = 0x04, /* ISO/IEC 13818-3 Audi */
- ISO_13818_PRIVATE = 0x05, /* ISO/IEC 13818-1 private sections */
- ISO_13818_PES_PRIVATE = 0x06, /* ISO/IEC 13818-1 PES packets containing private data */
- ISO_13522_MHEG = 0x07, /* ISO/IEC 13512 MHEG */
- ISO_13818_DSMCC = 0x08, /* ISO/IEC 13818-1 Annex A DSM CC */
- ISO_13818_TYPE_A = 0x0a, /* ISO/IEC 13818-6 Multiprotocol encapsulation */
- ISO_13818_TYPE_B = 0x0b, /* ISO/IEC 13818-6 DSM-CC U-N Messages */
- ISO_13818_TYPE_C = 0x0c, /* ISO/IEC 13818-6 Stream Descriptors */
- ISO_13818_TYPE_D = 0x0d, /* ISO/IEC 13818-6 Sections (any type, including private data) */
- ISO_13818_AUX = 0x0e, /* ISO/IEC 13818-1 auxiliary */
- ISO_13818_PART7_AUDIO = 0x0f, /* ISO/IEC 13818-7 Audio with ADTS transport sytax */
- ISO_14496_PART2_VIDEO = 0x10, /* ISO/IEC 14496-2 Visual (MPEG-4) */
- ISO_14496_PART3_AUDIO = 0x11, /* ISO/IEC 14496-3 Audio with LATM transport syntax */
- ISO_14496_PART10_VIDEO = 0x1b, /* ISO/IEC 14496-10 Video (MPEG-4 part 10/AVC, aka H.264) */
- STREAM_VIDEO_MPEG = 0x80,
- STREAM_AUDIO_AC3 = 0x81,
- STREAM_DVBSUB = 0x100
-} ts_stream_type;
-
-/* stream info descriptors */
-#define STREAM_DESCR_AC3 0x6a
-#define STREAM_DESCR_DVBSUB 0x59
-
-/*
- * PAT
- */
-
-#define TS_MAX_PROGRAMS 64
-#define TS_MAX_PMTS 32
-#define TS_MAX_AUDIO_TRACKS 32
-#define TS_MAX_SPU_TRACKS 32
-
-typedef struct {
- int program_number[TS_MAX_PROGRAMS];
- uint16_t pmt_pid[TS_MAX_PROGRAMS];
-} pat_data_t;
-
-int ts_parse_pat(pat_data_t *pat_data, const uint8_t *ts_data);
-
-
-/*
- * PMT
- */
-
-#define INVALID_PID 0xffff
-
-typedef struct {
- uint8_t *pmt; /* raw data */
- uint8_t *pmt_write_ptr;
-
- uint32_t crc32;
- uint version_number;
-
- uint16_t pcr_pid;
- uint16_t video_pid;
- ts_stream_type video_type;
-
- uint8_t audio_tracks_count;
- uint8_t spu_tracks_count;
-
- struct {
- uint16_t pid;
- ts_stream_type type;
- /*uint8_t lang[8];*/
- } audio_tracks[TS_MAX_AUDIO_TRACKS];
-
- struct {
- uint16_t pid;
- uint8_t lang[8];
- uint16_t comp_page_id;
- uint16_t aux_page_id;
- } spu_tracks[TS_MAX_SPU_TRACKS];
-
-} pmt_data_t;
-
-/*
- * parse_pmt()
- *
- * returns 1 : PMT parsed and changed
- * 0 : error or unchanged pmt
- */
-int ts_parse_pmt(pmt_data_t *pmt, uint program_no, const uint8_t *ts_data);
-
-/*
- * PCR
- */
-
-int64_t ts_get_pcr(const uint8_t *data);
-int ts_get_pcr_n(const uint8_t *pkt, int npkt, int64_t *pcr);
-
-/*
- * TS->ES, simple ES parsers
- */
-
-typedef struct ts_state_s ts_state_t;
-struct video_size_s;
-
-ts_state_t *ts_state_init(int buffer_size);
-void ts_state_reset(ts_state_t *ts);
-void ts_state_dispose(ts_state_t *ts);
-
-int64_t ts_get_pts(ts_state_t *ts, const uint8_t *data);
-int ts_get_picture_type(ts_state_t *ts, const uint8_t *data, int h264);
-int ts_get_video_size(ts_state_t *ts, const uint8_t *data, struct video_size_s *size, int h264);
-
-
-#ifdef __cplusplus
-} /* extern "C" { */
-#endif
-
-#endif // _XINELIBOUTPUT_TS_H_
diff --git a/tools/udp_buffer.h b/tools/udp_buffer.h
deleted file mode 100644
index 6044b794..00000000
--- a/tools/udp_buffer.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * udp_buffer.h: Ring buffer for UDP/RTP streams
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: udp_buffer.h,v 1.6 2009-03-24 19:35:23 phintuka Exp $
- *
- */
-
-#ifndef __UDP_BUFFER_H
-#define __UDP_BUFFER_H
-
-#include <stdint.h>
-
-#include <vdr/config.h> // VDRVERSNUM
-
-#include "../xine_input_vdr_net.h" // frame headers
-#include "ts.h"
-
-#define UDP_BUFFER_SIZE 0x100 // 2^n
-#define UDP_BUFFER_MASK 0xff // 2^n - 1
-
-#if UDP_BUFFER_MASK != UDP_SEQ_MASK
-# error Buffer handling error !!!
-#endif
-
-
-class cUdpBackLog
-{
- friend class cUdpScheduler;
-
- private:
-
- cUdpBackLog(cUdpBackLog&);
-
- stream_rtp_header_impl_t *m_UdpBuffer[UDP_BUFFER_SIZE];
- int m_UdpBufLen[UDP_BUFFER_SIZE]; /* size of allocated memory, not frame */
- int m_PayloadSize[UDP_BUFFER_SIZE]; /* size of frame */
- unsigned int m_SeqNo; /* next (outgoing) sequence number */
- unsigned int m_RtpSeqNo; /* next (outgoing) RTP sequence number */
-
- protected:
-
- cUdpBackLog()
- {
- memset(m_UdpBuffer, 0, sizeof(stream_rtp_header_impl_t *)*UDP_BUFFER_SIZE);
- memset(m_UdpBufLen, 0, sizeof(int) * UDP_BUFFER_SIZE);
- memset(m_PayloadSize, 0, sizeof(int) * UDP_BUFFER_SIZE);
- m_SeqNo = 0;
- m_RtpSeqNo = random();
- }
-
- void Clear(int HowManyFrames)
- {
- // Clear n last frames from buffer.
- // (called to adjust sequence numbering when some
- // already allocated frames won't be sent)
- //
- // Note: Nothing is freed.
- // To completely reset buffer it must be deleted and re-created.
- //
- m_SeqNo = (m_SeqNo + UDP_BUFFER_SIZE - HowManyFrames) & UDP_BUFFER_MASK;
- }
-
- virtual ~cUdpBackLog()
- {
- for(int i=0; i<UDP_BUFFER_SIZE; i++)
- if(m_UdpBuffer[i]) {
- //m_UdpBufLen[i] = 0;
- delete[] m_UdpBuffer[i];
- m_UdpBuffer[i] = NULL;
- }
- }
-
- stream_rtp_header_impl_t *Get(int UdpSeqNo)
- {
- int BufIndex = UdpSeqNo & UDP_BUFFER_MASK;
- return m_UdpBuffer[BufIndex];
- }
-
- int PayloadSize(int UdpSeqNo)
- {
- int BufIndex = UdpSeqNo & UDP_BUFFER_MASK;
- return m_UdpBuffer[BufIndex] ? m_PayloadSize[BufIndex] : 0;
- }
-
- stream_rtp_header_impl_t *MakeFrame(uint64_t StreamPos,
- const uchar *Data, int DataLen)
- {
- int UdpPacketLen = DataLen + sizeof(stream_rtp_header_impl_t);
- int BufIndex = m_SeqNo & UDP_BUFFER_MASK;
-
- // old buffer too small ? free it
- if(m_UdpBuffer[BufIndex] && m_UdpBufLen[BufIndex] < UdpPacketLen) {
- delete[] m_UdpBuffer[BufIndex];
- m_UdpBuffer[BufIndex] = NULL;
- }
-
- // no buffer ? alloc it
- if(!m_UdpBuffer[BufIndex]) {
- m_UdpBuffer[BufIndex] = (stream_rtp_header_impl_t*)new uchar[UdpPacketLen];
- m_UdpBufLen[BufIndex] = UdpPacketLen;
- }
- m_PayloadSize[BufIndex] = DataLen;
-
- // Fill frame to buffer
- stream_rtp_header_impl_t *header = m_UdpBuffer[BufIndex];
-
- memcpy(header->payload, Data, DataLen);
-
- // RTP header
- header->rtp_hdr.raw[0] = RTP_VERSION_BYTE | RTP_HDREXT_BIT;
-#if VDRVERSNUM >= 10701
- if (DATA_IS_TS(Data))
- header->rtp_hdr.raw[1] = RTP_PAYLOAD_TYPE_TS;
- else
- header->rtp_hdr.raw[1] = RTP_PAYLOAD_TYPE_PES;
-#else
- header->rtp_hdr.raw[1] = RTP_PAYLOAD_TYPE_PES;
-#endif
- header->rtp_hdr.seq = htons(m_RtpSeqNo & 0xFFFF);
- /*header->rtp_hdr.ts = htonl((uint32_t)(RtpScr.Now() & 0xffffffff));*/
- /*header->rtp_hdr.ssrc = htonl(m_ssrc);*/
-
- // RTP header extension
- header->hdr_ext.hdr.size = htons(RTP_HEADER_EXT_X_SIZE);
- header->hdr_ext.hdr.type = htons(RTP_HEADER_EXT_X_TYPE);
-
- // UDP header
- header->hdr_ext.pos = htonull(StreamPos);
- header->hdr_ext.seq = htons(m_SeqNo);
-
- header->hdr_ext.padding1 = 0;
-
- m_RtpSeqNo = (m_RtpSeqNo + 1) & 0xFFFF;
- m_SeqNo = (m_SeqNo + 1) & UDP_SEQ_MASK;
-
- return header;
- }
-};
-
-
-#endif
diff --git a/tools/udp_pes_scheduler.c b/tools/udp_pes_scheduler.c
deleted file mode 100644
index d46a99a8..00000000
--- a/tools/udp_pes_scheduler.c
+++ /dev/null
@@ -1,938 +0,0 @@
-/*
- * udp_pes_scheduler.h: PES scheduler for UDP/RTP streams
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: udp_pes_scheduler.c,v 1.52 2009-08-19 12:19:43 phintuka Exp $
- *
- */
-
-//#define LOG_UDP_RATE
-//#define LOG_RESEND
-//#define LOG_SCR
-
-#define __STDC_FORMAT_MACROS
-#define __STDC_CONSTANT_MACROS
-#include <inttypes.h>
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-
-#include <vdr/config.h>
-#include <vdr/tools.h>
-#include <vdr/videodir.h>
-
-#include "../logdefs.h" // logging
-#include "../config.h" // configuration data
-#include "../xine_input_vdr_net.h" // frame headers and constants
-
-#include "ts.h"
-#include "pes.h"
-#include "udp_buffer.h"
-#include "time_pts.h"
-#include "cxsocket.h"
-#include "sap.h" // SAP - Session Announcement Protocol
-#include "sdp.h" // SDP - Session Description Protocol
-#include "rtcp.h" // RTCP
-
-#include "udp_pes_scheduler.h"
-
-
-#ifdef LOG_RESEND
-# define LOGRESEND LOGDBG
-#else
-# define LOGRESEND(x...)
-#endif
-
-#ifdef LOG_SCR
-# define LOGSCR LOGDBG
-#else
-# define LOGSCR(x...)
-#endif
-
-/*
- * constants
- */
-
-const uint MAX_QUEUE_SIZE = 64; // ~ 65 ms with typical DVB stream
-const uint MAX_LIVE_QUEUE_SIZE = (64+60); // ~ 100 ms with typical DVB stream
-const uint HARD_LIMIT = (4*1024); // ~ 40 Mbit/s === 4 Mb/s
-
-const uint MAX_BURST_BYTES = 32768; // 32 kb
-const uint MAX_BURST_FRAMES = 15; // 15 UDP packets
-
-const uint RTCP_MIN_INTERVAL = 45000; // 500 ms (pts units)
-
-// initial burst length after seek (500ms = ~13 video frames)
-const int64_t INITIAL_BURST_TIME = INT64_C(45000); // pts units (90kHz)
-
-// assume seek when when pts difference between two frames exceeds this (2,5 seconds)
-const int64_t JUMP_LIMIT_TIME = INT64_C(225000); // pts units (90kHz)
-
-const uint SCHEDULER_MIN_DELAY_MS = 3;
-const uint SCHEDULER_MAX_DELAY_MS = 20;
-
-static inline int64_t abs64(int64_t val) { return val<0 ? -val : val; }
-
-cUdpScheduler::cUdpScheduler()
-{
-
- // Scheduler data
-
- m_ScrSource = eScrDetect;
- m_CurrentAudioVtime = 0;
- m_CurrentVideoVtime = 0;
- m_CurrentPcr = 0;
-
- m_MasterClock.Set(INT64_C(0));
-
- m_BurstBytes = 0;
- m_BurstFrames = 0;
-
- m_Master = false;
- m_TrickSpeed = false;
-
- // RTP
-
- srandom(time(NULL) ^ getpid());
-
- m_ssrc = random();
- LOGDBG("RTP SSRC: 0x%08x", m_ssrc);
- m_LastRtcpTime = 0;
- m_Frames = 0;
- m_Octets = 0;
- m_RtpScr.Set((int64_t)random());
-
- m_fd_sap = -1;
-
- // Queuing
-
- int i;
- for(i=0; i<MAX_UDP_HANDLES; i++)
- m_Handles[i] = -1;
-
- m_BackLog = new cUdpBackLog;
-
- m_QueueNextSeq = 0;
- m_QueuePending = 0;
-
- // Thread
-
- Start();
-}
-
-cUdpScheduler::~cUdpScheduler()
-{
- m_Lock.Lock();
-
- Cancel(-1);
- m_Cond.Broadcast();
- m_CondWait.Signal();
- m_Lock.Unlock();
-
- Cancel(3);
-
- if(m_fd_rtcp.open() || m_fd_rtp.open())
- Send_SAP(false);
-
- CLOSESOCKET(m_fd_sap);
-
- delete m_BackLog;
-}
-
-void cUdpScheduler::Scheduler_Sleep(int ms)
-{
- m_CondWait.Wait(ms);
- m_BurstBytes = 0;
- m_BurstFrames = 0;
-}
-
-bool cUdpScheduler::AddRtp(void)
-{
- cMutexLock ml(&m_Lock);
-
- if(m_fd_rtcp.open()) {
- LOGERR("cUdpScheduler::AddHandle: RTCP socket already open !");
- Send_SAP(false);
- m_fd_rtcp.close();
- }
-
- /* need new ssrc */
- m_ssrc = random();
- LOGDBG("RTP SSRC: 0x%08x", m_ssrc);
-
- //
- // RTP
- //
- if(! m_fd_rtp.create(cxSocket::estDGRAM)) {
- LOGERR("socket() failed (UDP/RTP multicast)");
- return false;
- }
-
- // Set buffer sizes
- m_fd_rtp.set_buffers(KILOBYTE(256), 2048);
-
- // Set multicast socket options
- if(!m_fd_rtp.set_multicast(xc.remote_rtp_ttl)) {
- m_fd_rtp.close();
- return false;
- }
-
- if(xc.remote_local_ip[0]) {
- struct sockaddr_in name;
- name.sin_family = AF_INET;
- name.sin_addr.s_addr = inet_addr(xc.remote_local_ip);
- if(name.sin_addr.s_addr == INADDR_NONE)
- LOGERR("Local address %s is invalid", xc.remote_local_ip);
- name.sin_port = htons(xc.remote_rtp_port);
- if (bind(m_fd_rtp.handle(), (struct sockaddr *)&name, sizeof(name)) < 0)
- LOGERR("bind(%s:%d) failed for udp/rtp multicast", xc.remote_local_ip, xc.remote_rtp_port);
-#if 0
- struct ip_mreqn mreqn;
- mreqn.imr_multiaddr.s_addr = inet_addr(xc.remote_rtp_addr);
- mreqn.imr_address.s_addr = inet_addr(xc.remote_local_ip); /* IP address of local interface */
- //mreqn.imr_ifindex = ; /* interface index */
- if(setsockopt(m_fd_rtp.handle(), IPPROTO_IP, IP_MULTICAST_IF, &mreqn, sizeof(mreqn)))
- LOGERR("setting multicast source address/interface failed");
-#endif
- }
-
- // Connect to multicast address
- if(!m_fd_rtp.connect(xc.remote_rtp_addr, xc.remote_rtp_port) &&
- errno != EINPROGRESS) {
- LOGERR("connect(fd_rtp) failed. Address=%s, port=%d",
- xc.remote_rtp_addr, xc.remote_rtp_port);
- m_fd_rtp.close();
- return false;
- }
-
- // Set to non-blocking mode
- m_fd_rtp.set_blocking(false);
-
- //
- // RTCP
- //
- if(! m_fd_rtcp.create(cxSocket::estDGRAM))
- LOGERR("socket() failed (RTCP multicast)");
-
- m_fd_rtcp.set_buffers(16384, 16384);
- if(!m_fd_rtcp.set_multicast(xc.remote_rtp_ttl))
- m_fd_rtcp.close();
-
- if(xc.remote_local_ip[0]) {
- struct sockaddr_in name;
- name.sin_family = AF_INET;
- name.sin_addr.s_addr = inet_addr(xc.remote_local_ip);
- name.sin_port = htons(xc.remote_rtp_port+1);
- if (bind(m_fd_rtcp.handle(), (struct sockaddr *)&name, sizeof(name)) < 0)
- LOGERR("bind(%s:%d) failed for udp/rtp multicast", xc.remote_local_ip, xc.remote_rtp_port);
-#if 0
- struct ip_mreqn mreqn;
- mreqn.imr_multiaddr.s_addr = inet_addr(xc.remote_rtp_addr);
- mreqn.imr_address.s_addr = inet_addr(xc.remote_local_ip); /* IP address of local interface */
- //mreqn.imr_ifindex = ; /* interface index */
- if(setsockopt(m_fd_rtp.handle(), IPPROTO_IP, IP_MULTICAST_IF, &mreqn, sizeof(mreqn)))
- LOGERR("setting multicast source address/interface failed");
-#endif
- }
-
- /* RTCP port (RFC 1889) */
- if(!m_fd_rtcp.connect(xc.remote_rtp_addr, xc.remote_rtp_port + 1) &&
- errno != EINPROGRESS) {
- LOGERR("connect(fd_rtcp) failed. Address=%s, port=%d",
- xc.remote_rtp_addr, xc.remote_rtp_port +
- (xc.remote_rtp_port&1)?-1:1);
- m_fd_rtcp.close();
- }
-
- // Set to non-blocking mode
- m_fd_rtcp.set_blocking(false);
-
- // Finished
-
- if(!AddHandle(m_fd_rtp))
- LOGERR("cUdpScheduler::AddHandle(fd_rtp) failed");
-
- Send_SAP(true);
-
- return true;
-}
-
-bool cUdpScheduler::AddHandle(int fd)
-{
- cMutexLock ml(&m_Lock);
-
- int i;
-
- for(i=0; i<MAX_UDP_HANDLES; i++)
- if(m_Handles[i] < 0 || m_Handles[i] == fd) {
- m_Handles[i] = fd;
-
- /* query socket send buffer size */
- m_wmem[i] = 0x10000; /* default to 64k */
- socklen_t l = sizeof(int);
- if(getsockopt(m_Handles[i], SOL_SOCKET, SO_SNDBUF, &m_wmem[i], &l))
- LOGERR("getsockopt(SO_SNDBUF) failed");
- m_wmem[i] /= 2; /* man 7 socket */
-
- m_Cond.Broadcast();
-
- return true;
- }
-
- return false;
-}
-
-void cUdpScheduler::RemoveRtp(void)
-{
- cMutexLock ml(&m_Lock);
-
- if(m_fd_rtp.open() || m_fd_rtcp.open()) {
- Send_SAP(false);
-
- RemoveHandle(m_fd_rtp);
-
- m_fd_rtp.close();
- m_fd_rtcp.close();
- CLOSESOCKET(m_fd_sap);
- }
-}
-
-void cUdpScheduler::RemoveHandle(int fd)
-{
- cMutexLock ml(&m_Lock);
-
- int i;
- for(i=0; i<MAX_UDP_HANDLES; i++)
- if(m_Handles[i] == fd)
- break;
-
- for(; i<MAX_UDP_HANDLES-1; i++)
- m_Handles[i] = m_Handles[i+1];
-
- m_Handles[MAX_UDP_HANDLES-1] = -1;
-
- if(m_Handles[0] < 0) {
- // No clients left ...
-
- // Flush all buffers
- m_QueueNextSeq = 0;
- m_QueuePending = 0;
-
- m_BackLogDeleteMutex.Lock();
- delete m_BackLog;
- m_BackLog = new cUdpBackLog;
- m_BackLogDeleteMutex.Unlock();
-
- m_Frames = 0;
- m_Octets = 0;
- }
-}
-
-int cUdpScheduler::Poll(int TimeoutMs, bool Master)
-{
- cMutexLock ml(&m_Lock);
-
- m_Master = Master;
-
- if(m_Handles[0] < 0) {
- // no clients, so we can eat all data we are given ...
- return DEFAULT_POLL_SIZE;
- }
-
- uint limit = m_Master ? MAX_QUEUE_SIZE : MAX_LIVE_QUEUE_SIZE;
- if(m_QueuePending >= limit) {
- uint64_t WaitEnd = cTimeMs::Now();
- if(TimeoutMs >= 0)
- WaitEnd += (uint64_t)TimeoutMs;
-
- while (cTimeMs::Now() < WaitEnd &&
- Running() &&
- m_QueuePending >= limit)
- m_Cond.TimedWait(m_Lock, 5);
- }
-
- return limit > m_QueuePending ? limit - m_QueuePending : 0;
-}
-
-bool cUdpScheduler::Flush(int TimeoutMs)
-{
- cMutexLock ml(&m_Lock);
-
- if(m_Handles[0] < 0)
- return true;
-
- if(m_QueuePending > 0) {
- uint64_t WaitEnd = cTimeMs::Now();
- if(TimeoutMs >= 0)
- WaitEnd += (uint64_t)TimeoutMs;
-
- while (cTimeMs::Now() < WaitEnd &&
- Running() &&
- m_QueuePending > 0)
- m_Cond.TimedWait(m_Lock, 5);
- }
- return m_QueuePending == 0;
-}
-
-void cUdpScheduler::Clear(void)
-{
- cMutexLock ml(&m_Lock);
-
- m_BackLog->Clear(m_QueuePending);
-
- m_QueuePending = 0;
- m_Cond.Broadcast();
-
- m_ScrSource = eScrDetect;
-}
-
-void cUdpScheduler::Pause(bool On)
-{
- cMutexLock ml(&m_Lock);
-
- if(On)
- m_MasterClock.Pause();
- else
- m_MasterClock.Resume();
-
- m_TrickSpeed = false;
-}
-
-void cUdpScheduler::TrickSpeed(const int Multiplier)
-{
- cMutexLock ml(&m_Lock);
-
-#ifdef LOG_SCR
- if(Multiplier == 1 || Multiplier == -1) {
- LOGMSG("UDP clock --> normal");
- } else if(Multiplier < 0)
- LOGMSG("UDP clock --> %dx", -Multiplier);
- else
- LOGMSG("UDP clock --> 1/%d", Multiplier);
-#endif
-
- m_MasterClock.TrickSpeed(Multiplier);
-
- m_TrickSpeed = (Multiplier==-1 || Multiplier==1) ? false : true;
-}
-
-void cUdpScheduler::SetScrSpeed(const int Speed)
-{
- cMutexLock ml(&m_Lock);
-
- m_MasterClock.SetScrSpeed(Speed);
- m_RtpScr.SetScrSpeed(Speed);
-}
-
-bool cUdpScheduler::Queue(uint64_t StreamPos, const uchar *Data, int Length)
-{
- cMutexLock ml(&m_Lock);
-
- if(m_Handles[0] < 0)
- return true;
-
- uint limit = m_Master ? MAX_QUEUE_SIZE : MAX_LIVE_QUEUE_SIZE;
- if(m_QueuePending >= limit)
- return false;
-
- m_BackLog->MakeFrame(StreamPos, Data, Length);
- m_QueuePending++;
-
- m_Cond.Broadcast();
-
- return true;
-}
-
-void cUdpScheduler::QueuePadding(void)
-{
- cMutexLock ml(&m_Lock);
-
- if (m_Handles[0] < 0)
- return;
-
- if (m_QueuePending > 2)
- return;
-
- QueuePaddingInternal();
-
- m_Cond.Broadcast();
-}
-
-void cUdpScheduler::QueuePaddingInternal(void)
-{
- static unsigned const char Padding[] = {0x00,0x00,0x01,0xBE,0x00,0x02,0xff,0xff};
-
- int PrevSeq = (m_QueueNextSeq + UDP_BUFFER_SIZE - 1) & UDP_BUFFER_MASK;
- stream_rtp_header_impl_t *Frame = m_BackLog->Get(PrevSeq);
- if (Frame) {
- int PrevLen = m_BackLog->PayloadSize(PrevSeq);
- uint64_t Pos = ntohll(Frame->hdr_ext.pos) + PrevLen - 8;
- m_BackLog->MakeFrame(Pos, Padding, 8);
- } else
- m_BackLog->MakeFrame(0, Padding, 8);
-
- m_QueuePending++;
-}
-
-int cUdpScheduler::CalcElapsedVtime(int64_t pts, ScrSource_t ScrSource)
-{
- int64_t diff = 0;
-
- switch (ScrSource) {
-
- case eScrFromVideo:
- diff = pts - m_CurrentVideoVtime;
- if (diff > JUMP_LIMIT_TIME || (-diff) > JUMP_LIMIT_TIME) { // 1 s (must be > GOP)
- // RESET
- LOGSCR("cUdpScheduler SCR RESET (Video jump %lld->%lld)", m_CurrentVideoVtime, pts);
- m_CurrentVideoVtime = pts;
-
- // Use video pts for sync only in audioless trickspeeds
- // (audio has smaller, constant and increasing intervals)
- if (m_TrickSpeed)
- m_MasterClock.Set(m_CurrentVideoVtime + INITIAL_BURST_TIME);
-
- return -1;
- }
- if (diff < 0) /* ignore small negative differences (B/P frames are sent out-of-order) */
- diff = 0;
- else
- m_CurrentVideoVtime = pts;
- break;
-
- case eScrFromAudio:
- diff = abs64(pts - m_CurrentAudioVtime);
- if (diff > JUMP_LIMIT_TIME) { // 1 sec
- // RESET
- LOGSCR("cUdpScheduler SCR RESET (Audio jump %lld->%lld)", m_CurrentAudioVtime, pts);
- m_CurrentAudioVtime = pts;
- m_MasterClock.Set(m_CurrentAudioVtime + INITIAL_BURST_TIME);
- return -1;
- }
- m_CurrentAudioVtime = pts;
- break;
-
- case eScrFromPcr:
- diff = pts - m_CurrentPcr;
- if (diff > JUMP_LIMIT_TIME || diff < 0) { // 1 sec
- // RESET
- LOGSCR("cUdpScheduler RESET (PCR jump %lld->%lld)", m_CurrentPcr, pts);
- m_CurrentPcr = pts;
- m_MasterClock.Set(m_CurrentPcr + INITIAL_BURST_TIME);
- return -1;
- }
- m_CurrentPcr = pts;
- break;
-
- default: break;
- }
-
- return (int) diff;
-}
-
-void cUdpScheduler::Send_RTCP(void)
-{
- if(!m_fd_rtcp.open())
- return;
-
- uint64_t scr = m_RtpScr.Now();
-
- if(scr > (m_LastRtcpTime + RTCP_MIN_INTERVAL)) {
- uint8_t frame[2048], *content = frame;
- char hostname[64] = "";
- rtcp_packet_t *msg = (rtcp_packet_t *)content;
- struct timeval tv;
-
- gettimeofday(&tv, NULL);
- gethostname(hostname, sizeof(hostname)-1);
- hostname[sizeof(hostname)-1] = 0;
-
- // SR (Sender report)
- msg->hdr.raw[0] = 0x81; // RTP version = 2, Report count = 1 */
- msg->hdr.ptype = RTCP_SR;
- msg->hdr.length = htons(6); // length 6 dwords
-
- msg->sr.ssrc = htonl(m_ssrc);
- msg->sr.ntp_sec = htonl(tv.tv_sec + 0x83AA7E80);
- msg->sr.ntp_frac = htonl((uint32_t)((double)tv.tv_usec*(double)(1LL<<32)*1.0e-6));
- msg->sr.rtp_ts = htonl((uint32_t)(scr & 0xffffffff));
- msg->sr.psent = htonl((uint32_t)(m_Frames & 0xffffffff));
- msg->sr.osent = htonl((uint32_t)(m_Octets & 0xffffffff));
-
- content += sizeof(rtcp_common_t) + sizeof(rtcp_sr_t);
- msg = (rtcp_packet_t *)content;
-
- // SDES
- msg->hdr.raw[0] = 0x81; // RTP version = 2, Report count = 1 */
- msg->hdr.ptype = RTCP_SDES;
- msg->hdr.count = 1;
-
- msg->sdes.ssrc = m_ssrc;
- msg->sdes.item[0].type = RTCP_SDES_CNAME;
- sprintf(msg->sdes.item[0].data, "VDR@%s:%d%c%c%c",
- hostname[0] ? hostname : xc.remote_rtp_addr,
- xc.remote_rtp_port, 0, 0, 0);
- msg->sdes.item[0].length = strlen(msg->sdes.item[0].data);
- msg->hdr.length = htons(1 + 1 + ((msg->sdes.item[0].length - 2) + 3) / 4);
-
- content += sizeof(rtcp_common_t) + 4*ntohs(msg->hdr.length);
- msg = (rtcp_packet_t *)content;
-
- // Send
-#ifndef LOG_RTCP
- (void) m_fd_rtcp.send(frame, content - frame);
-#else
- LOGMSG("RTCP send (%d)", m_fd_rtcp.send(frame, content - frame));
- for(int i=0; i<content-frame; i+=16)
- LOGMSG("%02X %02X %02X %02X %02X %02X %02X %02X "
- "%02X %02X %02X %02X %02X %02X %02X %02X "
- " %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c",
- frame[i+0],frame[i+1],frame[i+2],frame[i+3],
- frame[i+4],frame[i+5],frame[i+6],frame[i+7],
- frame[i+8],frame[i+9],frame[i+10],frame[i+11],
- frame[i+12],frame[i+13],frame[i+14],frame[i+15],
- frame[i+0],frame[i+1],frame[i+2],frame[i+3],
- frame[i+4],frame[i+5],frame[i+6],frame[i+7],
- frame[i+8],frame[i+9],frame[i+10],frame[i+11],
- frame[i+12],frame[i+13],frame[i+14],frame[i+15]);
-#endif
-
- m_LastRtcpTime = scr;
- }
-}
-
-
-void cUdpScheduler::Send_SAP(bool Announce)
-{
- if(!xc.remote_rtp_sap || !m_fd_rtp.open())
- return;
-
- char ip[64] = "";
- uint32_t local_addr = m_fd_rtp.get_local_address(ip);
-
- if(!local_addr)
- return;
-
- uint32_t payload_type = VDRVERSNUM > 10702 ? SDP_PAYLOAD_MPEG_TS : SDP_PAYLOAD_MPEG_PES;
- const char *sdp_descr = vdr_sdp_description(ip,
- 2001,
- xc.listen_port,
- xc.remote_rtp_addr,
- payload_type,
- m_ssrc,
- xc.remote_rtp_port,
- xc.remote_rtp_ttl);
- if(!sdp_descr)
- return;
-
-#if 1
- /* store copy of SDP data */
- if(m_fd_sap < 0) {
- cString fname = AddDirectory(VideoDirectory,
- cString::sprintf("xineliboutput@%s.sdp",
- ip));
- FILE *fp = fopen(fname, "w");
- if(fp) {
- fprintf(fp, "%s", sdp_descr);
- fclose(fp);
- }
- }
-#endif
-
- sap_pdu_t *pdu = sap_create_pdu(local_addr,
- Announce,
- (m_ssrc >> 16 | m_ssrc) & 0xffff,
- "application/sdp",
- sdp_descr);
-
- if(!sap_send_pdu(&m_fd_sap, pdu, 0))
- LOGERR("SAP/SDP announce failed");
- free(pdu);
-
- if(!Announce)
- CLOSESOCKET(m_fd_sap);
-}
-
-#ifdef LOG_SCR
-static const char ScrSourceName[][6] = {"???", "VIDEO", "PS1", "AUDIO", "PCR"};
-#endif
-
-void cUdpScheduler::Schedule(const uchar *Data, int Length)
-{
- int64_t pts = NO_PTS;
- int elapsed = 0;
- ScrSource_t ScrSource = eScrDetect;
-
- // Get timestamp from data
-
- if (DATA_IS_TS(Data)) {
- if (ts_get_pcr_n(Data, Length/TS_SIZE, &pts)) {
- LOGSCR("UDP PCR: %"PRId64, pts);
- ScrSource = eScrFromPcr;
- elapsed = CalcElapsedVtime(pts, eScrFromPcr);
- }
- } else /* if (DATA_IS_PES(Data)) */ {
- if (PES_HAS_PTS(Data)) {
- ScrSource = IS_VIDEO_PACKET(Data) ? eScrFromVideo : IS_AUDIO_PACKET(Data) ? eScrFromAudio : eScrDetect;
- pts = pes_get_pts(Data, Length);
- elapsed = CalcElapsedVtime(pts, ScrSource);
- }
- }
-
- if (m_ScrSource < ScrSource)
- m_ScrSource = ScrSource;
-
- if(elapsed > 0) {
-
- int64_t now = m_MasterClock.Now();
- int64_t SendTime = ScrSource==eScrFromVideo ? m_CurrentVideoVtime :
- ScrSource==eScrFromAudio ? m_CurrentAudioVtime :
- ScrSource==eScrFromPcr ? m_CurrentPcr : now;
-
- LOGSCR("PTS: %lld (%s) elapsed %d ms (PID %02x)", pts, ScrSourceStr[ScrSource],
- pts_to_ms(elapsed), DATA_IS_TS(Data) ? TS_PID(Data) : Data[3]);
-
- //
- // Detect discontinuity (against SCR)
- //
- if (now > SendTime && (now - SendTime) > JUMP_LIMIT_TIME) {
- LOGSCR("cUdpScheduler MasterClock init (was in past) %s", ScrSourceStr[ScrSource]);
- now = SendTime + INITIAL_BURST_TIME;
- m_MasterClock.Set(now);
- } else if (now < SendTime && (SendTime - now) > JUMP_LIMIT_TIME) {
- LOGSCR("cUdpScheduler MasterClock init (was in future) %s", ScrSourceStr[ScrSource]);
- now = SendTime + INITIAL_BURST_TIME;
- m_MasterClock.Set(now);
- }
-
- //
- // Delay
- //
- while (SendTime > now) {
-
- uint delay_ms = pts_to_ms(SendTime - now);
- if (delay_ms < SCHEDULER_MIN_DELAY_MS)
- break;
-
- LOGSCR("cUdpScheduler sleeping %d ms (time ref: %s, beat interval %d ms)",
- delay_ms, ScrSourceStr[ScrSource], pts_to_ms(elapsed));
-
- if (delay_ms > SCHEDULER_MAX_DELAY_MS)
- delay_ms = SCHEDULER_MAX_DELAY_MS;
-
- Scheduler_Sleep(delay_ms);
-
- now = m_MasterClock.Now();
- }
- }
-}
-
-void cUdpScheduler::Action(void)
-{
- /* UDP Scheduler needs high priority */
- const int priority = -5;
- SetPriority(priority);
- errno = 0;
- if ((nice(priority) == -1) && errno)
- LOGDBG("cUdpScheduler: Can't nice to value: %d", priority);
-
- m_Lock.Lock();
-
- while (Running()) {
-
- if(m_Handles[0] < 0) {
- m_Cond.TimedWait(m_Lock, 5000);
- continue;
- }
-
- // Wait until we have outgoing data in queue
- if(m_QueuePending <= 0) {
- m_BurstFrames = m_BurstBytes = 0;
- m_Cond.TimedWait(m_Lock, 100);
- if(m_QueuePending <= 0) {
- // Still nothing...
- // Send padding frame once in 100ms so clients can detect
- // possible missing frames and server shutdown
- QueuePaddingInternal();
- }
- continue; // to check Running()
- }
-
- // Take next frame from queue
- stream_rtp_header_impl_t *frame = m_BackLog->Get(m_QueueNextSeq);
- int PayloadSize = m_BackLog->PayloadSize(m_QueueNextSeq);
- int UdpPacketLen = PayloadSize + sizeof(stream_udp_header_t);
- int RtpPacketLen = PayloadSize + sizeof(stream_rtp_header_impl_t);
-
- m_QueueNextSeq = (m_QueueNextSeq + 1) & UDP_BUFFER_MASK;
- m_QueuePending--;
-
- m_Cond.Broadcast();
- m_BackLogDeleteMutex.Lock(); /* ensure frame will not be deleted from queue */
- m_Lock.Unlock();
-
- // Schedule frame
- if(m_Master)
- Schedule(frame->payload, PayloadSize);
-
- // Need some bandwidth limit for ex. sequence of still frames when
- // moving cutting marks very fast (no audio or PTS available).
- // Hard limit for used bandwidth:
- // - ~1 frames/ms & 8kb/ms -> 8mb/s -> ~ 80 Mbit/s ( / client)
- // - max burst 15 frames or 32 kb
- m_BurstFrames ++;
- m_BurstBytes += PayloadSize;
- if (m_BurstFrames >= MAX_BURST_FRAMES && m_BurstBytes >= MAX_BURST_BYTES) {
- Scheduler_Sleep(4);
-#ifdef LOG_UDP_RATE
- static uint64_t dbg_timer = cTimeMs::Now();
- static int dbg_bytes = 0;
- dbg_bytes += bytes;
- if (dbg_timer + 60000 <= cTimeMs::Now()) {
- LOGDBG("UDP rate: %4d Kbps (queue %d)", dbg_bytes/(60*1024/8), m_QueuePending);
- dbg_bytes = 0;
- dbg_timer = cTimeMs::Now();
- }
-#endif
- }
-
- /* tag frame with ssrc and timestamp */
- frame->rtp_hdr.ts = htonl((uint32_t)(m_RtpScr.Now() & 0xffffffff));
- frame->rtp_hdr.ssrc = htonl(m_ssrc);
-
- /* deliver to all active sockets */
- for(int i=0; i<MAX_UDP_HANDLES && m_Handles[i]>=0; i++) {
-
- //
- // use TIOCOUTQ ioctl instead of poll/select.
- // - poll/select for UDP/RTP may return true even when queue
- // is (almost) full
- // - kernel silently drops frames it cant send
- // -> poll() + send() just causes frames to be dropped
- //
- uint size = 0;
- if(!ioctl(m_Handles[i], TIOCOUTQ, &size)) {
- if(size >= (m_wmem[i] - 2*RtpPacketLen)) {
- LOGMSG("cUdpScheduler: kernel transmit queue > ~%dkb (max %dkb) ! (master=%d)",
- (m_wmem[i] - 2*RtpPacketLen)/1024, m_wmem[i]/1024, m_Master);
- Scheduler_Sleep(2);
- }
- } else {
- if(m_QueuePending > (MAX_QUEUE_SIZE-5))
- LOGDBG("cUdpScheduler: kernel transmit queue > ~30kb ! (master=%d ; Queue=%d)",
- m_Master, m_QueuePending);
- Scheduler_Sleep(2);
- }
-
- if(m_Handles[i] == m_fd_rtp.handle()) {
- if(send(m_Handles[i], frame, RtpPacketLen, 0) <= 0)
- LOGERR("cUdpScheduler: UDP/RTP send() failed !");
- } else {
- /* UDP: send without rtp header */
- if (send(m_Handles[i], RTP_UDP_PAYLOAD(frame), UdpPacketLen, 0) <= 0)
- LOGERR("cUdpScheduler: UDP send() failed !");
- }
- }
-
- m_BackLogDeleteMutex.Unlock(); /* release queue */
- m_Lock.Lock();
-
- m_Frames ++;
- m_Octets += PayloadSize;
- if(m_fd_rtcp.open() && (m_Frames & 0xff) == 1) { // every 256th frame
- Send_RTCP();
-#if 0
- if((m_Frames & 0xff00) == 0) // every 65536th frame (~ 2 min)
- Send_SAP();
-#else
- if((m_Frames & 0x0300) == 0) // every 1024th frame (~ 2...4 sec)
- Send_SAP();
-#endif
- }
- }
-
- m_Lock.Unlock();
-}
-
-void cUdpScheduler::ReSend(int fd, uint64_t Pos, int Seq1, int Seq2)
-{
- if(fd < 0) /* no re-send for RTP */
- return;
-
- struct {
- stream_udp_header_t hdr;
- char payload[64-sizeof(stream_udp_header_t)];
- } udp_ctrl = {{(uint64_t)INT64_C(-1), (uint16_t)-1}, {0}};
-
- // Handle buffer wrap
- if(Seq1 > Seq2)
- Seq2 += UDP_BUFFER_SIZE;
-
- cMutexLock ml(&m_Lock); // keeps also scheduler thread suspended ...
-
- if(Seq2-Seq1 > 64) {
- LOGDBG("cUdpScheduler::ReSend: requested range too large (%d-%d)", Seq1, Seq2);
- snprintf(udp_ctrl.payload, sizeof(udp_ctrl.payload),
- "UDP MISSING %d-%d %" PRIu64,
- Seq1, (Seq2 & UDP_BUFFER_MASK), Pos);
- send(fd, &udp_ctrl, sizeof(udp_ctrl), 0);
- return;
- }
-
- // re-send whole range
- for(; Seq1 <= Seq2; Seq1++) {
-
- // Wait if kernel queue is full
- int size = 0;
- if(!ioctl(fd, TIOCOUTQ, &size))
- if(size > ((0x10000)/2 - 2048)) { // assume 64k kernel buffer
- LOGDBG("cUdpScheduler::ReSend: kernel transmit queue > ~30kb !");
- Scheduler_Sleep(2);
- }
-
- stream_rtp_header_impl_t *frame = m_BackLog->Get(Seq1);
-
- if(frame) {
- if(ntohull(frame->hdr_ext.pos) - Pos < 100000) {
- send(fd,
- RTP_UDP_PAYLOAD(frame),
- m_BackLog->PayloadSize(Seq1) + sizeof(stream_udp_header_t),
- 0);
- LOGRESEND("cUdpScheduler::ReSend: %d (%d bytes) @%lld sent",
- Seq1, m_BackLog->PayloadSize(Seq1), Pos);
- Pos = ntohull(frame->hdr_ext.pos) + m_BackLog->PayloadSize(Seq1);
- continue;
- } else {
- // buffer has been lost long time ago...
- LOGRESEND("cUdpScheduler::ReSend: Requested position does not match "
- "(%lld ; has %lld)", Pos, ntohll(frame->hdr_ext.pos));
- }
- } else {
- LOGRESEND("cUdpScheduler::ReSend: %d @%lld missing", Seq1, Pos);
- }
-
- // buffer has been lost - send packet missing info
-
- LOGRESEND("cUdpScheduler::ReSend: missing %d-%d @%d (hdr 0x%llx 0x%x)",
- Seq1, Seq1, Pos, udp_ctrl.hdr.pos, udp_ctrl.hdr.seq);
-
- int Seq0 = Seq1;
- for(; Seq1 < Seq2; Seq1++) {
- stream_rtp_header_impl_t *frame = m_BackLog->Get(Seq1+1);
- if(frame && (ntohull(frame->hdr_ext.pos) - Pos < 100000))
- break;
- }
-
- snprintf(udp_ctrl.payload, sizeof(udp_ctrl.payload),
- "UDP MISSING %d-%d %" PRIu64,
- Seq0, (Seq1 & UDP_BUFFER_MASK), Pos);
-
- send(fd, &udp_ctrl, sizeof(udp_ctrl), 0);
- }
-}
diff --git a/tools/udp_pes_scheduler.h b/tools/udp_pes_scheduler.h
deleted file mode 100644
index 99f1861b..00000000
--- a/tools/udp_pes_scheduler.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * udp_pes_scheduler.h: PES scheduler for UDP/RTP streams
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: udp_pes_scheduler.h,v 1.22 2009-08-19 11:32:21 phintuka Exp $
- *
- */
-
-#ifndef __UDP_PES_SCHEDULER_H
-#define __UDP_PES_SCHEDULER_H
-
-#include <stdint.h>
-
-#include <vdr/tools.h> // uchar
-#include <vdr/thread.h>
-
-#include "cxsocket.h"
-#include "time_pts.h"
-
-#define MAX_UDP_HANDLES 16
-
-class cUdpBackLog;
-
-class cUdpScheduler : public cThread
-{
- public:
-
- cUdpScheduler();
- virtual ~cUdpScheduler();
-
- // fd should be binded & connected to IP:PORT (local+remote) pair !
- bool AddHandle(int fd); /* UDP unicast */
- void RemoveHandle(int fd); /* UDP unicast */
- bool AddRtp(void); /* UDP/RTP multicast */
- void RemoveRtp(void); /* UDP/RTP multicast */
- bool AddHandle(cxSocket& s) { return AddHandle(s.handle()); }
- void RemoveHandle(cxSocket& s) { RemoveHandle(s.handle()); }
-
- bool Clients(void) { return m_Handles[0] >= 0; }
- int Poll(int TimeoutMs, bool Master);
- bool Queue(uint64_t StreamPos, const uchar *Data, int Length);
- void QueuePadding(void);
- void ReSend(int fd, uint64_t Pos, int Seq1, int Seq2);
-
- void Clear(void);
- bool Flush(int TimeoutMs);
-
- void Pause(bool On);
- void TrickSpeed(const int Multiplier);
- void SetScrSpeed(const int Speed = 90000);
-
- protected:
-
- // Signalling
-
- cCondVar m_Cond;
- cMutex m_Lock;
-
- // Clients
-
- int m_Handles[MAX_UDP_HANDLES];
- uint m_wmem[MAX_UDP_HANDLES]; /* kernel buffer size */
-
- cxSocket m_fd_rtp;
- cxSocket m_fd_rtcp;
-
- // Queue
-
- uint m_QueueNextSeq; /* next outgoing */
- uint m_QueuePending; /* outgoing queue size */
- cUdpBackLog *m_BackLog; /* queue for incoming data (not yet send) and retransmissions */
- cMutex m_BackLogDeleteMutex;
-
- // Scheduling
-
- typedef enum {
- /* from worst to best */
- eScrDetect = 0,
- eScrFromVideo = 1,
- eScrFromPS1 = 2,
- eScrFromAudio = 3,
- eScrFromPcr = 4,
- } ScrSource_t;
-
- cTimePts m_MasterClock; /* Current MPEG PTS (synchronized to current stream) */
- bool m_TrickSpeed; /* current (replay) speed */
- bool m_Master; /* if true, we are master metronom for playback */
-
- ScrSource_t m_ScrSource;
- int64_t m_CurrentAudioVtime;
- int64_t m_CurrentVideoVtime;
- int64_t m_CurrentPcr;
-
- uint m_BurstBytes; /* number of bytes sent without sleeps */
- uint m_BurstFrames; /* number of frames sent without sleeps */
-
- cCondWait m_CondWait;
-
- int CalcElapsedVtime(int64_t pts, ScrSource_t ScrSource);
- void Schedule(const uchar *Data, int Length);
- void Scheduler_Sleep(int ms);
- void QueuePaddingInternal(void);
-
- // RTP
-
- uint32_t m_ssrc; /* RTP synchronization source id */
- cTimePts m_RtpScr; /* 90 kHz monotonic time source for RTP timestamps */
-
- // RTCP
-
- uint64_t m_LastRtcpTime;
- uint32_t m_Frames;
- uint32_t m_Octets;
-
- void Send_RTCP(void);
-
- // SAP
-
- int m_fd_sap;
-
- void Send_SAP(bool Announce = true);
-
- // Thread
-
- virtual void Action(void);
-};
-
-#endif
diff --git a/tools/vdrdiscovery.c b/tools/vdrdiscovery.c
deleted file mode 100644
index e301056d..00000000
--- a/tools/vdrdiscovery.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * vdrdiscovery.c
- *
- * Simple broadcast protocol to search VDR with xineliboutput server
- * from (local) network.
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: vdrdiscovery.c,v 1.9 2009-06-29 21:23:33 phintuka Exp $
- *
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <poll.h>
-#include <unistd.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <arpa/inet.h>
-
-#define LOG_MODULENAME "[discovery] "
-#include "../logdefs.h"
-
-#include "vdrdiscovery.h"
-
-/*
- * constants
- */
-
-#ifndef DISCOVERY_PORT
-# define DISCOVERY_PORT 37890
-#endif
-
-/* discovery protocol strings (v1.0) */
-#define DISCOVERY_1_0_HDR "VDR xineliboutput DISCOVERY 1.0" "\r\n"
-#define DISCOVERY_1_0_CLI "Client: %s:%d" "\r\n"
-#define DISCOVERY_1_0_SVR "Server port: %d" "\r\n"
-#define DISCOVERY_1_0_ADDR "Server address: %s" "\r\n"
-#define DISCOVERY_1_0_VERSION "Server version: " /*vdr-" VDRVERSION "\r\n\t"*/ \
- "xineliboutput-" XINELIBOUTPUT_VERSION "\r\n"
-
-/*
- *
- */
-
-static inline int discovery_init(int port)
-{
- int fd_discovery = -1;
- int iBroadcast = 1, iReuse = 1;
- struct sockaddr_in sin;
-
- if ((fd_discovery = socket(PF_INET, SOCK_DGRAM, 0/*IPPROTO_TCP*/)) < 0) {
- LOGERR("discovery_init: socket() failed");
- return -1;
- }
-
- if (setsockopt(fd_discovery, SOL_SOCKET, SO_BROADCAST, &iBroadcast, sizeof(int)) < 0)
- LOGERR("discovery_init: setsockopt(SO_BROADCAST) failed");
-
- if (setsockopt(fd_discovery, SOL_SOCKET, SO_REUSEADDR, &iReuse, sizeof(int)) < 0)
- LOGERR("discovery_init: setsockopt(SO_REUSEADDR) failed");
-
- sin.sin_family = AF_INET;
- sin.sin_port = htons(port);
- sin.sin_addr.s_addr = htonl(INADDR_BROADCAST);
-
- if (bind(fd_discovery, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
- LOGERR("discovery_init: bind() failed");
- close(fd_discovery);
- return -1;
- }
-
- return fd_discovery;
-}
-
-int udp_discovery_init(void)
-{
- return discovery_init(DISCOVERY_PORT);
-}
-
-static inline int udp_discovery_send(int fd_discovery, int port, char *msg)
-{
- struct sockaddr_in sin;
- int len = strlen(msg);
-
- sin.sin_family = AF_INET;
- sin.sin_port = htons(port);
- sin.sin_addr.s_addr = INADDR_BROADCAST;
-
- if(len != sendto(fd_discovery, msg, len, 0,
- (struct sockaddr *)&sin, sizeof(sin))) {
- LOGERR("UDP broadcast send failed (discovery)");
- return -1;
- }
-
- //LOGDBG("UDP broadcast send succeed (discovery)");
- return 0;
-}
-
-int udp_discovery_broadcast(int fd_discovery, int server_port, const char *server_address)
-{
- char *msg = NULL;
- int result;
-
- if(server_address && *server_address) {
- result = asprintf(&msg,
- DISCOVERY_1_0_HDR //"VDR xineliboutput DISCOVERY 1.0" "\r\n"
- DISCOVERY_1_0_SVR //"Server port: %d" "\r\n"
- DISCOVERY_1_0_ADDR //"Server Address: %d.%d.%d.%d \r\n"
- DISCOVERY_1_0_VERSION //"Server version: xineliboutput-" XINELIBOUTPUT_VERSION "\r\n"
- "\r\n",
- server_port, server_address);
- } else {
- result = asprintf(&msg,
- DISCOVERY_1_0_HDR //"VDR xineliboutput DISCOVERY 1.0" "\r\n"
- DISCOVERY_1_0_SVR //"Server port: %d" "\r\n"
- DISCOVERY_1_0_VERSION //"Server version: xineliboutput-" XINELIBOUTPUT_VERSION "\r\n"
- "\r\n",
- server_port);
- }
-
- if (result >= 0) {
- result = udp_discovery_send(fd_discovery, DISCOVERY_PORT, msg);
- free(msg);
- }
-
- return result;
-}
-
-static inline int udp_discovery_search(int fd_discovery, int port)
-{
- char *msg = NULL;
- int result;
-
- result = asprintf(&msg,
- DISCOVERY_1_0_HDR /* "VDR xineliboutput DISCOVERY 1.0" "\r\n" */
- DISCOVERY_1_0_CLI /* "Client: %s:%d" "\r\n" */
- "\r\n",
- "255.255.255.255",
- port);
-
- if (result >= 0) {
- result = udp_discovery_send(fd_discovery, port, msg);
- free(msg);
- }
-
- return result;
-}
-
-int udp_discovery_recv(int fd_discovery, char *buf, int timeout,
- struct sockaddr_in *source)
-{
- socklen_t sourcelen = sizeof(struct sockaddr_in);
- struct pollfd pfd;
- int err;
-
- pfd.fd = fd_discovery;
- pfd.events = POLLIN;
-
- errno = 0;
- err = poll(&pfd, 1, timeout);
- if(err < 1) {
- if(err < 0)
- LOGERR("broadcast poll error");
- return err;
- }
-
- memset(source, 0, sourcelen);
- memset(buf, 0, DISCOVERY_MSG_MAXSIZE);
-
- err = recvfrom(fd_discovery, buf, DISCOVERY_MSG_MAXSIZE-1, 0,
- (struct sockaddr *)source, &sourcelen);
-
- if(err <= 0)
- LOGDBG("fd_discovery recvfrom() error");
-
- return err;
-}
-
-int udp_discovery_is_valid_search(const char *buf)
-{
- static const char id_string[] = { DISCOVERY_1_0_HDR "Client:" };
-
- if(!strncmp(id_string, buf, strlen(id_string))) {
- LOGMSG("Received valid discovery message %s", buf);
- return 1;
- }
-
- LOGDBG("BROADCAST: %s", buf);
- return 0;
-}
-
-int udp_discovery_find_server(int *port, char *address)
-{
- static const char mystring[] = DISCOVERY_1_0_HDR "Server port: ";
- struct sockaddr_in from;
- char buf[DISCOVERY_MSG_MAXSIZE];
- int fd_discovery = -1;
- int trycount = 0;
- int err = 0;
-
- *port = DISCOVERY_PORT;
- strcpy(address, "vdr");
-
- if((fd_discovery = discovery_init(DISCOVERY_PORT)) < 0)
- return 0;
-
- while(err >= 0 && ++trycount < 4) {
-
- if((err = udp_discovery_search(fd_discovery, DISCOVERY_PORT) >= 0)) {
-
- errno = 0;
- while( (err = udp_discovery_recv(fd_discovery, buf, 500, &from)) > 0) {
-
- uint32_t tmp = ntohl(from.sin_addr.s_addr);
-
- buf[err] = 0;
- LOGDBG("Reveived broadcast: %d bytes from %d.%d.%d.%d \n%s",
- err,
- ((tmp>>24)&0xff), ((tmp>>16)&0xff),
- ((tmp>>8)&0xff), ((tmp)&0xff),
- buf);
- if(!strncmp(mystring, buf, strlen(mystring))) {
- char *iploc;
- LOGDBG("Valid discovery message");
- close(fd_discovery);
-
- // default: use broadcast source address
- sprintf(address, "%d.%d.%d.%d",
- ((tmp>>24)&0xff), ((tmp>>16)&0xff),
- ((tmp>>8)&0xff), ((tmp)&0xff));
-
- // Check if announce message includes alternative server address
- iploc = strstr(buf + strlen(mystring), "Server address: ");
- if(iploc) {
- uint32_t svraddr;
- iploc += strlen("Server address: ");
- svraddr = inet_addr(iploc);
- if(svraddr == INADDR_NONE) {
- LOGMSG("Server provided invalid address !");
- } else {
- svraddr = ntohl(svraddr);
- sprintf(address, "%d.%d.%d.%d",
- ((svraddr>>24)&0xff), ((svraddr>>16)&0xff),
- ((svraddr>>8)&0xff), ((svraddr)&0xff));
- LOGMSG("Replacing broadcast source address %d.%d.%d.%d "
- "with server-given address %s",
- ((tmp>>24)&0xff), ((tmp>>16)&0xff),
- ((tmp>>8)&0xff), ((tmp)&0xff),
- address);
- }
- }
-
- *port = -1;
- if(1 == sscanf(buf + strlen(mystring), "%d", port) &&
- *port >= 1000 && *port <= 0xffff)
- return 1;
- LOGMSG("Server-given port is invalid !");
- } else {
- LOGDBG("NOT valid discovery message");
- }
- }
- }
- }
-
- /* failed */
- close(fd_discovery);
- return 0;
-}
-
-
diff --git a/tools/vdrdiscovery.h b/tools/vdrdiscovery.h
deleted file mode 100644
index de612733..00000000
--- a/tools/vdrdiscovery.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * vdrdiscovery.h
- *
- * Simple broadcast protocol to search VDR with xineliboutput server
- * from (local) network.
- *
- * See the main source file 'xineliboutput.c' for copyright information and
- * how to reach the author.
- *
- * $Id: vdrdiscovery.h,v 1.5 2009-02-10 15:26:11 phintuka Exp $
- *
- */
-
-#ifndef _VDRDISCOVERY_H_
-#define _VDRDISCOVERY_H_
-
-#define DISCOVERY_MSG_MAXSIZE 1024
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct sockaddr_in;
-
-/*
- * Client interface
- */
-
-/*
- * udp_discovery_find_server()
- *
- * Search for server. Return address and port.
- * Returns 0 on success.
- */
-int udp_discovery_find_server(int *port, char *address);
-
-/*
- * Server interface
- */
-
-/*
- * udp_discovery_init()
- *
- * Initialize server socket. Return value is the socket file descriptor,
- * and can be used for polling.
- * Returns < 0 on error.
- */
-int udp_discovery_init(void);
-
-/*
- * udp_discovery_broadcast()
- *
- * Send server announcement.
- * Returns 0 on success.
- */
-int udp_discovery_broadcast(int fd_discovery, int server_port, const char *server_address);
-
-/*
- * udp_discovery_recv()
- *
- * Receive query or announcement.
- * Returns number of bytes received, <= 0 on error.
- * Result is null-terminated string, not more than DISCOVERY_MSG_MAXSIZE bytes.
- */
-int udp_discovery_recv(int fd_discovery, char *buf, int timeout,
- struct sockaddr_in *source);
-
-/*
- * udp_discovery_is_valid_search()
- *
- * Check if string is valid search message.
- * Returns 1 for valid messages, 0 for invalid messages.
- */
-int udp_discovery_is_valid_search(const char *buf);
-
-#ifdef __cplusplus
-};
-#endif
-
-
-#endif // _VDRDISCOVERY_H_