[dvblast-devel] [Git][videolan/dvblast][master] 2 commits: Use DTV_SCRAMBLING_SEQUENCE_INDEX for DVB-S2 multistream

Christophe Massiot (@cmassiot) gitlab at videolan.org
Sat Nov 1 18:38:28 UTC 2025



Christophe Massiot pushed to branch master at VideoLAN / dvblast


Commits:
746e19af by Christophe Massiot at 2025-10-25T18:31:23+02:00
Use DTV_SCRAMBLING_SEQUENCE_INDEX for DVB-S2 multistream

- - - - -
b276f61a by Christophe Massiot at 2025-11-01T19:37:49+01:00
Add support for DVB-S2 raw BBFrame demuxing.

- - - - -


7 changed files:

- NEWS
- README
- demux.c
- dvb.c
- dvblast.c
- dvblast.h
- output.c


Changes:

=====================================
NEWS
=====================================
@@ -3,6 +3,10 @@ Changes between 3.4 and 3.5:
   * Print bitrate status for each service
   * Fix passing through the EITp/f without EPG tables (broken in 3.3)
   * Add new option --udp-lock-timeout
+  * Use newer linux-dvb API to get signal statistics
+  * Add support for descrambling cards with UDP/RTP input
+  * Use DTV_SCRAMBLING_SEQUENCE_INDEX for DVB-S2 multistream
+  * Add support for DVB-S2 raw BBFrame demuxing
 
 Changes between 3.3 and 3.4:
 ----------------------------


=====================================
README
=====================================
@@ -309,3 +309,36 @@ unused ones, can be output.
 
 Other options are self-understandable, and are listed in dvblast -h.
 
+
+Descrambling device support
+===========================
+DVBlast can descramble a UDP or RTP stream using a CAM and a descrambling
+PCIe card. You have to select the device with --sec-number:
+dvblast -D 239.255.0.1:1234 --sec-number 0
+
+
+Raw BBFrame support for Multiple Input Stream
+=============================================
+
+Some DVB-S2 transponders (especially on Eutelsat 5°W) use a feature called
+Multiple Input Stream (MIS) to transmit several TS on the same frequency.
+To retrieve a specific stream, you normally use --multistream-id-pls-mode,
+--multistream-id-pls-code and --multistream-id-is-id and the specific
+stream will be retrieved by the demod.
+
+However some cards (at the moment from Digital Devices brand) have a feature
+allowing to bypass the demod, and do the demultiplexing of DVB-S2 BBframes
+in software, which allows to retrieve all streams with a single tuner/demod,
+and also fixes some compatibility issues on some frequencies. See:
+https://support.digital-devices.eu/index.php?article=194&rated=1
+
+This feature is activated with --bbframe-demux. When this flag is set, you
+have to specify the streams you want instead of the SID in the config file,
+for instance:
+239.255.0.1:1234		1	10
+239.255.0.2:1234		1	7
+
+This will send streams 10 and 7 to the given addresses. The second argument
+and the pids are ignored. The whole TS is transmitted, so if you want to
+demultiplex it, use a second DVBlast instance with the -D input:
+dvblast -D 239.255.0.1:1234


=====================================
demux.c
=====================================
@@ -1,9 +1,9 @@
 /*****************************************************************************
  * demux.c
  *****************************************************************************
- * Copyright (C) 2004, 2008-2011, 2015-2018 VideoLAN
+ * Copyright (C) 2004, 2008-2011, 2015-2018, 2025 VideoLAN
  *
- * Authors: Christophe Massiot <massiot at via.ecp.fr>
+ * Authors: Christophe Massiot <cmassiot at upipe.orgq>
  *          Andy Gatward <a.j.gatward at reading.ac.uk>
  *          Marian Ďurkovič <md at bts.sk>
  *
@@ -49,6 +49,7 @@
 #include <bitstream/dvb/si.h>
 #include <bitstream/dvb/si_print.h>
 #include <bitstream/mpeg/psi_print.h>
+#include <bitstream/dvb/s2.h>
 
 /*****************************************************************************
  * Local declarations
@@ -101,11 +102,28 @@ typedef struct sid_t
     unsigned long i_packets_passed;
 } sid_t;
 
+struct mis
+{
+    uint8_t i_mis;
+    uint8_t i_matype1;
+    bool b_issy;
+    bool b_npd;
+    uint16_t i_upl;
+
+    uint8_t p_up[TS_SIZE + S2BBDF_ISSY_MAX_SIZE + S2BBDF_NPD_SIZE];
+    uint8_t i_up_size;
+
+    output_t **pp_outputs;
+    int i_nb_outputs;
+};
+
 mtime_t i_wallclock = 0;
 
 static ts_pid_t p_pids[MAX_PIDS];
 static sid_t **pp_sids = NULL;
 static int i_nb_sids = 0;
+static struct mis **pp_miss = NULL;
+static int i_nb_miss = 0;
 
 static PSI_TABLE_DECLARE(pp_current_pat_sections);
 static PSI_TABLE_DECLARE(pp_next_pat_sections);
@@ -115,6 +133,11 @@ static PSI_TABLE_DECLARE(pp_current_nit_sections);
 static PSI_TABLE_DECLARE(pp_next_nit_sections);
 static PSI_TABLE_DECLARE(pp_current_sdt_sections);
 static PSI_TABLE_DECLARE(pp_next_sdt_sections);
+
+struct mis *p_current_mis = NULL;
+static uint8_t i_last_bbframe_counter = UINT8_MAX;
+static uint16_t i_current_mis_dfl = 0;
+
 static mtime_t i_last_dts = -1;
 static int i_demux_fd;
 static uint64_t i_nb_packets = 0;
@@ -268,6 +291,39 @@ static inline sid_t *FindSID( uint16_t i_sid )
     return NULL;
 }
 
+/*****************************************************************************
+ * FindMis
+ *****************************************************************************/
+static inline struct mis *FindMis( uint8_t i_mis )
+{
+    int i;
+
+    for ( i = 0; i < i_nb_miss; i++ )
+    {
+        struct mis *p_mis = pp_miss[i];
+        if ( p_mis->i_mis == i_mis )
+            return p_mis;
+    }
+    return NULL;
+}
+
+/*****************************************************************************
+ * NewMis
+ *****************************************************************************/
+static inline struct mis *NewMis( uint8_t i_mis )
+{
+    struct mis *p_mis = malloc( sizeof(struct mis) );
+    p_mis->i_mis = i_mis;
+    p_mis->i_matype1 = 0xff; /* impossible value */
+    p_mis->i_up_size = 0;
+    p_mis->pp_outputs = NULL;
+    p_mis->i_nb_outputs = 0;
+    i_nb_miss++;
+    pp_miss = realloc( pp_miss, sizeof(struct mis *) * i_nb_miss );
+    pp_miss[i_nb_miss - 1] = p_mis;
+    return p_mis;
+}
+
 /*****************************************************************************
  * Print info
  *****************************************************************************/
