diff --git a/mythtv/libs/libmythbase/mythbaseutil.h b/mythtv/libs/libmythbase/mythbaseutil.h
index 2d74c02..6d9914c 100644
--- a/mythtv/libs/libmythbase/mythbaseutil.h
+++ b/mythtv/libs/libmythbase/mythbaseutil.h
@@ -49,5 +49,24 @@ static inline void setup_pipe(int mypipe[2], long myflags[2])
     }
 }
 #endif
+static inline uint ELFHash(const QByteArray &ba)
+{
+    const uchar *k = (const uchar *)ba.data();
+    uint h = 0;
+    uint g;
+
+    if (k)
+    {
+        while (*k)
+        {
+            h = (h << 4) + *k++;
+            if ((g = (h & 0xf0000000)) != 0)
+                h ^= g >> 24;
+            h &= ~g;
+        }
+    }
+
+    return h;
+}
 
 #endif // _MYTH_DB_UTIL_H_
diff --git a/mythtv/libs/libmythtv/eitfixup.cpp b/mythtv/libs/libmythtv/eitfixup.cpp
index d61e72c..3a5b2fc 100644
--- a/mythtv/libs/libmythtv/eitfixup.cpp
+++ b/mythtv/libs/libmythtv/eitfixup.cpp
@@ -1,6 +1,9 @@
 // C++ headers
 #include <algorithm>
 
+// Qt headers
+#include <QCoreApplication>
+
 // MythTV headers
 #include "eitfixup.h"
 #include "dvbdescriptors.h" // for MythCategoryType
@@ -9,6 +12,10 @@
 #include "programinfo.h" // for subtitle types and audio and video properties
 #include "dishdescriptors.h" // for dish_theme_type_to_string
 
+#include "mythlogging.h"
+#include <unistd.h>
+#include "mythbaseutil.h"
+
 /*------------------------------------------------------------------------
  * Event Fix Up Scripts - Turned on by entry in dtv_privatetype table
  *------------------------------------------------------------------------*/
@@ -122,7 +129,9 @@ EITFixUp::EITFixUp()
                         "NRK2s historiekveld|Detektimen|Nattkino|Filmklassiker|Film|Kortfilm|P.skemorg[eo]n|"
                         "Radioteatret|Opera|P2-Akademiet|Nyhetsmorg[eo]n i P2 og Alltid Nyheter:): (.+)"),
       m_noPremiere("\\s+-\\s+(Sesongpremiere|Premiere|premiere)!?$"),
-      m_Stereo("\\b\\(?[sS]tereo\\)?\\b")
+      m_Stereo("\\b\\(?[sS]tereo\\)?\\b"),
+      m_boxerYear("[0-9]{4}"),
+      m_boxerCountryCode("[A-Z]{3}")
 
 {
 }
@@ -180,6 +189,16 @@ void EITFixUp::Fix(DBEventEIT &event) const
     if (kFixNO & event.fixup)
         FixNO(event);
 
+    if (kFixBoxer & event.fixup)
+        FixBoxer(event);
+
+    if (kFixBoxerDescCo & event.fixup)
+        FixBoxerDescriptionCompact(event);
+
+    //this one needs to be after kFixBoxerDescCo
+    if (kFixBoxerDesc & event.fixup)
+        FixBoxerDescription(event);
+
     if (kFixNRK_DVBT & event.fixup)
         FixNRK_DVBT(event);
 
@@ -1767,3 +1786,296 @@ void EITFixUp::FixNRK_DVBT(DBEventEIT &event) const
     }
 }
 
