[mythtv-users] backend takes 100% CPU recording DVB-T

Stephen Williams stephen.gw at gmail.com
Wed Apr 19 12:47:07 UTC 2006


It looks like ticket #1694 is related. This ticket (unfortunately
closed) proposed the backporting of a number of EIT efficiency fixes
to the 0.19-fixes branch with the aim of reducing CPU usage.

I've put together a unified patch for the fixes mentioned in that
ticket (attached below). I'm not in a position to try this out myself
for a day or two but if anybody feels like giving it a whirl then I
think we'd all be interested to know if this has any beneficial
effect.

Stephen

>>>>>

Index: /trunk/mythtv/libs/libmythtv/mpeg/dvbdescriptors.cpp
===================================================================
--- /trunk/mythtv/libs/libmythtv/mpeg/dvbdescriptors.cpp (revision 9157)
+++ /trunk/mythtv/libs/libmythtv/mpeg/dvbdescriptors.cpp (revision 9220)
@@ -5,64 +5,86 @@
 #include <qdeepcopy.h>

+// Only some of the QTextCodec calls are reenterant.
+// If you use this please verify that you are using a reenterant call.
+static const QTextCodec *iso8859_codecs[16] =
+{
+    QTextCodec::codecForName("Latin1"),
+    QTextCodec::codecForName("ISO8859-1"),  // Western
+    QTextCodec::codecForName("ISO8859-2"),  // Central European
+    QTextCodec::codecForName("ISO8859-3"),  // Central European
+    QTextCodec::codecForName("ISO8859-4"),  // Baltic
+    QTextCodec::codecForName("ISO8859-5"),  // Cyrillic
+    QTextCodec::codecForName("ISO8859-6"),  // Arabic
+    QTextCodec::codecForName("ISO8859-7"),  // Greek
+    QTextCodec::codecForName("ISO8859-8"),  // Hebrew, visually ordered
+    QTextCodec::codecForName("ISO8859-9"),  // Turkish
+    QTextCodec::codecForName("ISO8859-10"),
+    QTextCodec::codecForName("ISO8859-11"),
+    QTextCodec::codecForName("ISO8859-12"),
+    QTextCodec::codecForName("ISO8859-13"),
+    QTextCodec::codecForName("ISO8859-14"),
+    QTextCodec::codecForName("ISO8859-15"), // Western
+};
+
 // Decode a text string according to ETSI EN 300 468 Annex A