@@ -512,6 +568,14 @@ void demux_Close( void )
     }
     free( pp_sids );
 
+    for ( i = 0; i < i_nb_miss; i++ )
+    {
+        struct mis *p_mis = pp_miss[i];
+        free( p_mis->pp_outputs );
+        free( p_mis );
+    }
+    free( pp_miss );
+
 #ifdef HAVE_ICONV
     if (iconv_handle != (iconv_t)-1) {
         iconv_close(iconv_handle);
@@ -636,6 +700,14 @@ static void demux_Handle( block_t *p_ts )
         pf_Reset();
     }
 
+    if ( i_mis_is_id == -1 )
+    {
+        /* BBframe mode, only demux 0x80 sections of PID 0x010e */
+        if ( i_pid == S2BBFRAMES_PID )
+            HandlePSIPacket( p_ts->p_ts, p_ts->i_dts );
+        goto demux_out;
+    }
+
     if ( i_es_timeout )
     {
         int i_pes_status = -1;
@@ -774,6 +846,7 @@ static void demux_Handle( block_t *p_ts )
     if ( output_dup.config.i_config & OUTPUT_VALID )
         output_Put( &output_dup, p_ts );
 
+demux_out:
     if ( b_passthrough )
         fwrite(p_ts->p_ts, TS_SIZE, 1, stdout);
 
@@ -795,6 +868,66 @@ static bool IsIn( const uint16_t *pi_pids, int i_nb_pids, uint16_t i_pid )
 
 void demux_Change( output_t *p_output, const output_config_t *p_config )
 {
+    if ( i_mis_is_id == -1 )
+    {
+        /* Special case for MIS demux - sid == mis, ignore pids */
+        uint16_t i_old_mis = p_output->config.i_sid;
+        uint16_t i_mis = p_config->i_sid;
+
+        p_output->config.i_config = p_config->i_config;
+        p_output->config.i_sid = p_config->i_sid;
+
+        if ( i_mis == i_old_mis )
+            return;
+
+        if ( i_old_mis != UINT16_MAX )
+        {
+            struct mis *p_mis = FindMis( i_old_mis );
+            int j;
+            for ( j = 0; j < p_mis->i_nb_outputs; j++ )
+            {
+                if ( p_mis->pp_outputs[j] == p_output )
+                {
+                    p_mis->pp_outputs[j] = NULL;
+                    break;
+                }
+            }
+        }
+
+        if ( i_mis != UINT16_MAX )
+        {
+            struct mis *p_mis = FindMis( i_mis );
+            int j;
+            if ( p_mis == NULL )
+            {
+                /* Not yet detected but may come later */
+                p_mis = NewMis( i_mis );
+            }
+
+            for ( j = 0; j < p_mis->i_nb_outputs; j++ )
+                if ( p_mis->pp_outputs[j] == p_output )
+                    break;
+
+            if ( j == p_mis->i_nb_outputs )
+            {
+                for ( j = 0; j < p_mis->i_nb_outputs; j++ )
+                    if ( p_mis->pp_outputs[j] == NULL )
+                        break;
+
+                if ( j == p_mis->i_nb_outputs )
+                {
+                    p_mis->i_nb_outputs++;
+                    p_mis->pp_outputs = realloc( p_mis->pp_outputs,
+                                                 sizeof(output_t *)
+                                                  * p_mis->i_nb_outputs );
+                }
+
+                p_mis->pp_outputs[j] = p_output;
+            }
+        }
+        return;
+    }
+
     uint16_t *pi_wanted_pids, *pi_current_pids;
     int i_nb_wanted_pids, i_nb_current_pids;
     uint16_t i_wanted_pcr_pid, i_current_pcr_pid;
@@ -3120,6 +3253,232 @@ out_eit:
     SendEIT( p_sid, i_dts, p_eit );
 }
 
+/*****************************************************************************
+ * HandleBBFrameSection
+ *****************************************************************************/
+static void HandleBBFrameSection( const uint8_t *p_bbframes, mtime_t i_dts )
+{
+    if ( !s2bbframes_validate( p_bbframes ) )
+    {
+        msg_Warn( NULL, "invalid BBFrame section received" );
+        return;
+    }
+
+    uint8_t i_counter = s2bbframes_get_counter( p_bbframes );
+    uint8_t *p_bbframe = s2bbframes_get_bbframe( p_bbframes );
+    uint16_t i_bbframe_size = s2bbframes_get_length( p_bbframes );
+
+    if ( i_counter == S2BBFRAMES_HEADER_COUNTER )
+    {
+        /* Parse new BBFrame header */
+        if ( i_bbframe_size < S2BBH_SIZE )
+        {
+            msg_Warn( NULL, "too short BBFrame section received" );
+            return;
+        }
+        if ( !s2bbh_validate( p_bbframe ) )
+        {
+            msg_Warn( NULL, "invalid BBFrame header received" );
+            return;
+        }
+        if ( s2bbh_get_tsgs( p_bbframe ) != S2BBH_TSGS_TRANSPORT )
+        {
+            msg_Warn( NULL, "unsupported Generic Stream Input" );
+            return;
+        }
+        if ( s2bbh_is_sis( p_bbframe ) )
+        {
+            msg_Warn( NULL, "unsupported Single Input Stream mode" );
+            return;
+        }
+        if ( s2bbh_get_sync( p_bbframe ) != TS_SYNC )
+        {
+            msg_Warn( NULL, "invalid BBFrame sync received" );
+            return;
+        }
+
+        i_last_bbframe_counter = 0;
+        uint8_t i_mis = s2bbh_get_mis( p_bbframe );
+        bool b_ccm = s2bbh_is_ccm( p_bbframe );
+        bool b_issyi = s2bbh_has_issyi( p_bbframe );
+        bool b_npd = s2bbh_has_npd( p_bbframe );
+        uint8_t i_ro = s2bbh_get_ro( p_bbframe );
+        uint16_t i_upl = s2bbh_get_upl( p_bbframe ) / 8;
+        i_current_mis_dfl = s2bbh_get_dfl( p_bbframe ) / 8;
+        uint16_t i_syncd = s2bbh_get_syncd( p_bbframe ) / 8;
+
+        p_current_mis = FindMis( i_mis );
+        if ( p_current_mis == NULL )
+        {
+            p_current_mis = malloc( sizeof(struct mis) );
+            p_current_mis->i_mis = i_mis;
+            p_current_mis->i_matype1 = 0xff; /* impossible value */
+            p_current_mis->i_up_size = 0;
+            p_current_mis->pp_outputs = NULL;
+            p_current_mis->i_nb_outputs = 0;
+            i_nb_miss++;
+            pp_miss = realloc( pp_miss, sizeof(struct mis *) * i_nb_miss );
+            pp_miss[i_nb_miss - 1] = p_current_mis;
+        }
+
+        if ( p_current_mis->i_matype1 != p_bbframe[0] )
+        {
+            switch (i_print_type) {
+            case PRINT_XML:
+                fprintf(print_fh, "<STREAM mis=\"%"PRIu8"\" mode=\"%s\" issyi=\"%s\" npd=\"%s\" ro=\"%s\" />\n",
+                        i_mis, b_ccm ? "ccm" : "acm",
+                        b_issyi ? "true" : "false",
+                        b_npd ? "true" : "false",
+                        i_ro == S2BBH_RO_35 ? "0.35" :
+                            (i_ro == S2BBH_RO_25 ? "0.25" :
+                                (i_ro == S2BBH_RO_20 ? "0.20" : "reserved")));
+                break;
+            case PRINT_TEXT:
+                fprintf(print_fh, "new stream mis %"PRIu8", %s, %sissyi, %snpd, ro %s\n",
+                        i_mis, b_ccm ? "ccm" : "acm",
+                        b_issyi ? "" : "no ",
+                        b_npd ? "" : "no ",
+                        i_ro == S2BBH_RO_35 ? "0.35" :
+                            (i_ro == S2BBH_RO_25 ? "0.25" :
+                                (i_ro == S2BBH_RO_20 ? "0.20" : "reserved")));
+                break;
+            default:
+                break;
+            }
+            p_current_mis->i_matype1 = p_bbframe[0];
+            p_current_mis->b_issy = b_issyi;
+            p_current_mis->b_npd = b_npd;
+            p_current_mis->i_upl = i_upl;
+        }
+
+        if ( i_syncd == UINT16_MAX / 8)
+        {
+            /* BBFrame without UP */
+            return;
+        }
+
+        if ( !p_current_mis->i_nb_outputs )
+        {
+            p_current_mis = NULL;
+            return;
+        }
+
+        p_bbframe += S2BBH_SIZE;
+        i_bbframe_size -= S2BBH_SIZE;
+
+        if ( (i_syncd + 1) % p_current_mis->i_upl !=
+             (p_current_mis->i_upl -
+              p_current_mis->i_up_size) % p_current_mis->i_upl )
+        {
+            msg_Warn( NULL, "fixed a BBframe disalignment (MIS %"PRIu8")",
+                      p_current_mis->i_mis );
+            p_current_mis->i_up_size = 0;
+            p_bbframe += i_syncd + 1;
+            i_bbframe_size -= i_syncd + 1;
+            i_current_mis_dfl -= i_syncd + 1;
+        }
+    }
+    else if ( p_current_mis == NULL )
+    {
+        /* Partial frame, abort */
+        return;
+    }
+    else if ( i_last_bbframe_counter + 1 != i_counter )
+    {
+        msg_Warn( NULL, "BBFrame discontinuity on MIS %"PRIu8" expected_counter %u got %u",
+                  p_current_mis->i_mis, i_last_bbframe_counter + 1,
+                  i_counter );
+        p_current_mis->i_up_size = 0;
+        p_current_mis = NULL;
+        return;
+    }
+    else
+        i_last_bbframe_counter = i_counter;
+
+    if ( i_bbframe_size > i_current_mis_dfl )
+    {
+        /* Remove padding */
+        i_bbframe_size = i_current_mis_dfl;
+    }
+
+    while ( p_current_mis->i_up_size + i_bbframe_size >= p_current_mis->i_upl )
+    {
+        /* Immediately output TS packet to avoid bursting issues */
+        uint16_t i_remainder = p_current_mis->i_upl - p_current_mis->i_up_size;
+        memcpy( p_current_mis->p_up + p_current_mis->i_up_size, p_bbframe,
+                i_remainder );
+        p_bbframe += i_remainder;
+        i_bbframe_size -= i_remainder;
+        i_current_mis_dfl -= i_remainder;
+        p_current_mis->i_up_size = 0;
+
+        block_t *p_ts = block_New();
+        p_ts->i_dts = i_dts;
+        p_ts->p_ts[0] = TS_SYNC;
+        memcpy( p_ts->p_ts + 1, p_current_mis->p_up, TS_SIZE - 1 );
+
+        /* Check CRC (last octet of UP after extra data) */
+        if ( s2bbcrc_check( p_current_mis->p_up, p_current_mis->i_upl - 1 )
+              != p_current_mis->p_up[p_current_mis->i_upl - 1] )
+            ts_set_transporterror( p_ts->p_ts );
+
+        for ( int i = 0; i < p_current_mis->i_nb_outputs; i++ )
+        {
+            output_t *p_output = p_current_mis->pp_outputs[i];
+
+            if ( p_output == NULL ||
+                 !(p_output->config.i_config & OUTPUT_VALID) )
+                continue;
+
+            output_Put( p_output, p_ts );
+        }
+
+        p_ts->i_refcount--;
+        if ( !p_ts->i_refcount )
+            block_Delete( p_ts );
+
+        if ( p_current_mis->b_npd )
+        {
+            /* Handle Null Packet Deletion */
+            uint8_t i_null_packets =
+                p_current_mis->p_up[p_current_mis->i_upl - 2];
+            if ( i_null_packets )
+            {
+                block_t *p_ts = block_New();
+                p_ts->i_dts = i_dts;
+                ts_pad( p_ts->p_ts );
+
+                while ( i_null_packets-- )
+                {
+                    for ( int i = 0; i < p_current_mis->i_nb_outputs; i++ )
+                    {
+                        output_t *p_output = p_current_mis->pp_outputs[i];
+
+                        if ( p_output == NULL ||
+                             !(p_output->config.i_config & OUTPUT_VALID) )
+                            continue;
+
+                        output_Put( p_output, p_ts );
+                    }
+                }
+
+                p_ts->i_refcount--;
+                if ( !p_ts->i_refcount )
+                    block_Delete( p_ts );
+            }
+        }
+    }
+
+    /* Copy the rest of the BBFrame to the temporary buffer */
+    if ( i_bbframe_size )
+    {
+        memcpy( p_current_mis->p_up + p_current_mis->i_up_size, p_bbframe,
+                i_bbframe_size );
+        p_current_mis->i_up_size += i_bbframe_size;
+        i_current_mis_dfl -= i_bbframe_size;
+    }
+}
+
 /*****************************************************************************
  * HandleSection
  *****************************************************************************/
@@ -3144,6 +3503,13 @@ static void HandleSection( uint16_t i_pid, uint8_t *p_section, mtime_t i_dts )
         return;
     }
 