+/** \fn EITFixUp::FixBoxer(DBEventEIT&) const
+ *  \brief Use this to clean DVB-T guide in Sweden
+ */
+void EITFixUp::FixBoxer(DBEventEIT &event) const
+{
+	if (event.subtitle.length() > 0)
+	{
+		event.description = event.subtitle + event.description;
+		event.subtitle = "";
+	}
+
+	int position = event.title.indexOf("(HD)");
+	if (position != -1)
+	{
+		event.title = event.title.replace("(HD)", "").trimmed();
+		event.videoProps |= VID_HDTV;
+	}
+	
+	QStringList strListDesc=event.description.split(".");
+	for(int i=0;i<strListDesc.count();i++)
+	{
+		if(strListDesc[i].contains("HD"))
+		{
+			event.videoProps |= VID_HDTV;
+		}
+		if(strListDesc[i].contains("Textat sid"))
+		{
+			event.subtitleType |= SUB_NORMAL;
+		}
+		if(strListDesc[i].contains(QString::fromUtf8("Sänds med 5.1 ljud")))
+		{
+			event.audioProps |= AUD_DOLBY;
+		}
+	}
+	
+	//create seriesId and programId just like mythfilldatabase does with xmltv data
+	//this works well because we have good data about season and episodes thanks to the crex boxer infotag descriptor
+	CreateProgramID(event);
+}
+/** \fn EITFixUp::FixBoxerDescriptionCompact(DBEventEIT&) const
+ * \brief Extract compact form of category, country, year and possibly subtitle from the description
+ */
+void EITFixUp::FixBoxerDescriptionCompact(DBEventEIT &event) const
+{
+	enum descPart
+	{
+		category,
+		country,
+		year
+	};
+
+	//needed because it is mostly series that have a subtitle
+	//this will also reduce the possibility of a picking bad subtitle
+	bool isSeries = (event.syndicatedepisodenumber.contains("E") && event.syndicatedepisodenumber.contains("S"));
+	
+	//format of the "compact subtitle" at the beginning of the description is
+	//a comma separated list have the following fields in this order:
+	//zero or more categories
+	//one or more 3 character country codes that always is in upper case
+	//exactly one 4 digit year
+	//optionally a subtitle
+	
+	QStringList strListCategories;
+	//most likely production country
+	QStringList strListCountries;
+	uint16_t airdate=0;
+	QString subtitle="";
+
+	descPart state=category;
+	QStringList strListDescParts=event.description.split(",");
+	//character position in description, used to know where to cut the description when we are done
+	int pos=0;
+	for(int i=0;i<strListDescParts.count();i++)
+	{
+		pos++;
+		pos+=strListDescParts[i].length();
+		if(strListDescParts[i].trimmed().isEmpty())
+		{
+			continue;
+		}
+
+		//country code and year is easy to detect
+		if(strListDescParts[i].trimmed().indexOf(m_boxerCountryCode)==0)
+		{
+			strListCountries.append(strListDescParts[i].trimmed());
+			state=country;
+		}
+		else if(strListDescParts[i].trimmed().indexOf(m_boxerYear)==0)
+		{
+			airdate=strListDescParts[i].trimmed().toUShort();
+			state=year;
+		}
+		else
+		{
+			if(state==category)
+			{
+				//this part must be a category
+				strListCategories.append(strListDescParts[i].trimmed());
+				LOG(VB_EIT, LOG_DEBUG, QString("EITFixUp::FixBoxerDescriptionCompact Category: '%1'").arg(strListDescParts[i].trimmed()));
+			}
+			else if(state==year)
+			{
+				//the only thing after the year is the optional subtitle
+				//and there is nothing more to do after this
+				//make sure subtitle is 55 characters or less to avoid
+				//accidentally picking the first sentence of the description
+				if(isSeries && strListDescParts[i].trimmed().length()<=55)
+				{
+					subtitle=strListDescParts[i].trimmed();
+				}
+				else
+				{
+					//if we didn't pick up any subtitle at this point we need to move back pos
+					//so we don't remove this part of the description
+					pos--;
+					pos-=strListDescParts[i].length();
+				}
+				break;
+			}
+		}
+	}
+	
+	if(!event.description.isEmpty())
+	{
+		event.description.remove(0,pos+1);
+	}
+	if(!subtitle.isEmpty())
+	{
+		event.subtitle=subtitle;
+	}
+	if(airdate>0 && event.airdate==0)
+	{
+		event.airdate=airdate;
+	}
+
+	//build the category string
+	QString newCategory="";
+	if(strListCategories.count()>0 && event.category.isEmpty())
+	{
+		for(int i=0;i<strListCategories.count();i++)
+		{
+			QString tmp=strListCategories[i].trimmed();
+			if(!tmp.isEmpty())
+			{
+				if(i!=0)
+				{
+					newCategory+="/";
+				}
+				newCategory+=tmp;
+			}
+			
+		}
+		event.category=newCategory;
+	}
+}
+
+/** \fn EITFixUp::FixBoxerDescription(DBEventEIT&) const
+ * \brief Extract country, category, and year from the description
+ */
+void EITFixUp::FixBoxerDescription(DBEventEIT &event) const
+{
+	//this function is not as reliable as FixBoxerDescriptionCompact but instead works on most channels
+	//idealy this code should only run on all channels except those already handled by FixBoxerDescriptionCompact
+	//but since that is not easily doable it will only update fields if they are missing and this one should be run last
+
+	//borrow regex from swedish dvb-c comhem fixup, it is exatly what is needed
+	QRegExp tmpCountry = m_comHemCountry;
+	int pos = tmpCountry.indexIn(event.description);
+	if (pos != -1)
+	{
+		QStringList list = tmpCountry.capturedTexts();
+		QString replacement;
+
+		// Original title, usually english title
+		// note: list[1] contains extra () around the text that needs removing
+		if (list[1].length() > 0)
+		{
+			replacement = list[1] + " ";
+			//store it somewhere?
+		}
+
+		// Countr(y|ies)
+		if (list[2].length() > 0)
+		{
+			replacement += list[2] + " ";
+			//store it somewhere?
+		}
+
+		// Category
+		if (list[3].length() > 0)
+		{
+			replacement += list[3] + ".";
+			if(event.category.isEmpty())
+			{
+				event.category = list[3];
+				if(list[3].indexOf("serie")!=-1)
+				{
+					event.categoryType = kCategorySeries;
+				}
+			}
+			LOG(VB_EIT, LOG_DEBUG, QString("EITFixUp::FixBoxerDescription Category: '%1'").arg(list[3]));
+		}
+
+		// Year
+		if (list[4].length() > 0 && event.airdate==0)
+		{
+			bool ok;
+			uint y = list[4].trimmed().toUInt(&ok);
+			if (ok)
+				event.airdate = y;
+		}
+
+		// Remove year and actors.
+		// The reason category is left in the description is because otherwise
+		// the country would look wierd like "Amerikansk. Rest of description."
+		event.description = event.description.replace(list[0],replacement);
+	}
+}
+
+void EITFixUp::CreateProgramID(DBEventEIT &event) const
+{
+	QString season;
+	QString episode;
+	if(!event.syndicatedepisodenumber.isEmpty())
+	{
+		QRegExp epnum("E([0-9]+)S([0-9]+)");
+		if(epnum.indexIn(event.syndicatedepisodenumber)!=-1)
+		{
+			episode=epnum.cap(1);
+			season=epnum.cap(2);
+		}
+	}
+	CreateProgramID(event,season,episode);
+}
+
+/** \fn EITFixUp::CreateProgramID(DBEventEIT&, QString season, QString episode) const
+ *  \brief Create seriesId and programId in the same way mythfilldatabase does.
+ */
+void EITFixUp::CreateProgramID(DBEventEIT &event, QString season, QString episode) const
+{
+	QString seriesid=QString::number(ELFHash(event.title.toUtf8()));
+	event.seriesId=seriesid;
+	
+	QString programid;
+	if(event.categoryType==kCategoryMovie)
+	{
+		programid="MV";
+	}
+	else if(event.categoryType==kCategorySeries)
+	{
+		programid="EP";
+	}
+	else if(event.categoryType==kCategorySports)
+	{
+		programid="SP";
+	}
+	else
+	{
+		programid="SH";
+	}
+	programid.append(seriesid);
+	if(!episode.isEmpty() && !season.isEmpty())
+	{
+		int season_int=season.toInt();
+		if(season_int > 35)
+		{
+			if(event.categoryType!=kCategoryMovie)
+			{
+				programid.clear();
+			}
+		}
+		else
+		{
+			programid.append(episode);
+			programid.append(QString::number(season_int, 36));
+			if(event.partnumber && event.parttotal)
+			{
+				programid+=QString::number(event.partnumber);
+				programid+=QString::number(event.parttotal);
+			}
+		}
+	}
+	else
+	{
+		if(event.categoryType!=kCategoryMovie)
+		{
+			programid.clear();
+		}
+	}
+	//the function AddDVBEITAuthority() converts this string to lower case :-(
+	//perhaps it doesn't matter
+	event.programId=programid;
+}
\ No newline at end of file
diff --git a/mythtv/libs/libmythtv/eitfixup.h b/mythtv/libs/libmythtv/eitfixup.h
index 3a9b6ef..f3ab90e 100644
--- a/mythtv/libs/libmythtv/eitfixup.h
+++ b/mythtv/libs/libmythtv/eitfixup.h
@@ -51,6 +51,9 @@ class EITFixUp
         kFixNO         = 0x10000,
         kFixNRK_DVBT   = 0x20000,
         kFixDish       = 0x40000,
