Aktuelles
Digital Eliteboard - Das Digitale Technik Forum

Registriere dich noch heute kostenlos, um Mitglied zu werden! Sobald du angemeldet bist, kannst du auf unserer Seite aktiv teilnehmen, indem du deine eigenen Themen und Beiträge erstellst und dich über deinen eigenen Posteingang mit anderen Mitgliedern unterhalten kannst! Zudem bekommst du Zutritt zu Bereichen, welche für Gäste verwehrt bleiben

Registriere dich noch heute kostenlos, um Mitglied zu werden! Sobald du angemeldet bist, kannst du auf unserer Seite aktiv teilnehmen, indem du deine eigenen Themen und Beiträge erstellst und dich über deinen eigenen Posteingang mit anderen Mitgliedern unterhalten kannst! Zudem bekommst du Zutritt zu Bereichen, welche für Gäste verwehrt bleiben

ICAM Patch oscam-emu

Status
Für weitere Antworten geschlossen.
hi,
hast du die cam gepatched - könntest du die für versuche bereitstellen?
danke vorab.

oder wie sehe die lösung deiner meinung nach aus?

mfg
adi22
 
Ich kann den Patch in seinem jetzigen Zustand mal hier einstellen. Ist allerdings weit entfernt von einem stable Release und enthält noch sehr viel überflüssigen Code / Kommentare aus Ideen und Tests. Werde da noch etwas weiter rumprobieren. Leider nimmt das manuelle Testen ziemlich viel Zeit in Anspruch.

Diff:
diff --git a/ffdecsa/ffdecsa.c b/ffdecsa/ffdecsa.c
index ca6d109..2ca01ff 100644
--- a/ffdecsa/ffdecsa.c
+++ b/ffdecsa/ffdecsa.c
@@ -63,8 +63,7 @@
 #define PARALLEL_MODE PARALLEL_128_SSE2
 
 #elif defined(__mips__) || defined(__mips) || defined(__MIPS__)
-//#define PARALLEL_MODE PARALLEL_64_LONG
-#define PARALLEL_MODE PARALLEL_32_INT
+#define PARALLEL_MODE PARALLEL_64_LONG
 
 #elif defined(__sh__) || defined(__SH4__)
 #define PARALLEL_MODE PARALLEL_32_INT
@@ -75,7 +74,7 @@
 #ifdef WITH_ARM_NEON
 #define PARALLEL_MODE PARALLEL_128_NEON
 #else
-#define PARALLEL_MODE PARALLEL_32_INT
+#define PARALLEL_MODE PARALLEL_64_LONG
 #endif
 
 #else
diff --git a/module-emulator-streamserver.c b/module-emulator-streamserver.c
index e32c244..3d72605 100644
--- a/module-emulator-streamserver.c
+++ b/module-emulator-streamserver.c
@@ -36,7 +36,7 @@ int32_t emu_stream_source_port = 8001;
 char *emu_stream_source_auth = NULL;
 int32_t emu_stream_relay_port = 17999;
 int8_t emu_stream_emm_enabled = 0;
-uint32_t cluster_size = 50;
+uint32_t cluster_size = 50, suggested_cluster_size;
 
 static uint8_t emu_stream_server_mutex_init = 0;
 static pthread_mutex_t emu_stream_server_mutex;
@@ -47,6 +47,10 @@ uint16_t emu_stream_cur_srvid[EMU_STREAM_SERVER_MAX_CONNECTIONS];
 int8_t stream_server_has_ecm[EMU_STREAM_SERVER_MAX_CONNECTIONS];
 
 pthread_mutex_t emu_fixed_key_data_mutex[EMU_STREAM_SERVER_MAX_CONNECTIONS];
+pthread_mutex_t emu_send_buffer_mutex[EMU_STREAM_SERVER_MAX_CONNECTIONS];
+uint8_t *send_buffer[EMU_STREAM_SERVER_MAX_CONNECTIONS];
+uint32_t send_buffer_length[EMU_STREAM_SERVER_MAX_CONNECTIONS] = {0};
+uint32_t send_buffer_offset[EMU_STREAM_SERVER_MAX_CONNECTIONS] = {0};
 emu_stream_client_key_data emu_fixed_key_data[EMU_STREAM_SERVER_MAX_CONNECTIONS];
 LLIST *ll_emu_stream_delayed_keys[EMU_STREAM_SERVER_MAX_CONNECTIONS];
 
@@ -1237,19 +1241,20 @@ static void DescrambleTsPacketsCompel(emu_stream_client_data *data, uint8_t *str
     }
 }
 
-static void DescrambleTsPacketsICam(emu_stream_client_data *data, uint8_t *stream_buf, uint32_t bufLength, uint16_t packetSize)
+static uint16_t DescrambleTsPacketsICam(emu_stream_client_data *data, uint8_t *stream_buf, uint32_t bufLength, uint16_t packetSize)
 {
-    uint8_t *packetCluster[4];
-    uint8_t scrambled_packets = 0, scramblingControl;
-    uint32_t i, tsHeader;
-    int8_t odd_even = -1, odd_even_count = 1;
+    uint8_t *packetCluster[3];
+    uint16_t retVal = 0; // return 0 if we could not descramble the packets
+
+#ifdef MODULE_RADEGAST
+    uint32_t i;
+    uint32_t tsHeader;
 
     for (i = 0; i < bufLength; i += packetSize)
     {
         tsHeader = b2i(4, stream_buf + i);
-        scramblingControl = (tsHeader & 0xC0) >> 6;
 
-#ifdef MODULE_RADEGAST
+
         uint16_t pid, offset, payloadStart;
 
         pid = (tsHeader & 0x1FFF00) >> 8;
@@ -1272,30 +1277,8 @@ static void DescrambleTsPacketsICam(emu_stream_client_data *data, uint8_t *strea
             ParseTsData(0x80, 0xFE, 3, &data->have_ecm_data, data->ecm_data, sizeof(data->ecm_data),
                         &data->ecm_data_pos, payloadStart, stream_buf + i + offset, packetSize - offset, ParseEcmData, data);
         }
-#endif // MODULE_RADEGAST
-
-        if (scramblingControl == 0)
-        {
-            continue;
-        }
-
-        scrambled_packets++;
-        scramblingControl &= 0x1;
-
-        if (odd_even == -1)
-        {
-            odd_even = scramblingControl;
-        }
-
-        if (odd_even != scramblingControl)
-        {
-            odd_even_count++;
-            odd_even = scramblingControl;
-        }
     }
-
-    if (scrambled_packets == 0)
-        return;
+#endif // MODULE_RADEGAST
 
     SAFE_MUTEX_LOCK(&emu_fixed_key_data_mutex[data->connid]);
 
@@ -1305,14 +1288,12 @@ static void DescrambleTsPacketsICam(emu_stream_client_data *data, uint8_t *strea
         packetCluster[1] = stream_buf + bufLength;
         packetCluster[2] = NULL;
 
-        decrypt_packets(emu_fixed_key_data[data->connid].icam_csa_ks, packetCluster);
-        if (odd_even_count > 1) // odd and even packets together cannot be decrypted in one step
-        {
-            decrypt_packets(emu_fixed_key_data[data->connid].icam_csa_ks, packetCluster);
-        }
+        retVal = decrypt_packets(emu_fixed_key_data[data->connid].icam_csa_ks, packetCluster);
     }
 
     SAFE_MUTEX_UNLOCK(&emu_fixed_key_data_mutex[data->connid]);
+
+    return retVal;
 }
 
 static int32_t connect_to_stream(char *http_buf, int32_t http_buf_len, char *stream_path)