+    if ( i_mis_is_id == -1 )
+    {
+        HandleBBFrameSection( p_section, i_dts );
+        free( p_section );
+        return;
+    }
+
     if ( !psi_get_current( p_section ) )
     {
         /* Ignore sections which are not in use yet. */


=====================================
dvb.c
=====================================
@@ -1,9 +1,9 @@
 /*****************************************************************************
  * dvb.c: linux-dvb input for DVBlast
  *****************************************************************************
- * Copyright (C) 2008-2010, 2015 VideoLAN
+ * Copyright (C) 2008-2010, 2015, 2025 VideoLAN
  *
- * Authors: Christophe Massiot <massiot at via.ecp.fr>
+ * Authors: Christophe Massiot <cmassiot at upipe.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -827,6 +827,23 @@ static fe_rolloff_t GetRollOff(void)
     }
 }
 
+static int GetSSI(void)
+{
+    if ( streq(psz_mis_pls_mode, "GOLD") )
+        return i_mis_pls_code;
+
+    /* ROOT mode */
+    uint32_t x, g;
+
+    for ( g = 0, x = 1; g < 0x3ffff; g++ )
+    {
+        if ( i_mis_pls_code == x )
+            return g;
+        x = (((x ^ (x >> 7)) & 1) << 17) | (x >> 1);
+    }
+    return 0xffffffff;
+}
+
 static fe_guard_interval_t GetGuard(void)
 {
     switch ( i_guard )
@@ -1006,19 +1023,21 @@ static struct dtv_properties dvbs_cmdseq = {
 #define IDX_DVBS2_PILOT     6
 #define IDX_DVBS2_ROLLOFF   7
 #define IDX_DVBS2_STREAM_ID 8
+#define IDX_DVBS2_SSI       9
 
 /* Commands 0..5 are the same as dvbs_cmdargs */
 /* Commands 6..8 are special for DVB-S2 */
 static struct dtv_property dvbs2_cmdargs[] = {
-    { .cmd = DTV_DELIVERY_SYSTEM, .u.data = SYS_DVBS2 },
-    { .cmd = DTV_FREQUENCY,       .u.data = 0 },
-    { .cmd = DTV_MODULATION,      .u.data = PSK_8 },
-    { .cmd = DTV_INVERSION,       .u.data = INVERSION_AUTO },
-    { .cmd = DTV_SYMBOL_RATE,     .u.data = 27500000 },
-    { .cmd = DTV_INNER_FEC,       .u.data = FEC_AUTO },
-    { .cmd = DTV_PILOT,           .u.data = PILOT_AUTO },   /* idx: 6 */
-    { .cmd = DTV_ROLLOFF,         .u.data = ROLLOFF_AUTO }, /* idx: 7 */
-    { .cmd = DTV_STREAM_ID,       .u.data = 0 },            /* idx: 8 */
+    { .cmd = DTV_DELIVERY_SYSTEM,           .u.data = SYS_DVBS2 },
+    { .cmd = DTV_FREQUENCY,                 .u.data = 0 },
+    { .cmd = DTV_MODULATION,                .u.data = PSK_8 },
+    { .cmd = DTV_INVERSION,                 .u.data = INVERSION_AUTO },
+    { .cmd = DTV_SYMBOL_RATE,               .u.data = 27500000 },
+    { .cmd = DTV_INNER_FEC,                 .u.data = FEC_AUTO },
+    { .cmd = DTV_PILOT,                     .u.data = PILOT_AUTO },   /* idx: 6 */
+    { .cmd = DTV_ROLLOFF,                   .u.data = ROLLOFF_AUTO }, /* idx: 7 */
+    { .cmd = DTV_STREAM_ID,                 .u.data = 0 },            /* idx: 8 */
+    { .cmd = DTV_SCRAMBLING_SEQUENCE_INDEX, .u.data = 0 },            /* idx: 9 */
     { .cmd = DTV_TUNE },
 };
 static struct dtv_properties dvbs2_cmdseq = {
@@ -1394,7 +1413,12 @@ static void FrontendSet( bool b_init )
             p->props[MODULATION].u.data = GetModulation();
             p->props[IDX_DVBS2_PILOT].u.data = GetPilot();
             p->props[IDX_DVBS2_ROLLOFF].u.data = GetRollOff();
-            p->props[IDX_DVBS2_STREAM_ID].u.data = i_mis;
+            if ( i_mis_pls_code )
+            {
+                p->props[IDX_DVBS2_STREAM_ID].u.data =
+                    i_mis_is_id != -1 ? i_mis_is_id : 0x80000000;
+                p->props[IDX_DVBS2_SSI].u.data = GetSSI();
+            }
         }
         else
             p = &dvbs_cmdseq;
@@ -1404,10 +1428,16 @@ static void FrontendSet( bool b_init )
         p->props[FEC_INNER].u.data = GetFECInner(info.caps);
         p->props[FREQUENCY].u.data = FrontendDoDiseqc();
 
-        msg_Dbg( NULL, "tuning DVB-S frontend to f=%d srate=%d inversion=%d fec=%d rolloff=%d modulation=%s pilot=%d mis=%d /pls-mode: %s (%d) pls-code: %d is-id: %d /",
-                 i_frequency, i_srate, i_inversion, i_fec, i_rolloff,
-                 psz_modulation == NULL ? "legacy" : psz_modulation, i_pilot,
-                 i_mis, psz_mis_pls_mode, i_mis_pls_mode, i_mis_pls_code, i_mis_is_id );
+        if ( i_mis_is_id == -1 )
+            msg_Dbg( NULL, "tuning DVB-S frontend in BBFrame mode to f=%d srate=%d inversion=%d fec=%d rolloff=%d modulation=%s pilot=%d pls-mode: %s pls-code: %d",
+                    i_frequency, i_srate, i_inversion, i_fec, i_rolloff,
+                    psz_modulation == NULL ? "legacy" : psz_modulation, i_pilot,
+                    psz_mis_pls_mode, i_mis_pls_code );
+        else
+            msg_Dbg( NULL, "tuning DVB-S frontend to f=%d srate=%d inversion=%d fec=%d rolloff=%d modulation=%s pilot=%d pls-mode: %s pls-code: %d is-id: %u",
+                    i_frequency, i_srate, i_inversion, i_fec, i_rolloff,
+                    psz_modulation == NULL ? "legacy" : psz_modulation, i_pilot,
+                    psz_mis_pls_mode, i_mis_pls_code, i_mis_is_id );
         break;
 
     case SYS_ATSC:


=====================================
dvblast.c
=====================================
@@ -1,9 +1,9 @@
 /*****************************************************************************
  * dvblast.c
  *****************************************************************************
- * Copyright (C) 2004, 2008-2011, 2015, 2020 VideoLAN
+ * Copyright (C) 2004, 2008-2011, 2015, 2020, 2025 VideoLAN
  *
- * Authors: Christophe Massiot <massiot at via.ecp.fr>
+ * Authors: Christophe Massiot <cmassiot at upipe.org>
  *          Andy Gatward <a.j.gatward at reading.ac.uk>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -81,9 +81,7 @@ int b_tone = 0;
 int i_bandwidth = 8;
 char *psz_modulation = NULL;
 int i_pilot = -1;
-int i_mis = 0;
 char *psz_mis_pls_mode = "ROOT";
-int i_mis_pls_mode = 0;
 int i_mis_pls_code = 0;
 int i_mis_is_id = 0;
 int i_fec_lp = 999;
@@ -159,6 +157,8 @@ void config_Init( output_config_t *p_config )
     p_config->i_if_index_v6 = -1;
     p_config->i_srcport = 0;
 
+    if ( i_mis_is_id == -1 )
+        p_config->i_sid = UINT16_MAX; /* sid is mis */
     p_config->pi_pids = NULL;
     p_config->b_passthrough = false;
     p_config->b_do_remap = false;
@@ -634,7 +634,7 @@ void usage()
         "[-u] [-w] [-U] [-L <latency>] [-E <retention>] [-d <dest IP>[<:port>][/<opts>]*] [-3] "
         "[-z] [-C [-e] [-M <network name>] [-N <network ID>]] [-T] [-j <system charset>] "
         "[-W] [-Y] [-l] [-g <logger ident>] [-Z <mrtg file>] [-V] [-h] [-B <provider_name>] "
-        "[-1 <mis_id>] [-2 <size>] [-5 <DVBS|DVBS2|DVBC_ANNEX_A|DVBC_ANNEX_B|DVBT|DVBT2|ATSC|ISDBT>] -y <ca_dev_number> "
+        "[-1] [-2 <size>] [-5 <DVBS|DVBS2|DVBC_ANNEX_A|DVBC_ANNEX_B|DVBT|DVBT2|ATSC|ISDBT>] -y <ca_dev_number> "
         "[-J <DVB charset>] [-Q <quit timeout>] [-0 pid_mapping] [-x <text|xml>]"
         "[-6 <print period>] [-7 <ES timeout>] [-4 <UDP lock timeout>]" );
 
@@ -667,7 +667,7 @@ void usage()
     msg_Raw( NULL, "  -P --pilot            DVB-S2 Pilot (-1 auto, 0 off, 1 on)" );
     msg_Raw( NULL, "  -R --rolloff          DVB-S2 Rolloff value" );
     msg_Raw( NULL, "    DVB-S2 35=0.35|25=0.25|20=0.20|0=AUTO (default: 35)" );
-    msg_Raw( NULL, "  -1 --multistream-id   Set stream ID (0-2147483648, default: 0)." );
+    msg_Raw( NULL, "  -1 --bbframe-demux    use raw BBframes to demultiplex MIS" );
     msg_Raw( NULL, "     --multistream-id-pls-mode   Set multistream PLS mode (ROOT, GOLD, COMBO, default: ROOT)" );
     msg_Raw( NULL, "     --multistream-id-pls-code   Set multistream PLS code (0-262143, default: 0)" );
     msg_Raw( NULL, "     --multistream-id-is-id      Set multistream IS id (0-255, default: 0)" );
@@ -771,7 +771,7 @@ int main( int i_argc, char **pp_argv )
         { "inversion",       required_argument, NULL, 'I' },
         { "modulation",      required_argument, NULL, 'm' },
         { "pilot",           required_argument, NULL, 'P' },
-        { "multistream-id",  required_argument, NULL, '1' },
+        { "bbframe-demux",   no_argument,       NULL, '1' },
         { "multistream-id-pls-mode",  required_argument, NULL, 0x100001 },
         { "multistream-id-pls-code",  required_argument, NULL, 0x100002 },
         { "multistream-id-is-id"   ,  required_argument, NULL, 0x100003 },
@@ -817,7 +817,7 @@ int main( int i_argc, char **pp_argv )
         { 0, 0, 0, 0 }
     };
 