+        kFixBoxer      = 0x80000,
+        kFixBoxerDescCo = 0x100000,
+        kFixBoxerDesc   = 0x200000,
 
         // Early fixups
         kEFixForceISO8859_1  = 0x2000,
@@ -90,6 +93,12 @@ class EITFixUp
     void FixCategory(DBEventEIT &event) const;      // Generic Category fixes
     void FixNO(DBEventEIT &event) const;            // Norwegian DVB-S
     void FixNRK_DVBT(DBEventEIT &event) const;      // Norwegian NRK DVB-T
+    void FixBoxer(DBEventEIT &event) const;         // Swedish DVB-T
+    void FixBoxerDescriptionCompact(DBEventEIT &event) const;
+    void FixBoxerDescription(DBEventEIT &event) const;
+    QString TranslateBoxerCategory(QString) const;
+    void CreateProgramID(DBEventEIT &event) const;
+    void CreateProgramID(DBEventEIT &event, QString season, QString episode) const;
 
     static QString AddDVBEITAuthority(uint chanid, const QString &id);
 
@@ -195,6 +204,8 @@ class EITFixUp
     const QRegExp m_noNRKCategories;
     const QRegExp m_noPremiere;
     const QRegExp m_Stereo;
+    const QRegExp m_boxerYear;
+    const QRegExp m_boxerCountryCode;
 };
 
 #endif // EITFIXUP_H