@@ -1393,6 +1374,181 @@ static void stream_client_disconnect(emu_stream_client_conn_data *conndata)
     NULLFREE(conndata);
 }
 
+int64_t parse_pcr(const uint8_t *tsPacket) {
+    if (tsPacket[0] != 0x47) {
+        return INVALID_PCR;
+    }
+
+    if (!(tsPacket[3] & 0x20)) {
+        return INVALID_PCR;
+    }
+
+    if ((tsPacket[5] & 0x10)) {
+        uint16_t extension = 0;
+        uint64_t base = 0;
+
+        base |= (uint64_t)(tsPacket[6])<<25;
+        base |= (uint64_t)(tsPacket[7])<<(25-8);
+        base |= (uint64_t)(tsPacket[8])<<(25-8-8);
+        base |= (uint64_t)(tsPacket[9])<<(25-8-8-8);
+        base |= (uint16_t)(tsPacket[10] & 128)>>7;
+        extension |= tsPacket[11];
+        extension |= (uint16_t)(tsPacket[10] & 0x01)<<8;
+
+        return base*300 + extension;
+    }
+
+    return INVALID_PCR;
+}
+
+int64_t parse_pcr_unchecked(const uint8_t *tsPacket) {
+    uint16_t extension = 0;
+    uint64_t base = 0;
+
+    base |= (uint64_t)(tsPacket[6])<<25;
+    base |= (uint64_t)(tsPacket[7])<<(25-8);
+    base |= (uint64_t)(tsPacket[8])<<(25-8-8);
+    base |= (uint64_t)(tsPacket[9])<<(25-8-8-8);
+    base |= (uint16_t)(tsPacket[10] & 128)>>7;
+    extension |= tsPacket[11];
+    extension |= (uint16_t)(tsPacket[10] & 0x01)<<8;
+
+    return base*300 + extension;
+}
+
+int8_t has_pcr(const uint8_t *tsPacket) {
+    if (tsPacket[0] != 0x47) {
+        return 0;
+    }
+
+    if (!(tsPacket[3] & 0x20)) {
+        return 0;
+    }
+
+    return (tsPacket[5] & 0x10);
+}
+
+uint8_t is_scrambled(const uint8_t *tsPacket) {
+    return tsPacket[3] & 0x80;
+}
+
+uint8_t has_rai_flag(const uint8_t *tsPacket) {
+    if( ( tsPacket[3] & 0x20 ) && ( tsPacket[4] > 0 ) ) {
+        return tsPacket[5] & 0x40;
+    }
+    return 0;
+}
+
+uint16_t get_pid(const uint8_t *tsPacket) {
+    return ((tsPacket[1] & 0x1f) << 8) | tsPacket[2];
+}
+
+uint64_t find_first_pcr_value(const uint8_t *tsPackets, const uint32_t numPackets, const uint8_t packetSize) {
+    uint32_t packetNo;
+    uint64_t pcr = INVALID_PCR;
+    for (packetNo=0;packetNo<numPackets;packetNo++) {
+        pcr = parse_pcr(tsPackets+packetNo*packetSize);
+        if (pcr != INVALID_PCR) {
+            return pcr;
+        }
+    }
+    return INVALID_PCR;
+}
+
+uint8_t *find_next_pcr_packet(uint8_t *tsPackets, uint32_t tsPacketsLen, uint8_t packetSize) {
+    uint32_t packetNo;
+    for (packetNo=0;packetNo*packetSize<tsPacketsLen;packetNo++) {
+        if (has_pcr(tsPackets+packetNo*packetSize)) {
+            return tsPackets+packetNo*packetSize;
+        }
+    }
+    return NULL;
+}
+
+uint64_t find_last_pcr_value(const uint8_t *tsPackets, const uint32_t numPackets, const uint8_t packetSize) {
+    uint32_t packetNo;
+    uint64_t pcr = INVALID_PCR;
+    for (packetNo=numPackets;packetNo-->0;) {
+        pcr = parse_pcr(tsPackets+packetNo*packetSize);
+        if (pcr != INVALID_PCR) {
+            return pcr;
+        }
+    }
+    return INVALID_PCR;
+}
+
+uint64_t calc_pcr_timespan(const uint8_t *tsPackets, const uint32_t numPackets, const uint8_t packetSize) {
+    return find_last_pcr_value(tsPackets, numPackets, packetSize) - find_first_pcr_value(tsPackets, numPackets, packetSize);
+}
+
+uint8_t has_pusi_flag(const uint8_t *tsPacket) {
+    return tsPacket[1] & 0x40;
+}
+
+
+static void stream_client_sender(void *arg)
+{
+    uint8_t continue_sending = 1;
+    uint8_t packetSize = 188;
+    int32_t connid = ((emu_stream_client_conn_data *) arg)->connid;
+    int32_t connfd = ((emu_stream_client_conn_data *) arg)->connfd;
+
+    cs_log("Stream client %i sender started!", connid);
+    while (continue_sending) {
+        // wait until we have enough packets in send buffer
+        while (continue_sending) {
+            SAFE_MUTEX_LOCK(&emu_send_buffer_mutex[connid]);
+            uint8_t *currentPacket = NULL, *descrambled_rai_packet = NULL;
+            uint64_t pcrdiff = 0;
+            uint32_t packetNo = 0;
+            for (currentPacket = send_buffer[connid]+send_buffer_offset[connid]; currentPacket<(send_buffer[connid]+send_buffer_length[connid]);currentPacket+=packetSize) {
+                if (has_rai_flag(currentPacket) && !is_scrambled(currentPacket)) {
+                    descrambled_rai_packet = currentPacket;
+                    break;
+                }
+                packetNo++;
+            }
+
+            if (descrambled_rai_packet != NULL) {
+                pcrdiff = calc_pcr_timespan(descrambled_rai_packet, (send_buffer[connid]+send_buffer_length[connid]-descrambled_rai_packet) / packetSize, packetSize);
+            }
+            SAFE_MUTEX_UNLOCK(&emu_send_buffer_mutex[connid]);
+            if (pcrdiff > INITIAL_BUFFER_TIME_MS*(PCR_FREQ/1000)) {
+                // printf("we have enough packets in buffer\n");
+                break;
+            } else {
+                // printf("we have a descrambled rai packet\n");
+            }
+            cs_sleepms(5); // 35 ms is a typical timespan between two PCR packets
+        }
+        cs_log("Stream client %i buffer time reached!", connid);
+        SAFE_MUTEX_LOCK(&emu_send_buffer_mutex[connid]);
+        while (continue_sending) {
+            uint16_t packetsToSend = (send_buffer_length[connid]-send_buffer_offset[connid]) / packetSize;
+            if (packetsToSend > 80) {
+                // limit bitrate to ~30mbit/s
+                packetsToSend = 80;
+            }
+
+            ssize_t bytesSent = send(connfd, send_buffer[connid]+send_buffer_offset[connid], packetsToSend*packetSize, 0);
+            if (bytesSent == -1) {
+                cs_log_dbg(0, "Stream client %i could not send. Stopping sender!", connid);
+                continue_sending = 0;
+                break;
+            } else if (bytesSent != packetsToSend*188) {
+                cs_log("Stream client %i sent only %d bytes", connid, bytesSent);
+            }
+
+            send_buffer_offset[connid]+=packetsToSend*188;
+            SAFE_MUTEX_UNLOCK(&emu_send_buffer_mutex[connid]);
+            cs_sleepms(5);
+            SAFE_MUTEX_LOCK(&emu_send_buffer_mutex[connid]);
+        }
+        SAFE_MUTEX_UNLOCK(&emu_send_buffer_mutex[connid]);
+    }
+    cs_log("Stream client %i sender stopped!", connid);
+}
+
 static void *stream_client_handler(void *arg)
 {
     emu_stream_client_conn_data *conndata = (emu_stream_client_conn_data *)arg;
@@ -1410,6 +1566,15 @@ static void *stream_client_handler(void *arg)
     uint16_t packetCount = 0, packetSize = 0, startOffset = 0;
     uint32_t remainingDataPos, remainingDataLength, tmp_pids[4];
 
+    uint64_t last_pcr = INVALID_PCR;
+    uint16_t packets_since_last_pcr;
+
+    struct timeb now, postPublish = {.time = 0};
+
+    uint64_t recved_since_last_long_poll = 0;
+
+    pthread_t sender_thread;
+
     struct pollfd pfd[2];
     int ret;
 
@@ -1428,10 +1593,19 @@ static void *stream_client_handler(void *arg)
         return NULL;
     }
 