-    while ( (c = getopt_long(i_argc, pp_argv, "q::c:r:t:o:i:a:n:5:f:F:R:s:S:k:v:pb:I:m:P:K:G:H:X:O:uwUTL:E:d:3D:A:lg:zCWYeM:N:j:J:B:x:Q:6:7:4:hVZ:y:0:1:2:9:", long_options, NULL)) != -1 )
+    while ( (c = getopt_long(i_argc, pp_argv, "q::c:r:t:o:i:a:n:5:f:F:R:s:S:k:v:pb:I:m:P:K:G:H:X:O:uwUTL:E:d:3D:A:lg:zCWYeM:N:j:J:B:x:Q:6:7:4:hVZ:y:0:12:9:", long_options, NULL)) != -1 )
     {
         switch ( c )
         {
@@ -894,9 +894,11 @@ int main( int i_argc, char **pp_argv )
         case '5':
             psz_delsys = optarg;
             break;
+
         case '9':
             dvb_plp_id = strtol( optarg, NULL, 0 );
             break;
+
         case 'f':
             if (optarg && optarg[0] != '-')
                 i_frequency = strtol( optarg, NULL, 0 );
@@ -962,34 +964,41 @@ int main( int i_argc, char **pp_argv )
             break;
 
         case '1':
-            i_mis = strtol( optarg, NULL, 0 );
+            i_mis_is_id = -1;
+            /* intended pass-through */
+
+        case 'u':
+            b_budget_mode = 1;
             break;
 
         case 0x100001: // --multistream-id-pls-mode
             psz_mis_pls_mode = optarg;
-            if        ( streq( psz_mis_pls_mode, "ROOT" ) ) {
-                i_mis_pls_mode = 0;
-            } else if ( streq( psz_mis_pls_mode, "GOLD" ) ) {
-                i_mis_pls_mode = 1;
-            } else if ( streq( psz_mis_pls_mode, "COMBO" ) ) {
-                i_mis_pls_mode = 2;
-            } else {
-                msg_Err(NULL, "Invalid --multistream-id-pls-mode '%s', valid options are: ROOT GOLD COMBO", optarg);
+            if ( !streq(psz_mis_pls_mode, "ROOT") &&
+                 !streq(psz_mis_pls_mode, "GOLD") )
+            {
+                msg_Err(NULL, "Invalid --multistream-id-pls-mode '%s', valid options are: ROOT GOLD", optarg);
                 exit(1);
             }
             break;
 
         case 0x100002: // --multistream-id-pls-code
             i_mis_pls_code = strtol( optarg, NULL, 0 );
-            if ( i_mis_pls_code < 0 || i_mis_pls_code > 262143 ) {
+            if ( i_mis_pls_code < 0 || i_mis_pls_code > 262143 )
+            {
                 msg_Err(NULL, "ERROR: Invalid --multistream-id-pls-code '%s', valid options are: 0-262143", optarg);
                 exit(1);
             }
             break;
 
         case 0x100003: // --multistream-id-is-id
+            if ( i_mis_is_id == -1 )
+            {
+                msg_Err(NULL, "ERROR: --multistream-id-is-id is incompatible with --bbframe-demux");
+                exit(1);
+            }
             i_mis_is_id = strtol( optarg, NULL, 0 );
-            if ( i_mis_is_id < 0 || i_mis_is_id > 255 ) {
+            if ( i_mis_is_id < 0 || i_mis_is_id > 255 )
+            {
                 msg_Err(NULL, "ERROR: Invalid --multistream-id-is-id '%s', valid options are: 0-255", optarg);
                 exit(1);
             }
@@ -1015,10 +1024,6 @@ int main( int i_argc, char **pp_argv )
             i_hierarchy = strtol( optarg, NULL, 0 );
             break;
 
-        case 'u':
-            b_budget_mode = 1;
-            break;
-
         case 'w':
             b_select_pmts = !b_select_pmts;
             break;
@@ -1234,7 +1239,10 @@ int main( int i_argc, char **pp_argv )
     {
         case PRINT_XML:
             fprintf(print_fh, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
-            fprintf(print_fh, "<TS>\n");
+            if ( i_mis_is_id != -1 )
+                fprintf(print_fh, "<TS>\n");
+            else
+                fprintf(print_fh, "<MIS>\n");
             break;
         default:
             break;
@@ -1285,26 +1293,6 @@ int main( int i_argc, char **pp_argv )
 
     srand( time(NULL) * getpid() );
 
-    if ( i_mis_pls_mode || i_mis_pls_code || i_mis_is_id )
-    {
-        i_mis = calc_multistream_id( i_mis_pls_mode, i_mis_pls_code, i_mis_is_id );
-        msg_Info( NULL, "Calculating multistream-id using pls-mode: %s (%d) pls-code: %d is-id: %d. Resulting multistream-id: %d (0x%x)",
-            psz_mis_pls_mode, i_mis_pls_mode, i_mis_pls_code, i_mis_is_id, i_mis, i_mis );
-    }
-    else if ( i_mis )
-    {
-        i_mis_pls_mode = (i_mis >> 26) & 0x03;
-        i_mis_pls_code = (i_mis >> 8) & 0x3ffff;
-        i_mis_is_id    = i_mis & 0xff;
-        psz_mis_pls_mode =
-            i_mis_pls_mode == 0 ? "ROOT" :
-            i_mis_pls_mode == 1 ? "GOLD" :
-            i_mis_pls_mode == 2 ? "COMBO" : "UNKNOWN";
-
-        msg_Info( NULL, "Calculated multistream pls-mode: %s (%d) pls-code: %d is-id: %d from multistream-id: %d (0x%x)",
-            psz_mis_pls_mode, i_mis_pls_mode, i_mis_pls_code, i_mis_is_id, i_mis, i_mis );
-    }
-
     demux_Open();
 
     // init the mrtg logfile
@@ -1349,7 +1337,10 @@ int main( int i_argc, char **pp_argv )
     switch (i_print_type)
     {
     case PRINT_XML:
-        fprintf(print_fh, "</TS>\n");
+        if ( i_mis_is_id != -1 )
+            fprintf(print_fh, "</TS>\n");
+        else
+            fprintf(print_fh, "</MIS>\n");
         break;
     default:
         break;


=====================================
dvblast.h
=====================================
@@ -1,9 +1,9 @@
 /*****************************************************************************
  * dvblast.h
  *****************************************************************************
- * Copyright (C) 2004, 2008-2011, 2015-2016, 2020 VideoLAN
+ * Copyright (C) 2004, 2008-2011, 2015-2016, 2020,2025 VideoLAN
  *
- * Authors: Christophe Massiot <massiot at via.ecp.fr>
+ * Authors: Christophe Massiot <cmassiot at upipe.org>
  *          Andy Gatward <a.j.gatward at reading.ac.uk>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -235,13 +235,10 @@ extern int i_inversion;
 extern char *psz_modulation;
 extern int i_pilot;
 
-/* Multistream settings */
-extern int i_mis;          /* Calculated from the three settings bellow, if they are set */
-extern char *psz_mis_pls_mode; /* ROOT, GOLD, COMBO */
-extern int i_mis_pls_mode; /* ROOT - 0, GOLD - 1, COMBO - 2 */
+/* multistream settings */
+extern char *psz_mis_pls_mode; /* ROOT, GOLD */
 extern int i_mis_pls_code; /* 0 .. 262143 */
 extern int i_mis_is_id;    /* 0 .. 255 */
-#define calc_multistream_id( pls_mode, pls_code, is_id ) ( pls_mode << 26 | pls_code << 8 | is_id )
 
 extern int i_fec_lp;
 extern int i_guard;


=====================================
output.c
=====================================
@@ -472,7 +472,7 @@ static void output_Flush( output_t *p_output )
         if ( !p_packet->pp_blocks[i_block]->i_refcount )
             block_Delete( p_packet->pp_blocks[i_block] );
         else if ( b_do_remap || p_output->config.b_do_remap ) {
-            /* still referenced so re-instate the orignial pid if remapped */
+            /* still referenced so re-instate the original pid if remapped */
             block_t * p_block = p_packet->pp_blocks[i_block];
             if (p_block->tmp_pid != UNUSED_PID)
                 ts_set_pid( p_block->p_ts, p_block->tmp_pid );
@@ -604,10 +604,10 @@ output_t *output_Find( const output_config_t *p_config )
         if ( !(p_output->config.i_config & OUTPUT_VALID) ) continue;
 
         if ( p_config->i_family != p_output->config.i_family ||
-             memcmp( &p_config->connect_addr, &p_output->config.connect_addr,
-                     i_sockaddr_len ) ||
-             memcmp( &p_config->bind_addr, &p_output->config.bind_addr,
-                     i_sockaddr_len ) )
+            memcmp( &p_config->connect_addr, &p_output->config.connect_addr,
+                    i_sockaddr_len ) ||
+            memcmp( &p_config->bind_addr, &p_output->config.bind_addr,
+                    i_sockaddr_len ) )
             continue;
 
         if ( p_config->i_family == AF_INET6 &&



View it on GitLab: https://code.videolan.org/videolan/dvblast/-/compare/74b297310be8def45d8c890c19a88fff3b1bbeb9...b276f61a4fc8af671f90b02a62e69175de285041

-- 
View it on GitLab: https://code.videolan.org/videolan/dvblast/-/compare/74b297310be8def45d8c890c19a88fff3b1bbeb9...b276f61a4fc8af671f90b02a62e69175de285041
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the dvblast-devel mailing list