diff --git a/mythtv/libs/libmythtv/eithelper.cpp b/mythtv/libs/libmythtv/eithelper.cpp
index 289062e..f139673 100644
--- a/mythtv/libs/libmythtv/eithelper.cpp
+++ b/mythtv/libs/libmythtv/eithelper.cpp
@@ -3,6 +3,9 @@
 // Std C headers
 #include <time.h>
 
+// Qt headers
+#include <QCoreApplication>
+
 // Std C++ headers
 #include <algorithm>
 using namespace std;
@@ -17,6 +20,7 @@ using namespace std;
 #include "premieretables.h"
 #include "dishdescriptors.h"
 #include "premieredescriptors.h"
+#include "boxerinfotagdescriptors.h"
 #include "mythdate.h"
 #include "programdata.h"
 #include "programinfo.h" // for subtitle types and audio and video properties
@@ -488,6 +492,64 @@ void EITHelper::AddEIT(const DVBEventInformationTable *eit)
             video_props, stars,
             seriesId,  programId);
 
+		const unsigned char *boxer_crex_infotag_desc=MPEGDescriptor::Find(list,PrivateDescriptorID::boxer_crex_infotag);
+		if(boxer_crex_infotag_desc)
+		{
+			BoxerCrexInfoTagDescriptor cbi(boxer_crex_infotag_desc);
+			cbi.Dump();
+			LOG(VB_EIT, LOG_DEBUG, LOC + QString("BoxerCrexInfoTag EIT: SeriesID: %1 Episode: %2 EpisodeTotal: %3 Season: %4 ProductionYear: %5")
+				.arg(QString::number(cbi.SeriesID()),QString::number(cbi.Episode()),QString::number(cbi.EpisodeTotal()),QString::number(cbi.Season()),QString::number(cbi.ProductionYear())));
+			LOG(VB_EIT, LOG_DEBUG, LOC + QString("BoxerCrexInfoTag EIT: Director: %1 ProdCountry: %2 SpokenLang: %3")
+				.arg(cbi.Director(),cbi.ProdCountry(),cbi.SpokenLang()));
+
+			//unfortunately the data contained in SeriesID is of too bad quality to be of use for mythtv
+			//same series have multiple different seriesid and even the same episode have different values :(
+			//according to spec the seriesid is only guaranteed  to be unique within the same service
+			/*if(cbi.SeriesID()>0)
+			{
+				event->seriesId=QString::number(cbi.SeriesID());
+			}*/
+			if(cbi.Episode()>0)
+			{
+				QString episodenum;
+				if(cbi.Season()>0)
+				{
+					episodenum=QString("E%1S%2").arg(QString::number(cbi.Episode()),QString::number(cbi.Season()));
+					
+					event->categoryType=kCategorySeries;
+					//category cannot be Movie if this is a series, so category is clearly wrong
+					//this is a common error in the guide data
+					if(event->category==QCoreApplication::translate("(Categories)", "Movie"))
+					{
+						event->category="";
+					}
+				}
+				else
+				{
+					episodenum=QString("E%1").arg(QString::number(cbi.Episode()));
+				}
+				event->syndicatedepisodenumber=episodenum;
+			}
+			//multipart program?
+			if(cbi.Season()==0 && cbi.Episode()>0 && cbi.EpisodeTotal()>0)
+			{
+				event->partnumber=cbi.Episode();
+				event->parttotal=cbi.EpisodeTotal();
+			}
+
+			event->previouslyshown=cbi.IsRerun();
+			//there no place to put cbi.IsLiveBroadcast() flag
+			event->airdate=cbi.ProductionYear();
+			if(!cbi.Director().isEmpty())
+			{
+				QStringList directors=cbi.Director().split(",");
+				for(int i=0;i<directors.count();i++)
+				{
+					event->AddPerson(DBPerson::kDirector,directors[i]);
+				}
+			}
+		}
+
         db_events.enqueue(event);
     }
 }