+    if (!cs_malloc(&send_buffer[conndata->connid], EMU_SEND_BUFFER_SIZE))
+    {
+        NULLFREE(http_buf);
+        NULLFREE(stream_buf);
+        stream_client_disconnect(conndata);
+        return NULL;
+    }
+
     if (!cs_malloc(&data, sizeof(emu_stream_client_data)))
     {
         NULLFREE(http_buf);
         NULLFREE(stream_buf);
+        NULLFREE(send_buffer[conndata->connid]);
         stream_client_disconnect(conndata);
         return NULL;
     }
@@ -1441,6 +1615,7 @@ static void *stream_client_handler(void *arg)
     {
         NULLFREE(http_buf);
         NULLFREE(stream_buf);
+        NULLFREE(send_buffer[conndata->connid]);
         NULLFREE(data);
         stream_client_disconnect(conndata);
         return NULL;
@@ -1451,6 +1626,7 @@ static void *stream_client_handler(void *arg)
     {
         NULLFREE(http_buf);
         NULLFREE(stream_buf);
+        NULLFREE(send_buffer[conndata->connid]);
         NULLFREE(data);
         stream_client_disconnect(conndata);
         return NULL;
@@ -1485,6 +1661,7 @@ static void *stream_client_handler(void *arg)
     {
         NULLFREE(http_buf);
         NULLFREE(stream_buf);
+        NULLFREE(send_buffer[conndata->connid]);
         NULLFREE(data);
         stream_client_disconnect(conndata);
         return NULL;
@@ -1527,6 +1704,11 @@ static void *stream_client_handler(void *arg)
         streamStatus = 0;
         bytesRead = 0;
 
+        send_buffer_length[conndata->connid] = 0;
+        send_buffer_offset[conndata->connid] = 0;
+
+        start_thread("emu stream client sender", stream_client_sender, conndata, &sender_thread, 0, 0);
+
         while (!exit_oscam && clientStatus != -1 && streamStatus != -1
                 && streamConnectErrorCount < 3 && streamDataErrorCount < 15)
         {
@@ -1537,8 +1719,8 @@ static void *stream_client_handler(void *arg)
             }
             else if (emu_fixed_key_data[conndata->connid].icam_csa_used)
             {
-                cur_dvb_buffer_size = 188 * cluster_size;
-                cur_dvb_buffer_wait = 188 * (cluster_size - 3);
+                cur_dvb_buffer_size = 188 * suggested_cluster_size;
+                cur_dvb_buffer_wait = 188 * suggested_cluster_size;
             }
             else
             {
@@ -1551,7 +1733,15 @@ static void *stream_client_handler(void *arg)
             pfd[1].fd = conndata->connfd;
             pfd[1].events = POLLRDHUP | POLLHUP;
 
+            struct timeb preMeasure, postMeasure;
+            cs_ftimeus(&preMeasure);
             ret = poll(pfd, 2, 2000);
+            cs_ftimeus(&postMeasure);
+            int64_t measured_time = comp_timebus(&postMeasure, &preMeasure);
+            if (measured_time > 2000) {
+                // printf("%7"PRIu64"\t%"PRId32"\t%"PRIu64"\n", measured_time, bytesRead, recved_since_last_long_poll);
+                recved_since_last_long_poll = 0;
+            }
 
             if (ret < 0) // poll error
             {
@@ -1571,6 +1761,7 @@ static void *stream_client_handler(void *arg)
                 if (pfd[0].revents & POLLIN) // new incoming data
                 {
                     streamStatus = recv(streamfd, stream_buf + bytesRead, cur_dvb_buffer_size - bytesRead, MSG_DONTWAIT);
+                    recved_since_last_long_poll += streamStatus;
                 }
                 if ((pfd[0].revents & POLLHUP) || (pfd[0].revents & POLLRDHUP)) // incoming connection closed
                 {
@@ -1601,7 +1792,6 @@ static void *stream_client_handler(void *arg)
                 {
                     cs_log_dbg(0, "WARNING: stream client %i non-full buffer from stream source", conndata->connid);
                     streamDataErrorCount++;
-                    cs_sleepms(100);
                 }
             }
             else
@@ -1612,7 +1802,7 @@ static void *stream_client_handler(void *arg)
             streamConnectErrorCount = 0;
             bytesRead += streamStatus;
 
-            if (bytesRead >= cur_dvb_buffer_wait)
+            if ((emu_fixed_key_data[data->connid].icam_csa_used && emu_fixed_key_data[data->connid].icam_csa_ks != NULL && bytesRead >= packetSize) || bytesRead >= cur_dvb_buffer_wait)
             {
                 startOffset = 0;
 
@@ -1622,9 +1812,9 @@ static void *stream_client_handler(void *arg)
                     SearchTsPackets(stream_buf, bytesRead, &packetSize, &startOffset);
                 }
 
-                if (packetSize == 0)
+                if (packetSize == 0) // no ts packets found yet
                 {
-                    bytesRead = 0;
+                    bytesRead = 0; // discard buffer
                 }
                 else
                 {
@@ -1649,7 +1839,18 @@ static void *stream_client_handler(void *arg)
                             }
                             else if (caid_is_icam(data->caid)) //ICAM
                             {
-                                DescrambleTsPacketsICam(data, stream_buf + startOffset, packetCount * packetSize, packetSize);
+                                //struct timeb preDescramble, postDescramble;
+                                //cs_ftimeus(&preDescramble);
+                                packetCount = DescrambleTsPacketsICam(data, stream_buf + startOffset, packetCount * packetSize, packetSize);
+                                cs_sleepms(1);
+                                // printf("descrambled %3"PRIu16" of %3"PRIu16" packets\n", packetCount, (bytesRead - startOffset) / packetSize);
+                                //cs_ftimeus(&postDescramble);
+                                //printf("%7"PRId64"\n",comp_timebus(&postDescramble, &preDescramble));
+                                if (packetCount == 0) {
+                                    // we could not descramble packets yet (probably b/c of missing cws)
+                                    // just copy all scrambled packets to sendbuffer
+                                    packetCount = ((bytesRead - startOffset) / packetSize);
+                                }
                             }
                         }
                         else
@@ -1663,7 +1864,22 @@ static void *stream_client_handler(void *arg)
                         ParseTsPackets(data, stream_buf + startOffset, packetCount * packetSize, packetSize);
                     }
 
-                    clientStatus = send(conndata->connfd, stream_buf + startOffset, packetCount * packetSize, 0);
+                    struct timeb preMeasure, postMeasure;
+
+                    // cs_ftimeus(&preMeasure);
+                    SAFE_MUTEX_LOCK(&emu_send_buffer_mutex[conndata->connid]);
+                    if (send_buffer_length[conndata->connid] + packetCount * packetSize > EMU_SEND_BUFFER_SIZE) {
+                        // reorganize sendbuffer
+                        cs_log("reorganize send_buffer");
+                        memmove(send_buffer[conndata->connid], send_buffer[conndata->connid] + send_buffer_offset[conndata->connid], send_buffer_length[conndata->connid] - send_buffer_offset[conndata->connid]);
+                        send_buffer_length[conndata->connid] = send_buffer_length[conndata->connid] - send_buffer_offset[conndata->connid];
+                        send_buffer_offset[conndata->connid] = 0;
+                    }
+                    memcpy(send_buffer[conndata->connid] + send_buffer_length[conndata->connid], stream_buf + startOffset, packetCount * packetSize);
+                    send_buffer_length[conndata->connid] += packetCount * packetSize;
+                    SAFE_MUTEX_UNLOCK(&emu_send_buffer_mutex[conndata->connid]);
+
+                    clientStatus = packetCount * packetSize;
 
                     remainingDataPos = startOffset + (packetCount * packetSize);
                     remainingDataLength = bytesRead - remainingDataPos;
@@ -1685,8 +1901,12 @@ static void *stream_client_handler(void *arg)
         close(streamfd);
     }
 
+    // wait for sender thread to finish
+    pthread_join(sender_thread, NULL);
+
     NULLFREE(http_buf);
     NULLFREE(stream_buf);
+    NULLFREE(send_buffer[conndata->connid]);
 
     for (i = 0; i < 8; i++)
     {
@@ -1695,10 +1915,6 @@ static void *stream_client_handler(void *arg)
             free_key_struct(data->key.pvu_csa_ks[i]);
         }
     }
-    if (data->key.icam_csa_ks)
-    {
-        free_key_struct(data->key.icam_csa_ks);
-    }
 #ifdef MODULE_RADEGAST
     icam_reset(data->connid);
 #endif
@@ -1717,7 +1933,8 @@ void *stream_server(void *UNUSED(a))
     emu_stream_client_conn_data *conndata;
 
     cluster_size = get_internal_parallelism();
-    cs_log("INFO: FFDecsa parallel mode = %d", cluster_size);
+    suggested_cluster_size = get_suggested_cluster_size();
+    cs_log("INFO: FFDecsa parallel mode = %d (suggested cluster size: %d packets)", cluster_size, suggested_cluster_size);
 
     if (!emu_stream_server_mutex_init)
     {
diff --git a/module-emulator-streamserver.h b/module-emulator-streamserver.h
index 5b76d0d..580e699 100644
--- a/module-emulator-streamserver.h
+++ b/module-emulator-streamserver.h
@@ -13,6 +13,15 @@
 #define EMU_DVB_BUFFER_WAIT_DES 188*29
 #define EMU_DVB_BUFFER_SIZE EMU_DVB_BUFFER_SIZE_CSA
 
+#define EMU_SEND_BUFFER_SIZE 188*204*208*2 // might implement ring buffer in future
+
+#define INVALID_PCR (uint64_t) 0xFFFFFFFFFFFFFFFF
+#define PCR_FREQ 27000000
+#define PCR_SCALE ((uint64_t)1 << 33) * 300
+
+// miliseconds of mpeg-ts to buffer
+#define INITIAL_BUFFER_TIME_MS 2500
+
 typedef struct
 {
     uint32_t pvu_des_ks[8][2][32];
@@ -85,6 +94,8 @@ extern pthread_mutex_t emu_fixed_key_data_mutex[EMU_STREAM_SERVER_MAX_CONNECTION
 extern emu_stream_client_key_data emu_fixed_key_data[EMU_STREAM_SERVER_MAX_CONNECTIONS];
 extern LLIST *ll_emu_stream_delayed_keys[EMU_STREAM_SERVER_MAX_CONNECTIONS];
 
+extern pthread_mutex_t emu_send_buffer_mutex[EMU_STREAM_SERVER_MAX_CONNECTIONS];
+
 void *stream_key_delayer(void *arg);
 bool stream_write_cw(ECM_REQUEST *er);
 
diff --git a/module-emulator.c b/module-emulator.c
index 0cdb915..ce6630e 100644
--- a/module-emulator.c
+++ b/module-emulator.c
@@ -735,6 +735,7 @@ static int32_t emu_reader_init(struct s_reader *UNUSED(reader))
         for (i = 0; i < EMU_STREAM_SERVER_MAX_CONNECTIONS; i++)
         {
             SAFE_MUTEX_INIT(&emu_fixed_key_data_mutex[i], NULL);
+            SAFE_MUTEX_INIT(&emu_send_buffer_mutex[i], NULL);
             ll_emu_stream_delayed_keys[i] = ll_create("ll_emu_stream_delayed_keys");
             memset(&emu_fixed_key_data[i], 0, sizeof(emu_stream_client_key_data));
         }
diff --git a/oscam-time.c b/oscam-time.c
index 0fceed5..7bb50b6 100644
--- a/oscam-time.c
+++ b/oscam-time.c
@@ -261,6 +261,22 @@ void add_ms_to_timeb(struct timeb *tb, int32_t ms)
     }
 }
 
+void add_us_to_timeb(struct timeb *tb, uint64_t us)
+{
+    if (us >= 1000000){
+        tb->time += us / 1000000;
+        tb->millitm += (us % 1000000);
+    }
+    else{
+        tb->millitm += us;
+    }
+    if(tb->millitm >= 1000000)
+    {
+        tb->millitm %= 1000000;
+        tb->time++;
+    }
+}
+
 int64_t add_ms_to_timeb_diff(struct timeb *tb, int32_t ms)
 {
     struct timeb tb_now;
diff --git a/oscam-time.h b/oscam-time.h
index d04f64b..138142c 100644
--- a/oscam-time.h
+++ b/oscam-time.h
@@ -19,6 +19,7 @@ void cs_sleepus(uint32_t usec);
 
 void add_ms_to_timespec(struct timespec *timeout, int32_t msec);
 void add_ms_to_timeb(struct timeb *tb, int32_t ms);
+void add_us_to_timeb(struct timeb *tb, uint64_t us);
 int64_t add_ms_to_timeb_diff(struct timeb *tb, int32_t ms);
 
 time_t cs_walltime(struct timeb *tp);

PS: Binaries werde ich nicht hochladen.
 
Zuletzt bearbeitet:
@putschi
welche basis hast du genommen? oscam-v11725 und icam-v9/v8 ???
und da du die uno4kse und solo2 erwähntest, gehe ich von ready2arm und ready2mips32el aus?
 
Zuletzt bearbeitet:
11725 + emu + v9
ready2arm und ready2mips32el? was meinst du damit?
 
Zuletzt bearbeitet:
@putschi
naja, du erwähntest in deinen Threads beide Box-Typen.
daraus schlussfolgere ich, das der "buffer.patch" entsprechend auch für beide CPU-Architekturen geeignet ist?
 
Ja, habs auch auf der Solo 2 mal ein wenig getestet. Sollte funktionieren.

Hab mal ein wenig aufgeräumt. Ist aber noch mehr rauszuschmeißen.

Wäre auch wünschenswert den sender_thread wieder zu entfernen. Ist auch noch ein relikt aus ersten Versuchen. Bringt unnötig Komplexität hinein.

Diff:
diff --git a/ffdecsa/ffdecsa.c b/ffdecsa/ffdecsa.c
index ca6d109..2ca01ff 100644
--- a/ffdecsa/ffdecsa.c
+++ b/ffdecsa/ffdecsa.c
@@ -63,8 +63,7 @@
 #define PARALLEL_MODE PARALLEL_128_SSE2
 
 #elif defined(__mips__) || defined(__mips) || defined(__MIPS__)
-//#define PARALLEL_MODE PARALLEL_64_LONG
-#define PARALLEL_MODE PARALLEL_32_INT
+#define PARALLEL_MODE PARALLEL_64_LONG
 
 #elif defined(__sh__) || defined(__SH4__)
 #define PARALLEL_MODE PARALLEL_32_INT
@@ -75,7 +74,7 @@
 #ifdef WITH_ARM_NEON
 #define PARALLEL_MODE PARALLEL_128_NEON
 #else
-#define PARALLEL_MODE PARALLEL_32_INT
+#define PARALLEL_MODE PARALLEL_64_LONG
 #endif
 
 #else
diff --git a/module-emulator-streamserver.c b/module-emulator-streamserver.c
index e32c244..70851cc 100644
--- a/module-emulator-streamserver.c
+++ b/module-emulator-streamserver.c
@@ -36,7 +36,7 @@ int32_t emu_stream_source_port = 8001;
 char *emu_stream_source_auth = NULL;
 int32_t emu_stream_relay_port = 17999;
 int8_t emu_stream_emm_enabled = 0;
-uint32_t cluster_size = 50;
+uint32_t cluster_size = 50, suggested_cluster_size;
 
 static uint8_t emu_stream_server_mutex_init = 0;
 static pthread_mutex_t emu_stream_server_mutex;
@@ -47,6 +47,10 @@ uint16_t emu_stream_cur_srvid[EMU_STREAM_SERVER_MAX_CONNECTIONS];
 int8_t stream_server_has_ecm[EMU_STREAM_SERVER_MAX_CONNECTIONS];
 
 pthread_mutex_t emu_fixed_key_data_mutex[EMU_STREAM_SERVER_MAX_CONNECTIONS];
+pthread_mutex_t emu_send_buffer_mutex[EMU_STREAM_SERVER_MAX_CONNECTIONS];
+uint8_t *send_buffer[EMU_STREAM_SERVER_MAX_CONNECTIONS];
+uint32_t send_buffer_length[EMU_STREAM_SERVER_MAX_CONNECTIONS] = {0};
+uint32_t send_buffer_offset[EMU_STREAM_SERVER_MAX_CONNECTIONS] = {0};
 emu_stream_client_key_data emu_fixed_key_data[EMU_STREAM_SERVER_MAX_CONNECTIONS];
 LLIST *ll_emu_stream_delayed_keys[EMU_STREAM_SERVER_MAX_CONNECTIONS];
 
@@ -1237,19 +1241,20 @@ static void DescrambleTsPacketsCompel(emu_stream_client_data *data, uint8_t *str
     }
 }
 
-static void DescrambleTsPacketsICam(emu_stream_client_data *data, uint8_t *stream_buf, uint32_t bufLength, uint16_t packetSize)
+static uint16_t DescrambleTsPacketsICam(emu_stream_client_data *data, uint8_t *stream_buf, uint32_t bufLength, uint16_t packetSize)
 {
-    uint8_t *packetCluster[4];
-    uint8_t scrambled_packets = 0, scramblingControl;
-    uint32_t i, tsHeader;
-    int8_t odd_even = -1, odd_even_count = 1;
+    uint8_t *packetCluster[3];
+    uint16_t retVal = bufLength / packetSize;
+
+#ifdef MODULE_RADEGAST
+    uint32_t i;
+    uint32_t tsHeader;
 
     for (i = 0; i < bufLength; i += packetSize)
     {
         tsHeader = b2i(4, stream_buf + i);
-        scramblingControl = (tsHeader & 0xC0) >> 6;
 
-#ifdef MODULE_RADEGAST
+
         uint16_t pid, offset, payloadStart;
 
         pid = (tsHeader & 0x1FFF00) >> 8;
@@ -1272,30 +1277,8 @@ static void DescrambleTsPacketsICam(emu_stream_client_data *data, uint8_t *strea
             ParseTsData(0x80, 0xFE, 3, &data->have_ecm_data, data->ecm_data, sizeof(data->ecm_data),
                         &data->ecm_data_pos, payloadStart, stream_buf + i + offset, packetSize - offset, ParseEcmData, data);
         }
-#endif // MODULE_RADEGAST
-
-        if (scramblingControl == 0)
-        {
-            continue;
-        }
-
-        scrambled_packets++;
-        scramblingControl &= 0x1;
-
-        if (odd_even == -1)
-        {
-            odd_even = scramblingControl;
-        }
-
-        if (odd_even != scramblingControl)
-        {
-            odd_even_count++;
-            odd_even = scramblingControl;
-        }
     }
-
-    if (scrambled_packets == 0)
-        return;
+#endif // MODULE_RADEGAST
 
     SAFE_MUTEX_LOCK(&emu_fixed_key_data_mutex[data->connid]);
 
@@ -1305,14 +1288,12 @@ static void DescrambleTsPacketsICam(emu_stream_client_data *data, uint8_t *strea
         packetCluster[1] = stream_buf + bufLength;
         packetCluster[2] = NULL;
 
-        decrypt_packets(emu_fixed_key_data[data->connid].icam_csa_ks, packetCluster);
-        if (odd_even_count > 1) // odd and even packets together cannot be decrypted in one step
-        {
-            decrypt_packets(emu_fixed_key_data[data->connid].icam_csa_ks, packetCluster);
-        }
+        retVal = decrypt_packets(emu_fixed_key_data[data->connid].icam_csa_ks, packetCluster);
     }
 
     SAFE_MUTEX_UNLOCK(&emu_fixed_key_data_mutex[data->connid]);
+
+    return retVal;
 }
 
 static int32_t connect_to_stream(char *http_buf, int32_t http_buf_len, char *stream_path)
@@ -1393,6 +1374,179 @@ static void stream_client_disconnect(emu_stream_client_conn_data *conndata)
     NULLFREE(conndata);
 }
 
+int64_t parse_pcr(const uint8_t *tsPacket) {
+    if (tsPacket[0] != 0x47) {
+        return INVALID_PCR;
+    }
+
+    if (!(tsPacket[3] & 0x20)) {
+        return INVALID_PCR;
+    }
+
+    if ((tsPacket[5] & 0x10)) {
+        uint16_t extension = 0;
+        uint64_t base = 0;
+
+        base |= (uint64_t)(tsPacket[6])<<25;
+        base |= (uint64_t)(tsPacket[7])<<(25-8);
+        base |= (uint64_t)(tsPacket[8])<<(25-8-8);
+        base |= (uint64_t)(tsPacket[9])<<(25-8-8-8);
+        base |= (uint16_t)(tsPacket[10] & 128)>>7;
+        extension |= tsPacket[11];
+        extension |= (uint16_t)(tsPacket[10] & 0x01)<<8;
+
+        return base*300 + extension;
+    }
+
+    return INVALID_PCR;
+}
+
+int64_t parse_pcr_unchecked(const uint8_t *tsPacket) {
+    uint16_t extension = 0;
+    uint64_t base = 0;
+
+    base |= (uint64_t)(tsPacket[6])<<25;
+    base |= (uint64_t)(tsPacket[7])<<(25-8);
+    base |= (uint64_t)(tsPacket[8])<<(25-8-8);
+    base |= (uint64_t)(tsPacket[9])<<(25-8-8-8);
+    base |= (uint16_t)(tsPacket[10] & 128)>>7;
+    extension |= tsPacket[11];
+    extension |= (uint16_t)(tsPacket[10] & 0x01)<<8;
+
+    return base*300 + extension;
+}
+
+int8_t has_pcr(const uint8_t *tsPacket) {
+    if (tsPacket[0] != 0x47) {
+        return 0;
+    }
+
+    if (!(tsPacket[3] & 0x20)) {
+        return 0;
+    }
+
+    return (tsPacket[5] & 0x10);
+}
+
+uint8_t is_scrambled(const uint8_t *tsPacket) {
+    return tsPacket[3] & 0x80;
+}
+
+uint8_t has_rai_flag(const uint8_t *tsPacket) {
+    if( ( tsPacket[3] & 0x20 ) && ( tsPacket[4] > 0 ) ) {
+        return tsPacket[5] & 0x40;
+    }
+    return 0;
+}
+
+uint16_t get_pid(const uint8_t *tsPacket) {
+    return ((tsPacket[1] & 0x1f) << 8) | tsPacket[2];
+}
+
+uint64_t find_first_pcr_value(const uint8_t *tsPackets, const uint32_t numPackets, const uint8_t packetSize) {
+    uint32_t packetNo;
+    uint64_t pcr = INVALID_PCR;
+    for (packetNo=0;packetNo<numPackets;packetNo++) {
+        pcr = parse_pcr(tsPackets+packetNo*packetSize);
+        if (pcr != INVALID_PCR) {
+            return pcr;
+        }
+    }
+    return INVALID_PCR;
+}
+
+uint8_t *find_next_pcr_packet(uint8_t *tsPackets, uint32_t tsPacketsLen, uint8_t packetSize) {
+    uint32_t packetNo;
+    for (packetNo=0;packetNo*packetSize<tsPacketsLen;packetNo++) {
+        if (has_pcr(tsPackets+packetNo*packetSize)) {
+            return tsPackets+packetNo*packetSize;
+        }
+    }
+    return NULL;
+}
+
+uint64_t find_last_pcr_value(const uint8_t *tsPackets, const uint32_t numPackets, const uint8_t packetSize) {
+    uint32_t packetNo;
+    uint64_t pcr = INVALID_PCR;
+    for (packetNo=numPackets;packetNo-->0;) {
+        pcr = parse_pcr(tsPackets+packetNo*packetSize);
+        if (pcr != INVALID_PCR) {
+            return pcr;
+        }
+    }
+    return INVALID_PCR;
+}
+
+uint64_t calc_pcr_timespan(const uint8_t *tsPackets, const uint32_t numPackets, const uint8_t packetSize) {
+    return find_last_pcr_value(tsPackets, numPackets, packetSize) - find_first_pcr_value(tsPackets, numPackets, packetSize);
+}
+
+uint8_t has_pusi_flag(const uint8_t *tsPacket) {
+    return tsPacket[1] & 0x40;
+}
+
+
+static void stream_client_sender(void *arg)
+{
+    uint8_t continue_sending = 1;
+    uint8_t packetSize = 188;
+    int32_t connid = ((emu_stream_client_conn_data *) arg)->connid;
+    int32_t connfd = ((emu_stream_client_conn_data *) arg)->connfd;
+
+    cs_log("Stream client %i sender started!", connid);
+    while (continue_sending) {
+        // wait until we have enough packets in send buffer
+        while (continue_sending) {
+            SAFE_MUTEX_LOCK(&emu_send_buffer_mutex[connid]);
+            uint8_t *currentPacket = NULL, *descrambled_rai_packet = NULL;
+            uint64_t pcrdiff = 0;
+            uint32_t packetNo = 0;
+            for (currentPacket = send_buffer[connid]+send_buffer_offset[connid]; currentPacket<(send_buffer[connid]+send_buffer_length[connid]);currentPacket+=packetSize) {
+                if (has_rai_flag(currentPacket) && !is_scrambled(currentPacket)) {
+                    descrambled_rai_packet = currentPacket;
+                    break;
+                }
+                packetNo++;
+            }
+
+            if (descrambled_rai_packet != NULL) {
+                pcrdiff = calc_pcr_timespan(descrambled_rai_packet, (send_buffer[connid]+send_buffer_length[connid]-descrambled_rai_packet) / packetSize, packetSize);
+            }
+            SAFE_MUTEX_UNLOCK(&emu_send_buffer_mutex[connid]);
+            if (pcrdiff > INITIAL_BUFFER_TIME_MS*(PCR_FREQ/1000)) {
+                break;
+            } else {
+            }
+            cs_sleepms(35); // 35 ms is a typical timespan between two PCR packets
+        }
+        cs_log("Stream client %i buffer time reached!", connid);
+        SAFE_MUTEX_LOCK(&emu_send_buffer_mutex[connid]);
+        while (continue_sending) {
+            uint16_t packetsToSend = (send_buffer_length[connid]-send_buffer_offset[connid]) / packetSize;
+            if (packetsToSend > 80) {
+                // limit bitrate to ~30mbit/s
+                packetsToSend = 80;
+            }
+
+            ssize_t bytesSent = send(connfd, send_buffer[connid]+send_buffer_offset[connid], packetsToSend*packetSize, 0);
+            if (bytesSent == -1) {
+                cs_log_dbg(0, "Stream client %i could not send. Stopping sender!", connid);
+                continue_sending = 0;
+                break;
+            } else if (bytesSent != packetsToSend*188) {
+                cs_log("Stream client %i sent only %d bytes", connid, bytesSent);
+            }
+
+            send_buffer_offset[connid]+=packetsToSend*188;
+            SAFE_MUTEX_UNLOCK(&emu_send_buffer_mutex[connid]);
+            cs_sleepms(5);
+            SAFE_MUTEX_LOCK(&emu_send_buffer_mutex[connid]);
+        }
+        SAFE_MUTEX_UNLOCK(&emu_send_buffer_mutex[connid]);
+    }
+    cs_log("Stream client %i sender stopped!", connid);
+}
+
 static void *stream_client_handler(void *arg)
 {
     emu_stream_client_conn_data *conndata = (emu_stream_client_conn_data *)arg;
@@ -1410,6 +1564,15 @@ static void *stream_client_handler(void *arg)
     uint16_t packetCount = 0, packetSize = 0, startOffset = 0;
     uint32_t remainingDataPos, remainingDataLength, tmp_pids[4];
 
+    uint64_t last_pcr = INVALID_PCR;
+    uint16_t packets_since_last_pcr;
+
+    struct timeb now, postPublish = {.time = 0};
+
+    uint64_t recved_since_last_long_poll = 0;
+
+    pthread_t sender_thread;
+
     struct pollfd pfd[2];
     int ret;
 
@@ -1428,10 +1591,19 @@ static void *stream_client_handler(void *arg)
         return NULL;
     }
 
+    if (!cs_malloc(&send_buffer[conndata->connid], EMU_SEND_BUFFER_SIZE))
+    {
+        NULLFREE(http_buf);
+        NULLFREE(stream_buf);
+        stream_client_disconnect(conndata);
+        return NULL;
+    }
+
     if (!cs_malloc(&data, sizeof(emu_stream_client_data)))
     {
         NULLFREE(http_buf);
         NULLFREE(stream_buf);
+        NULLFREE(send_buffer[conndata->connid]);
         stream_client_disconnect(conndata);
         return NULL;
     }
@@ -1441,6 +1613,7 @@ static void *stream_client_handler(void *arg)
     {
         NULLFREE(http_buf);
         NULLFREE(stream_buf);
+        NULLFREE(send_buffer[conndata->connid]);
         NULLFREE(data);
         stream_client_disconnect(conndata);
         return NULL;
@@ -1451,6 +1624,7 @@ static void *stream_client_handler(void *arg)
     {
         NULLFREE(http_buf);
         NULLFREE(stream_buf);
+        NULLFREE(send_buffer[conndata->connid]);
         NULLFREE(data);
         stream_client_disconnect(conndata);
         return NULL;
@@ -1485,6 +1659,7 @@ static void *stream_client_handler(void *arg)
     {
         NULLFREE(http_buf);
         NULLFREE(stream_buf);
+        NULLFREE(send_buffer[conndata->connid]);
         NULLFREE(data);
         stream_client_disconnect(conndata);
         return NULL;
@@ -1527,6 +1702,11 @@ static void *stream_client_handler(void *arg)
         streamStatus = 0;
         bytesRead = 0;
 
+        send_buffer_length[conndata->connid] = 0;
+        send_buffer_offset[conndata->connid] = 0;
+
+        start_thread("emu stream client sender", stream_client_sender, conndata, &sender_thread, 0, 0);
+
         while (!exit_oscam && clientStatus != -1 && streamStatus != -1
                 && streamConnectErrorCount < 3 && streamDataErrorCount < 15)
         {
@@ -1537,8 +1717,8 @@ static void *stream_client_handler(void *arg)
             }
             else if (emu_fixed_key_data[conndata->connid].icam_csa_used)
             {
-                cur_dvb_buffer_size = 188 * cluster_size;
-                cur_dvb_buffer_wait = 188 * (cluster_size - 3);
+                cur_dvb_buffer_size = 188 * suggested_cluster_size;
+                cur_dvb_buffer_wait = 188 * suggested_cluster_size;
             }
             else
             {
@@ -1546,12 +1726,15 @@ static void *stream_client_handler(void *arg)
                 cur_dvb_buffer_wait = EMU_DVB_BUFFER_WAIT_DES;
             }
 
+            uint8_t packets_left_in_buffer = (packetSize > 0) ? bytesRead/packetSize:0;
+            uint8_t descrambling = data->have_pat_data == 1 && data->have_pmt_data == 1;
+
             pfd[0].fd = streamfd;
             pfd[0].events = POLLIN | POLLRDHUP | POLLHUP;
             pfd[1].fd = conndata->connfd;
             pfd[1].events = POLLRDHUP | POLLHUP;
 
-            ret = poll(pfd, 2, 2000);
+            ret = poll(pfd, 2, (packets_left_in_buffer > 0 && descrambling) ? 5:2000);
 
             if (ret < 0) // poll error
             {
@@ -1562,9 +1745,14 @@ static void *stream_client_handler(void *arg)
             }
             else if (ret == 0) // timeout
             {
-                cs_log("WARNING: stream client %i no data from stream source", conndata->connid);
-                streamDataErrorCount++; // 2 sec timeout * 15 = 30 seconds no data -> close
-                continue;
+                if (packets_left_in_buffer > 0 && descrambling) {
+                    // was fast timeout
+                    streamStatus = 0; // act like we received 0 new bytes
+                } else {
+                    cs_log("WARNING: stream client %i no data from stream source", conndata->connid);
+                    streamDataErrorCount++; // 2 sec timeout * 15 = 30 seconds no data -> close
+                    continue;
+                }
             }
             else
             {
@@ -1601,7 +1789,6 @@ static void *stream_client_handler(void *arg)
                 {
                     cs_log_dbg(0, "WARNING: stream client %i non-full buffer from stream source", conndata->connid);
                     streamDataErrorCount++;
-                    cs_sleepms(100);
                 }
             }
             else
@@ -1612,7 +1799,7 @@ static void *stream_client_handler(void *arg)
             streamConnectErrorCount = 0;
             bytesRead += streamStatus;
 
-            if (bytesRead >= cur_dvb_buffer_wait)
+            if (bytesRead >= cur_dvb_buffer_wait || (packets_left_in_buffer > 0 && descrambling))
             {
                 startOffset = 0;
 
@@ -1622,9 +1809,9 @@ static void *stream_client_handler(void *arg)
                     SearchTsPackets(stream_buf, bytesRead, &packetSize, &startOffset);
                 }
 
-                if (packetSize == 0)
+                if (packetSize == 0) // no ts packets found yet
                 {
-                    bytesRead = 0;
+                    bytesRead = 0; // discard buffer
                 }
                 else
                 {
@@ -1649,7 +1836,8 @@ static void *stream_client_handler(void *arg)
                             }
                             else if (caid_is_icam(data->caid)) //ICAM
                             {
-                                DescrambleTsPacketsICam(data, stream_buf + startOffset, packetCount * packetSize, packetSize);
+                                packetCount = DescrambleTsPacketsICam(data, stream_buf + startOffset, packetCount * packetSize, packetSize);
+                                cs_sleepus(1500);
                             }
                         }
                         else
@@ -1663,7 +1851,18 @@ static void *stream_client_handler(void *arg)
                         ParseTsPackets(data, stream_buf + startOffset, packetCount * packetSize, packetSize);
                     }
 
-                    clientStatus = send(conndata->connfd, stream_buf + startOffset, packetCount * packetSize, 0);
+                    SAFE_MUTEX_LOCK(&emu_send_buffer_mutex[conndata->connid]);
+                    if (send_buffer_length[conndata->connid] + packetCount * packetSize > EMU_SEND_BUFFER_SIZE) {
+                        // reorganize sendbuffer
+                        memmove(send_buffer[conndata->connid], send_buffer[conndata->connid] + send_buffer_offset[conndata->connid], send_buffer_length[conndata->connid] - send_buffer_offset[conndata->connid]);
+                        send_buffer_length[conndata->connid] = send_buffer_length[conndata->connid] - send_buffer_offset[conndata->connid];
+                        send_buffer_offset[conndata->connid] = 0;
+                    }
+                    memcpy(send_buffer[conndata->connid] + send_buffer_length[conndata->connid], stream_buf + startOffset, packetCount * packetSize);
+                    send_buffer_length[conndata->connid] += packetCount * packetSize;
+                    SAFE_MUTEX_UNLOCK(&emu_send_buffer_mutex[conndata->connid]);
+
+                    clientStatus = packetCount * packetSize;
 
                     remainingDataPos = startOffset + (packetCount * packetSize);
                     remainingDataLength = bytesRead - remainingDataPos;
@@ -1685,8 +1884,12 @@ static void *stream_client_handler(void *arg)
         close(streamfd);
     }
 
+    // wait for sender thread to finish
+    pthread_join(sender_thread, NULL);
+
     NULLFREE(http_buf);
     NULLFREE(stream_buf);
+    NULLFREE(send_buffer[conndata->connid]);
 
     for (i = 0; i < 8; i++)
     {
@@ -1695,10 +1898,6 @@ static void *stream_client_handler(void *arg)
             free_key_struct(data->key.pvu_csa_ks[i]);
         }
     }