-QString dvb_decode_text(const unsigned char *src, uint length)
-{
-    QString result;
-
+QString dvb_decode_text(const unsigned char *src, uint raw_length)
+{
+    if (!raw_length)
+        return "";
+
+    if ((0x10 < src[0]) && (src[0] < 0x20))
+    {
+        // TODO: Handle multi-byte encodings
+        VERBOSE(VB_SIPARSER, "dvb_decode_text: "
+                "Multi-byte coded text is not yet supported.");
+        return "";
+    }
+
+    // Strip formatting characters
+    char dst[raw_length];
+    uint length = 0;
+    for (uint i = 0; i < raw_length; i++)
+    {
+        if ((src[i] < 0x80) || (src[i] > 0x9F))
+        {
+            dst[length] = src[i];
+            length++;
+        }
+    }
+    const char *buf = dst;
+
+    // Exit on empty string, sans formatting.
     if (!length)
-        return QString("");
-
-    unsigned char buf[length];
-    memcpy(buf, src, length);
-
-    if ((buf[0] <= 0x10) || (buf[0] >= 0x20))
-    {
-        // Strip formatting characters
-        for (uint p = 0; p < length; p++)
-        {
-            if ((buf[p] >= 0x80) && (buf[p] <= 0x9F))
-                memmove(buf + p, buf + p + 1, --length - p);
-        }
-
-        if (buf[0] >= 0x20)
-        {
-            result = QString::fromLatin1((const char*)buf, length);
-        }
-        else if ((buf[0] >= 0x01) && (buf[0] <= 0x0B))
-        {
-            QString coding = "ISO8859-" + QString::number(4 + buf[0]);
-            QTextCodec *codec = QTextCodec::codecForName(coding);
-            result = codec->toUnicode((const char*)buf + 1, length - 1);
-        }
-        else if (buf[0] == 0x10)
-        {
-            // If the first byte of the text field has a value "0x10"
-            // then the following two bytes carry a 16-bit value (uimsbf) N
-            // to indicate that the remaining data of the text field is
-            // coded using the character code table specified by
-            // ISO Standard 8859, parts 1 to 9
-
-            uint code = 1;
-            swab(buf + 1, &code, 2);
-            QString coding = "ISO8859-" + QString::number(code);
-            QTextCodec *codec = QTextCodec::codecForName(coding);
-            result = codec->toUnicode((const char*)buf + 3, length - 3);
-        }
+        return "";
+
+    // Decode using the correct text codec
+    if (buf[0] >= 0x20)
+    {
+        return QString::fromLatin1(buf, length);
+    }
+    else if ((buf[0] >= 0x01) && (buf[0] <= 0x0B))
+    {
+        return iso8859_codecs[4 + buf[0]]->toUnicode(buf + 1, length - 1);
+    }
+    else if (buf[0] == 0x10)
+    {
+        // If the first byte of the text field has a value "0x10"
+        // then the following two bytes carry a 16-bit value (uimsbf) N
+        // to indicate that the remaining data of the text field is
+        // coded using the character code table specified by
+        // ISO Standard 8859, parts 1 to 9
+
+        uint code = 1;
+        swab(buf + 1, &code, 2);
+        if (code <= 15)
+            return iso8859_codecs[code]->toUnicode(buf + 3, length - 3);
         else
-        {
-            // Unknown/invalid encoding - assume local8Bit
-            result = QString::fromLocal8Bit((const char*)buf + 1, length - 1);
-        }
+            return QString::fromLocal8Bit(buf + 3, length - 3);
     }
     else
     {
-        // TODO: Handle multi-byte encodings
-
-        VERBOSE(VB_SIPARSER, "dvbdescriptors.cpp: "
-                "Multi-byte coded text - not supported!");
-        result = "N/A";
-    }
-
-    return result;
+        // Unknown/invalid encoding - assume local8Bit
+        return QString::fromLocal8Bit(buf + 1, length - 1);
+    }
 }
Index: trunk/mythtv/libs/libmythtv/mpeg/pespacket.cpp
===================================================================
--- trunk/mythtv/libs/libmythtv/mpeg/pespacket.cpp (revision 9203)
+++ trunk/mythtv/libs/libmythtv/mpeg/pespacket.cpp (revision 9337)
@@ -136,13 +146,14 @@
 static map<unsigned char*, bool> alloc4096;

-#define BLOCKS188 1000
+#define BLOCKS188 512
 static unsigned char* get_188_block()
 {
-    if (!free188.size())
+    if (free188.empty())
     {
         mem188.push_back((unsigned char*) malloc(188 * BLOCKS188));
         free188.reserve(BLOCKS188);
+        unsigned char* block_start = mem188.back();
         for (uint i = 0; i < BLOCKS188; ++i)
-            free188.push_back(i*188 + mem188.back());
+            free188.push_back(i*188 + block_start);
     }

@@ -162,7 +173,7 @@
 {
     alloc188.erase(ptr);
-    if (alloc188.size())
-        free188.push_back(ptr);
-    else
+    free188.push_back(ptr);
+    // free the allocator only if more than 1 block was used
+    if (alloc188.empty() && mem188.size() > 1)
     {
         vector<unsigned char*>::iterator it;
@@ -175,13 +186,14 @@
 }

-#define BLOCKS4096 256
+#define BLOCKS4096 128
 static unsigned char* get_4096_block()
 {
-    if (!free4096.size())
+    if (free4096.empty())
     {
         mem4096.push_back((unsigned char*) malloc(4096 * BLOCKS4096));
         free4096.reserve(BLOCKS4096);
+        unsigned char* block_start = mem4096.back();
         for (uint i = 0; i < BLOCKS4096; ++i)
-            free4096.push_back(i*4096 + mem4096.back());
+            free4096.push_back(i*4096 + block_start);
     }

@@ -201,7 +213,5 @@
 {
     alloc4096.erase(ptr);
-    if (alloc4096.size())
-    {
-        free4096.push_back(ptr);
+    free4096.push_back(ptr);

 #if 0 // enable this to debug memory leaks
@@ -221,6 +231,7 @@
         }
 #endif
-    }
-    else
+
+    // free the allocator only if more than 1 block was used
+    if (alloc4096.empty() && mem4096.size() > 1)
     {
         vector<unsigned char*>::iterator it;


More information about the mythtv-users mailing list