@@ -830,6 +892,16 @@ static void init_fixup(QMap<uint64_t,uint> &fix)
     fix[40999U << 16 | 1068] = EITFixUp::kFixSubtitle;
     fix[40999U << 16 | 1069] = EITFixUp::kFixSubtitle;
 
+	// Boxer Sweden (DVB-T)
+	fix[ 8945U << 16 ] = EITFixUp::kFixBoxer|EITFixUp::kFixBoxerDesc;
+	fix[ 8945U << 16 |  910] = EITFixUp::kFixBoxerDescCo;	//C More First
+	fix[ 8945U << 16 |  970] = EITFixUp::kFixBoxerDescCo;	//C More Hits
+	fix[ 8945U << 16 |  900] = EITFixUp::kFixBoxerDescCo;	//C More Sport/SF-Kanalen
+	fix[ 8945U << 16 | 3460] = EITFixUp::kFixBoxerDescCo;	//C More Live HD/First HD
+	//too many false positives on the subtitle (mainly kid programs)
+	//fix[ 8945U << 16 | 3340] = EITFixUp::kFixBoxerDescCo;	//C More Fotboll/Hockey/Kids
+	fix[ 8945U << 16 | 3280] = EITFixUp::kFixBoxerDescCo;	//C More Series
+
     // Australia
     fix[ 4096U << 16] = EITFixUp::kFixAUStar;
     fix[ 4096U << 16] = EITFixUp::kFixAUStar;
