Index: iptv/iptvfeederhttp.cpp
===================================================================
--- iptv/iptvfeederhttp.cpp	(revision 0)
+++ iptv/iptvfeederhttp.cpp	(revision 0)
@@ -0,0 +1,202 @@
+/** -*- Mode: c++ -*-
+ *  IPTVFeederHTTP
+ *  Copyright (c) 2008 by Karl Dietz
+ *  Copyright (c) 2006 by Mike Mironov & Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+#include <algorithm>
+
+#include "iptvfeederhttp.h"
+
+// Qt headers
+#include <QUrl>
+
+// Live555 headers
+#include <BasicUsageEnvironment.hh>
+#include <MP3HTTPSource.hh>
+#include <MPEG2TransportStreamFromESSource.hh>
+
+// MythTV headers
+#include "iptvmediasink.h"
+#include "libmyth/mythcontext.h"
+#include "libmythdb/mythverbose.h"
+#include "tspacket.h"
+
+#define LOC QString("IPTVFeedHTTP: ")
+#define LOC_ERR QString("IPTVFeedHTTP, Error: ")
+
+IPTVFeederHTTP::IPTVFeederHTTP() :
+    _source(NULL),
+    _multiplexor(NULL),
+    _sink(NULL)
+{
+    VERBOSE(VB_RECORD, LOC + "ctor -- success");
+}
+
+IPTVFeederHTTP::~IPTVFeederHTTP()
+{
+    VERBOSE(VB_RECORD, LOC + "dtor -- begin");
+    Close();
+    VERBOSE(VB_RECORD, LOC + "dtor -- end");
+}
+
+bool IPTVFeederHTTP::IsHTTP(const QString &url)
+{
+    return url.startsWith("http://", Qt::CaseInsensitive);
+}
+
+bool IPTVFeederHTTP::Open(const QString &url)
+{
+    VERBOSE(VB_RECORD, LOC + QString("Open(%1) -- begin").arg(url));
+
+    QMutexLocker locker(&_lock);
+
+    if (_source)
+    {
+        VERBOSE(VB_RECORD, LOC + "Open() -- end 1");
+        return true;
+    }
+
+    QUrl parse(url);
+    if (!parse.isValid() || parse.host().isEmpty() || (-1 == parse.port()))
+    {
+        VERBOSE(VB_RECORD, LOC + "Open() -- end 2");
+        return false;
+    }
+
+	/* FIXME resolve target */
+    QByteArray host = parse.host().toLatin1();
+    struct in_addr addr;
+    addr.s_addr = our_inet_addr(host.constData());
+    NetAddress _target_address (addr.s_addr);
+
+    // Begin by setting up our usage environment:
+    if (!InitEnv())
+        return false;
+
+	_source = MP3HTTPSource::createNew(*_live_env, addr, parse.port(80), parse.encodedHost().constData(), parse.encodedPath().constData());
+    if (!_source)
+    {
+        VERBOSE(VB_IMPORTANT, LOC + "Failed to create Live MP3 HTTP Source.");
+
+        if (socket)
+            delete socket;
+
+        FreeEnv();
+        return false;
+    }
+
+	_multiplexor = MPEG2TransportStreamFromESSource::createNew(__live_env);
+    if (!_multiplexor)
+    {
+        VERBOSE(VB_IMPORTANT, LOC + "Failed to create MPEG 2 Transport Stream From ES Source Filter.");
+
+        FreeEnv();
+        return false;
+    }
+    /* attach MPEG2 Audio Layer 1-3 ES to TS */
+    _multiplexor -> addNewAudioSource (_source, 2);
+
+	/* TODO a buffer worth about 5 seconds at 40mbit/s, why? We just take 300kbit/s here,
+	 * as we deal mostly with radio streams of at most 256bkit/s for the audiostream
+	 */
+    _sink = IPTVMediaSink::CreateNew(*_live_env, TSPacket::SIZE * 1*1024);
+    if (!_sink)
+    {
+        VERBOSE(VB_IMPORTANT,
+                QString("IPTV # Failed to create sink: %1")
+                .arg(_live_env->getResultMsg()));
+
+        Medium::close(_multiplexor);
+        _multiplexor = NULL;
+        Medium::close(_source);
+        _source = NULL;
+        FreeEnv();
+
+        return false;
+    }
+
+    _sink->startPlaying(*_source, NULL, NULL);
+    vector<TSDataListener*>::iterator it = _listeners.begin();
+    for (; it != _listeners.end(); ++it)
+        _sink->AddListener(*it);
+
+    VERBOSE(VB_RECORD, LOC + "Open() -- end");
+
+    return true;
+}
+
+void IPTVFeederHTTP::Close(void)
+{
+    VERBOSE(VB_RECORD, LOC + "Close() -- begin");
+    Stop();
+
+    QMutexLocker locker(&_lock);
+
+    if (_sink)
+    {
+        Medium::close(_sink);
+        _sink = NULL;
+    }
+
+    if (_multiplexor)
+    {
+        Medium::close(_multiplexor);
+        _multiplexor = NULL;
+    }
+
+    if (_source)
+    {
+        Medium::close(_source);
+        _source = NULL;
+    }
+
+    FreeEnv();
+
+    VERBOSE(VB_RECORD, LOC + "Close() -- end");
+}
+
+void IPTVFeederHTTP::AddListener(TSDataListener *item)
+{
+    VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- begin");
+    if (!item)
+    {
+        VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end");
+        return;
+    }
+
+    // avoid duplicates
+    RemoveListener(item);
+
+    // add to local list
+    QMutexLocker locker(&_lock);
+    _listeners.push_back(item);
+
+    if (_sink)
+        _sink->AddListener(item);
+
+    VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end");
+}
+
+void IPTVFeederHTTP::RemoveListener(TSDataListener *item)
+{
+    VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- begin");
+    QMutexLocker locker(&_lock);
+    vector<TSDataListener*>::iterator it =
+        find(_listeners.begin(), _listeners.end(), item);
+
+    if (it == _listeners.end())
+    {
+        VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end 1");
+        return;
+    }
+
+    // remove from local list..
+    *it = *_listeners.rbegin();
+    _listeners.resize(_listeners.size() - 1);
+
+    if (_sink)
+        _sink->RemoveListener(item);
+
+    VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end 2");
+}
Index: iptv/iptvfeederhttp.h
===================================================================
--- iptv/iptvfeederhttp.h	(revision 0)
+++ iptv/iptvfeederhttp.h	(revision 0)
@@ -0,0 +1,73 @@
+/** -*- Mode: c++ -*-
+ *  IPTVFeederHTTP -- basic feeder for elementary streams over HTTP (aka internet radio)
+ *
+ *  It generates a valid DVB-IPTV SPTS with optional SI (only the minimum
+ *  SI as required by TS 101 154 is provided) from the received elementary
+ *  stream. (not yet)
+ *
+ *  Copyright (c) 2008 by Karl Dietz
+ *  Copyright (c) 2006 by Mike Mironov & Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#ifndef _IPTV_FEEDER_HTTP_H_
+#define _IPTV_FEEDER_HTTP_H_
+
+// MythTV headers
+#include "iptvfeederlive.h"
+
+class MP3HTTPSource;
+class MPEG2TransportStreamFromESSource;
+class IPTVMediaSink;
+
+
+class IPTVFeederHTTP : public IPTVFeederLive
+{
+  public:
+    IPTVFeederHTTP();
+    virtual ~IPTVFeederHTTP();
+
+    bool CanHandle(const QString &url) const { return IsHTTP(url); }
+    bool IsOpen(void) const { return _source; }
+
+    bool Open(const QString &url);
+    void Close(void);
+
+    void AddListener(TSDataListener*);
+    void RemoveListener(TSDataListener*);
+
+    static bool IsHTTP(const QString &url);
+
+  private:
+    MP3HTTPSource *_source;
+    MPEG2TransportStreamFromESSource *_multiplexor;
+    IPTVMediaSink  *_sink;
+
+    int _ICY_MetadataInt;
+
+    /* DVB Triplet for fake DVB-SI */
+
+    /** original network id, private range 0xFF00 - 0xFFFE, 255 ids starting at 0xff00 */
+    int _onid;
+    /**
+     * network id, private range 0xFF01 - 0xFFFF, 255 ids starting at 0xff01
+     *
+     * Notice the offset, according to EN 300 468 these should be the
+     * same in case the NIT is transmitted on the origin network.
+     * At the DVB registry the nid is not a superset of the onid!
+     *
+     * In our case onid and nid should be equal.
+     */
+    int _nid;
+    /** transport id, choose as you see fit
+     *
+     * Best would be to use one tid per source location. e.g. use the CRC16 of the stream URL.
+     *
+     */
+    int _tid;
+    /** service id, choose as you see fit */
+    int _sid;
+
+};
+
+#endif // _IPTV_FEEDER_HTTP_H_
Index: iptv/iptvfeederwrapper.cpp
===================================================================
--- iptv/iptvfeederwrapper.cpp	(revision 19138)
+++ iptv/iptvfeederwrapper.cpp	(working copy)
@@ -16,6 +16,7 @@
 #include "iptvfeederudp.h"
 #include "iptvfeederrtp.h"
 #include "iptvfeederfile.h"