-    if (data->key.icam_csa_ks)
-    {
-        free_key_struct(data->key.icam_csa_ks);
-    }
 #ifdef MODULE_RADEGAST
     icam_reset(data->connid);
 #endif
@@ -1717,7 +1916,8 @@ void *stream_server(void *UNUSED(a))
     emu_stream_client_conn_data *conndata;
 
     cluster_size = get_internal_parallelism();
-    cs_log("INFO: FFDecsa parallel mode = %d", cluster_size);
+    suggested_cluster_size = get_suggested_cluster_size();
+    cs_log("INFO: FFDecsa parallel mode = %d (suggested cluster size: %d packets)", cluster_size, suggested_cluster_size);
 
     if (!emu_stream_server_mutex_init)
     {
diff --git a/module-emulator-streamserver.h b/module-emulator-streamserver.h
index 5b76d0d..580e699 100644
--- a/module-emulator-streamserver.h
+++ b/module-emulator-streamserver.h
@@ -13,6 +13,15 @@
 #define EMU_DVB_BUFFER_WAIT_DES 188*29
 #define EMU_DVB_BUFFER_SIZE EMU_DVB_BUFFER_SIZE_CSA
 
+#define EMU_SEND_BUFFER_SIZE 188*204*208*2 // might implement ring buffer in future
+
+#define INVALID_PCR (uint64_t) 0xFFFFFFFFFFFFFFFF
+#define PCR_FREQ 27000000
+#define PCR_SCALE ((uint64_t)1 << 33) * 300
+
+// miliseconds of mpeg-ts to buffer
+#define INITIAL_BUFFER_TIME_MS 2500
+
 typedef struct
 {
     uint32_t pvu_des_ks[8][2][32];
@@ -85,6 +94,8 @@ extern pthread_mutex_t emu_fixed_key_data_mutex[EMU_STREAM_SERVER_MAX_CONNECTION
 extern emu_stream_client_key_data emu_fixed_key_data[EMU_STREAM_SERVER_MAX_CONNECTIONS];
 extern LLIST *ll_emu_stream_delayed_keys[EMU_STREAM_SERVER_MAX_CONNECTIONS];
 
+extern pthread_mutex_t emu_send_buffer_mutex[EMU_STREAM_SERVER_MAX_CONNECTIONS];
+
 void *stream_key_delayer(void *arg);
 bool stream_write_cw(ECM_REQUEST *er);
 
diff --git a/module-emulator.c b/module-emulator.c
index 0cdb915..ce6630e 100644
--- a/module-emulator.c
+++ b/module-emulator.c
@@ -735,6 +735,7 @@ static int32_t emu_reader_init(struct s_reader *UNUSED(reader))
         for (i = 0; i < EMU_STREAM_SERVER_MAX_CONNECTIONS; i++)
         {
             SAFE_MUTEX_INIT(&emu_fixed_key_data_mutex[i], NULL);
+            SAFE_MUTEX_INIT(&emu_send_buffer_mutex[i], NULL);
             ll_emu_stream_delayed_keys[i] = ll_create("ll_emu_stream_delayed_keys");
             memset(&emu_fixed_key_data[i], 0, sizeof(emu_stream_client_key_data));
         }

Mir ist leider noch immer nicht wirklich klar, wieso das notwendig ist. Interessant fand ich noch, dass der v9-Patch auf der VU+ Uno 4K SE gut funktioniert, wenn man den Transportstream inkl. ECMs von der SF8008 abholt. Es hängt also wohl wirklich mit dem Burst/Buffer Verhalten zusammen (2100 Packets alle ~100-900ms).
 
Zuletzt bearbeitet:
Im Allgemeinen stell ich mich zwar nicht so an, aber der Patch funktioniert bei mir nicht.

Was ist denn die Voraussetzung? Emu+V9+Buffer?
 
Das patchen funktioniert nicht? Hatte etwas weiter oben geschrieben, was ich als Basis genutzt habe. Kann es später aber auch nochmal kontrollieren
 
Das erhalte ich wenn ich den Patch ausführe:

patching file ffdecsa/ffdecsa.c
patching file module-emulator-streamserver.c
Hunk #3 FAILED at 1241.
Hunk #4 FAILED at 1276.
Hunk #5 FAILED at 1309.
Hunk #6 succeeded at 1397 with fuzz 1.
Hunk #7 FAILED at 1587.
Hunk #8 FAILED at 1605.
Hunk #9 FAILED at 1618.
Hunk #10 FAILED at 1628.
Hunk #11 FAILED at 1662.
Hunk #12 FAILED at 1704.
Hunk #13 FAILED at 1714.
Hunk #14 FAILED at 1723.
Hunk #15 FAILED at 1739.
Hunk #16 FAILED at 1778.
Hunk #17 FAILED at 1789.
Hunk #18 FAILED at 1799.
Hunk #19 FAILED at 1826.
Hunk #20 FAILED at 1840.
Hunk #21 FAILED at 1862.
Hunk #22 FAILED at 1872.
Hunk #23 FAILED at 1894.
20 out of 23 hunks FAILED -- saving rejects to file module-emulator-streamserver.c.rej
patching file module-emulator-streamserver.h
Hunk #1 succeeded at 13 with fuzz 1.
patching file module-emulator.c
Hunk #1 FAILED at 735.
1 out of 1 hunk FAILED -- saving rejects to file module-emulator.c.rej
 
Bash:
svn export https://svn.streamboard.tv/oscam/trunk oscam
pushd oscam || cd oscam
patch -i ../oscam-emu.patch -p0
patch -i ../oscam_emu_icam_dvbapi_radegast_v9.patch.txt -p1
patch -i ../buffer.patch -p1
popd || cd ..

weiß gerade nur nicht, wo ich den oscam-emu.patch für 11725 bezogen habe. ich meine das war im streamboard. edit:

$ sha1sum oscam-emu.patch
791fef9a607ee7daea66c98d74d4c2e4e462a51a oscam-emu.patch

$ sha1sum oscam_emu_icam_dvbapi_radegast_v9.patch.txt
c5ea085b659b760eaeffac587cefff6bc41108f4 oscam_emu_icam_dvbapi_radegast_v9.patch.txt
 
Zuletzt bearbeitet von einem Moderator:
Bash:
svn export https://svn.streamboard.tv/oscam/trunk oscam
pushd oscam || cd oscam
patch -i ../oscam-emu.patch -p0
patch -i ../oscam_emu_icam_dvbapi_radegast_v9.patch.txt -p 1
patch -i ../buffer.patch -p1
popd || cd ..

weiß gerade nur nicht, wo ich den oscam-emu.patch für 11725 bezogen habe. ich meine das war im streamboard
Die für 11725 gabs hier nicht glaube nicht. 11724 war die letzte soweit ich weiss. Und die für 11725, die habe ich auch vom streamboard.
 
Womit baust du denn? Mit s3 bekomme ich die gleichen Fehler wie @ChrisOsgood
Die Zeilen der Änderungen passen irgendwie nicht. Habs bei ein paar Hunks geändert aber wurde mir dann doch zu viel alles zu checken und ändern :D
 
Baue auch mit s3 (./s3 solo4k). Gepatcht habe ich allerdings manuell. Habe das oscam-svn Verzeichnis in s3 ausgetauscht. Nutze s3 nur, da es der schnellste Weg zu den Toolchains war.
 
Bauen mache ich auch mit s3. Mit s3 svn auschecken und dann händisch über die console patchen und dann mit s3 bauen.
Code:
patch -p0 < oscam-emu.patch
patch -p1 < oscam_emu_icam_dvbapi_radegast_v9.patch
patch -p1 < buffer.patch
Alle patches ohne Fehler nur der buffer.patch spuckt die ganzen Hunks usw. aus.
 
Status
Für weitere Antworten geschlossen.
Zurück
Oben