diff --git a/mythtv/libs/libmythtv/libmythtv.pro b/mythtv/libs/libmythtv/libmythtv.pro
index c815431..d462fc7 100644
--- a/mythtv/libs/libmythtv/libmythtv.pro
+++ b/mythtv/libs/libmythtv/libmythtv.pro
@@ -183,6 +183,7 @@ HEADERS += mpeg/freesat_huffman.h   mpeg/freesat_tables.h
 HEADERS += mpeg/iso6937tables.h
 HEADERS += mpeg/tsstats.h           mpeg/streamlisteners.h
 HEADERS += mpeg/H264Parser.h
+HEADERS += mpeg/boxerinfotagdescriptors.h
 
 SOURCES += mpeg/tspacket.cpp        mpeg/pespacket.cpp
 SOURCES += mpeg/mpegtables.cpp      mpeg/atsctables.cpp
@@ -198,6 +199,7 @@ SOURCES += mpeg/atsc_huffman.cpp
 SOURCES += mpeg/freesat_huffman.cpp
 SOURCES += mpeg/iso6937tables.cpp
 SOURCES += mpeg/H264Parser.cpp
+SOURCES += mpeg/boxerinfotagdescriptors.cpp
 
 # Channels, and the multiplexes that transmit them
 HEADERS += frequencies.h            frequencytables.h