+#include "iptvfeederhttp.h"
 #include "libmyth/mythcontext.h"
 #include "libmythdb/mythverbose.h"
 
@@ -70,6 +71,10 @@
     {
         tmp_feeder = new IPTVFeederFile();
     }
+    else if (IPTVFeederHTTP::IsHTTP(url))
+    {
+        tmp_feeder = new IPTVFeederHTTP();
+    }
     else
     {
         VERBOSE(VB_RECORD, LOC_ERR +
Index: iptv/README.HTTP
===================================================================
--- iptv/README.HTTP	(revision 0)
+++ iptv/README.HTTP	(revision 0)
@@ -0,0 +1,16 @@
+Source to capture MP3 Elementary streams from HTTP sources (aka Internet Radio Streams)
+Point the playlist to the final stream, not some playlist as these won't get resolved.
+
+========= Example playlist.m3u ==========
+= created from http://web.ard.de/radio/radionet/liste.php?ressort=alle
+= find them also on http://www.lyngsat.com/astra1h.html
+= NID 1
+= TID 1093
+= SID 28475 (1LIVE), 28402 (Bayern 3), 28432 (MDR JUMP)
+#EXTM3U
+#EXTINF:0,1 - 1LIVE
+http://gffstream.ic.llnwd.net/stream/gffstream_stream_wdr_einslive_a
+#EXTINF:0,2 - Bayern 3
+http://gffstream.ic.llnwd.net/stream/gffstream_w12a
+#EXTINF:0,3 - MDR JUMP
+http://c22033-l.i.core.cdn.streamfarm.net/22004mdrjump/live/3087mdr_jump/live_de_128.mp3
Index: libmythtv.pro
===================================================================
--- libmythtv.pro	(revision 18991)
+++ libmythtv.pro	(working copy)
@@ -442,6 +442,7 @@
         HEADERS += iptv/iptvfeederrtsp.h      iptv/iptvfeederudp.h
         HEADERS += iptv/iptvfeederfile.h      iptv/iptvfeederlive.h
         HEADERS += iptv/iptvfeederrtp.h       iptv/timeoutedtaskscheduler.h
+        HEADERS += iptv/iptvfeederhttp.h
 
         SOURCES += iptvchannel.cpp            iptvrecorder.cpp
         SOURCES += iptvsignalmonitor.cpp
@@ -451,6 +452,7 @@
         SOURCES += iptv/iptvfeederrtsp.cpp    iptv/iptvfeederudp.cpp
         SOURCES += iptv/iptvfeederfile.cpp    iptv/iptvfeederlive.cpp
         SOURCES += iptv/iptvfeederrtp.cpp     iptv/timeoutedtaskscheduler.cpp
+        SOURCES += iptv/iptvfeederhttp.cpp
 
         DEFINES += USING_IPTV
     }