diff --git a/mythtv/libs/libmythtv/mpeg/boxerinfotagdescriptors.cpp b/mythtv/libs/libmythtv/mpeg/boxerinfotagdescriptors.cpp
new file mode 100644
index 0000000..60ccc5e
--- /dev/null
+++ b/mythtv/libs/libmythtv/mpeg/boxerinfotagdescriptors.cpp
@@ -0,0 +1,96 @@
+#include "boxerinfotagdescriptors.h"
+#include "dvbdescriptors.h"
+#include "mythlogging.h"
+
+bool BoxerCrexInfoTagDescriptor::Parse(void)
+{
+	if(DescriptorLength() < 3)
+	{
+		return false;
+	}
+	
+	//encoding override for dvb_decode_text
+	//spec says strings are encoded according to character table 5 (latin/turkish) from DVB/ETSI EN 300 468 annex A
+	unsigned char enc[] = {0x05};
+	uint enc_len=1;
+
+	unsigned char *dataptr=const_cast<unsigned char *>(_data);
+	dataptr+=2;
+	
+	uint8_t cbi_type=dataptr[0];
+	dataptr+=1;
+	//Basic info
+	if(cbi_type==0x01)
+	{
+		_seriesid=        ((uint32_t)dataptr[0]  << 24) | ((uint32_t)dataptr[1] << 16) | ((uint32_t)dataptr[2] << 8) | dataptr[3];
+		dataptr+=4;
+		_episode=         ((uint16_t)dataptr[0]  << 8) | dataptr[1];
+		dataptr+=2;
+		_episode_total=   ((uint16_t)dataptr[0]  << 8) | dataptr[1];
+		dataptr+=2;
+		_season=          ((uint16_t)dataptr[0]  << 8) | dataptr[1];
+		dataptr+=2;
+		_status=          dataptr[0];
+		dataptr+=1;
+		_production_year= ((uint16_t)dataptr[0]  << 8) | dataptr[1];
+		dataptr+=2;
+
+		if(dataptr<(_data+DescriptorLength()))
+		{
+			uint8_t prod_country_length=dataptr[0];
+			dataptr+=1;
+			//LOG(VB_EIT, LOG_DEBUG, QString("BoxerCrexInfoTagDescriptor::Parse: prod_country_length=%1").arg(QString::number(prod_country_length)));
+			if(prod_country_length>0)
+			{
+				_prod_country=dvb_decode_text(dataptr,prod_country_length,enc,enc_len);
+			}
+			dataptr+=prod_country_length;
+		}
+
+		if(dataptr<(_data+DescriptorLength()))
+		{
+			uint8_t spoken_lang_length=dataptr[0];
+			dataptr+=1;
+			//LOG(VB_EIT, LOG_DEBUG, QString("BoxerCrexInfoTagDescriptor::Parse: spoken_lang_length=%1").arg(QString::number(spoken_lang_length)));
+			if(spoken_lang_length>0)
+			{
+				_spoken_lang=dvb_decode_text(dataptr,spoken_lang_length,enc,enc_len);
+			}
+			dataptr+=spoken_lang_length;
+		}
+
+		if(dataptr<(_data+DescriptorLength()))
+		{
+			uint8_t director_length=dataptr[0];
+			dataptr+=1;
+			//LOG(VB_EIT, LOG_DEBUG, QString("BoxerCrexInfoTagDescriptor::Parse: director_length=%1").arg(QString::number(director_length)));
+			if(director_length>0)
+			{
+				_director=dvb_decode_text(dataptr,director_length,enc,enc_len);
+			}
+			dataptr+=director_length;
+		}
+
+		return true;
+	}
+	//Credits
+	/*else if(cbi_type==0x02)
+	{
+		//not implemented since it is not transmitted (yet?)
+	}
+	//Keywords
+	else if(cbi_type==0x03)
+	{
+		//not implemented since it is not transmitted (yet?)
+	}*/
+	return false;
+}
+void BoxerCrexInfoTagDescriptor::Dump()
+{
+	QString data;
+	for(uint8_t i=0;i<_data[1];i++)
+	{
+		data+=QString(" %1").arg(_data[i],0,16);
+	}
+	LOG(VB_EIT, LOG_DEBUG, QString("BoxerCrexInfoTagDescriptor: Dump:%1").arg(data));
+}
\ No newline at end of file
diff --git a/mythtv/libs/libmythtv/mpeg/boxerinfotagdescriptors.h b/mythtv/libs/libmythtv/mpeg/boxerinfotagdescriptors.h
new file mode 100644
index 0000000..8041d48
--- /dev/null
+++ b/mythtv/libs/libmythtv/mpeg/boxerinfotagdescriptors.h
@@ -0,0 +1,92 @@
+#ifndef _BOXERINFOTAG_DESCRIPTORS_H_
+#define _BOXERINFOTAG_DESCRIPTORS_H_
+
+#include <stdint.h>
+#include <inttypes.h>
+
+// C++ headers
+#include <vector>
+using namespace std;
+
+// Qt headers
+#include <QString>
+#include <QDateTime>
+
+// MythTV headers
+#include "mpegdescriptors.h"
+
+class BoxerCrexInfoTagDescriptor : public MPEGDescriptor
+{
+public:
+	BoxerCrexInfoTagDescriptor(const unsigned char *data, int len = 300)
+		: MPEGDescriptor(data, len, PrivateDescriptorID::boxer_crex_infotag),
+		_seriesid(0),_episode(0),_episode_total(0),_season(0),_status(0),_production_year(0),
+		_prod_country(""),_spoken_lang(""),_director("")
+	{
+		if (_data && !Parse())
+			_data = NULL;
+	}
+	uint32_t SeriesID()
+	{
+		return _seriesid;
+	}
+	uint16_t Episode()
+	{
+		return _episode;
+	}
+	uint16_t EpisodeTotal()
+	{
+		return _episode_total;
+	}
+	uint16_t Season()
+	{
+		return _season;
+	}
+	
+	//status
+	bool IsLiveBroadcast()
+	{
+		return _status & 0x01;
+	}
+	bool IsRerun()
+	{
+		return _status & 0x02;
+	}
+
+	uint16_t ProductionYear()
+	{
+		return _production_year;
+	}
+	
+	QString Director()
+	{
+		return _director;
+	}
+	QString ProdCountry()
+	{
+		return _prod_country;
+	}
+	QString SpokenLang()
+	{
+		return _spoken_lang;
+	}
+
+	//debugging
+	void Dump();
+
+private:
+	virtual bool Parse(void);
+	
+	uint32_t _seriesid;
+	uint16_t _episode;
+	uint16_t _episode_total;
+	uint16_t _season;
+	uint8_t _status;
+	uint16_t _production_year;
+	
+	QString _prod_country;
+	QString _spoken_lang;
+	QString _director;
+
+};
+#endif // _BOXERINFOTAG_DESCRIPTORS_H_
diff --git a/mythtv/libs/libmythtv/mpeg/mpegdescriptors.cpp b/mythtv/libs/libmythtv/mpeg/mpegdescriptors.cpp
index 87c2c96..95735a9 100644
--- a/mythtv/libs/libmythtv/mpeg/mpegdescriptors.cpp
+++ b/mythtv/libs/libmythtv/mpeg/mpegdescriptors.cpp
@@ -365,6 +365,9 @@ QString MPEGDescriptor::DescriptorTagString(void) const
         case PrivateDescriptorID::premiere_content_transmission: /* 0xF2 */
             comma_list_append(str, "Possibly Premiere DE Content Transmission");
             break;
+        case PrivateDescriptorID::boxer_crex_infotag: /* 0xBC */
+            comma_list_append(str, "Possibly Boxer Crex infotag");
+            break;
     }
 
     if (str.isEmpty())
diff --git a/mythtv/libs/libmythtv/mpeg/mpegdescriptors.h b/mythtv/libs/libmythtv/mpeg/mpegdescriptors.h
index 0e7a448..d355175 100644
--- a/mythtv/libs/libmythtv/mpeg/mpegdescriptors.h
+++ b/mythtv/libs/libmythtv/mpeg/mpegdescriptors.h
@@ -194,6 +194,9 @@ class PrivateDescriptorID
         premiere_content_order        = 0xF0,
         premiere_parental_information = 0xF1,
         premiere_content_transmission = 0xF2,
+
+        // Private -- Boxer
+        boxer_crex_infotag = 0xBC,
     };
 };
 
diff --git a/mythtv/programs/mythfilldatabase/xmltvparser.cpp b/mythtv/programs/mythfilldatabase/xmltvparser.cpp
index b3f4456..fdf6445 100644
--- a/mythtv/programs/mythfilldatabase/xmltvparser.cpp
+++ b/mythtv/programs/mythfilldatabase/xmltvparser.cpp
@@ -11,6 +11,10 @@
 #include <iostream>
 #include <cstdlib>
 
+// libmythbase headers
+#include <unistd.h>
+#include "mythbaseutil.h"
+
 // libmyth headers
 #include "exitcodes.h"
 #include "mythcorecontext.h"
@@ -30,26 +34,6 @@ XMLTVParser::XMLTVParser() : isJapan(false), current_year(0)
     current_year = MythDate::current().date().toString("yyyy").toUInt();
 }
 
-static uint ELFHash(const QByteArray &ba)
-{
-    const uchar *k = (const uchar *)ba.data();
-    uint h = 0;
-    uint g;
-
-    if (k)
-    {
-        while (*k)
-        {
-            h = (h << 4) + *k++;
-            if ((g = (h & 0xf0000000)) != 0)
-                h ^= g >> 24;
-            h &= ~g;
-        }
-    }
-
-    return h;
-}
-
 static QString getFirstText(QDomElement element)
 {
     for (QDomNode dname = element.firstChild(); !dname.isNull();
