mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 13:00:26 -04:00 
			
		
		
		
	DATV: enhancement and fixes to DVBS2 external LDPC tool process. Implements #804
This commit is contained in:
		
							parent
							
								
									c575c02791
								
							
						
					
					
						commit
						233f512f9c
					
				| @ -197,7 +197,7 @@ bool DATVDemodSettings::deserialize(const QByteArray& data) | ||||
|         d.readS32(33, &m_maxBitflips, 0); | ||||
|         d.readString(34, &m_softLDPCToolPath, "/opt/install/sdrangel/bin/ldpctool"); | ||||
|         d.readS32(35, &tmp, 8); | ||||
|         m_softLDPCMaxTrials = tmp < 1 ? 1 : tmp > 8 ? 8 : tmp; | ||||
|         m_softLDPCMaxTrials = tmp < 1 ? 1 : tmp > m_softLDPCMaxMaxTrials ? m_softLDPCMaxMaxTrials : tmp; | ||||
| 
 | ||||
|         validateSystemConfiguration(); | ||||
| 
 | ||||
|  | ||||
| @ -106,6 +106,7 @@ struct DATVDemodSettings | ||||
|     uint16_t m_reverseAPIPort; | ||||
|     uint16_t m_reverseAPIDeviceIndex; | ||||
|     uint16_t m_reverseAPIChannelIndex; | ||||
|     static const int m_softLDPCMaxMaxTrials = 25; | ||||
| 
 | ||||
|     DATVDemodSettings(); | ||||
|     void resetToDefaults(); | ||||
|  | ||||
| @ -431,6 +431,10 @@ void DATVDemodSink::CleanUpDATVFramework(bool blnRelease) | ||||
|         { | ||||
|             delete (leansdr::s2_fecdec_soft<leansdr::llr_t,leansdr::llr_sb>*) r_fecdecsoft; | ||||
|         } | ||||
|         if(r_fecdechelper != nullptr) | ||||
|         { | ||||
|             delete (leansdr::s2_fecdec_helper<leansdr::llr_t,leansdr::llr_sb>*) r_fecdechelper; | ||||
|         } | ||||
| #endif | ||||
| 
 | ||||
|         if(p_deframer != nullptr) | ||||
| @ -442,7 +446,7 @@ void DATVDemodSink::CleanUpDATVFramework(bool blnRelease) | ||||
|         { | ||||
|             delete r_scope_symbols_dvbs2; | ||||
|         } | ||||
|     } | ||||
|     } // blnRelease
 | ||||
| 
 | ||||
|     m_objScheduler=nullptr; | ||||
| 
 | ||||
| @ -547,6 +551,7 @@ void DATVDemodSink::CleanUpDATVFramework(bool blnRelease) | ||||
|     p_s2_deinterleaver = nullptr; | ||||
|     r_fecdec = nullptr; | ||||
|     r_fecdecsoft = nullptr; | ||||
|     r_fecdechelper = nullptr; | ||||
|     p_deframer = nullptr; | ||||
|     r_scope_symbols_dvbs2 = nullptr; | ||||
| } | ||||
| @ -893,7 +898,7 @@ void DATVDemodSink::InitDATVS2Framework() | ||||
| 
 | ||||
|     m_blnDVBInitialized = false; | ||||
|     m_lngReadIQ = 0; | ||||
|     CleanUpDATVFramework(false); | ||||
|     CleanUpDATVFramework(true); | ||||
| 
 | ||||
|     qDebug()  << "DATVDemodSink::InitDATVS2Framework:" | ||||
|         <<  " Standard: " << m_settings.m_standard | ||||
| @ -1185,7 +1190,7 @@ void DATVDemodSink::InitDATVS2Framework() | ||||
|             *(leansdr::pipebuf< leansdr::fecframe<leansdr::llr_sb> > *) p_fecframes | ||||
|         ); | ||||
|         // Decode FEC-protected frames into plain BB frames.
 | ||||
|         r_fecdec = new leansdr::s2_fecdec_helper<leansdr::llr_t, leansdr::llr_sb>( | ||||
|         r_fecdechelper = new leansdr::s2_fecdec_helper<leansdr::llr_t, leansdr::llr_sb>( | ||||
|             m_objScheduler, | ||||
|             *(leansdr::pipebuf< leansdr::fecframe<leansdr::llr_sb> > *) p_fecframes, | ||||
|             *(leansdr::pipebuf<leansdr::bbframe> *) p_bbframes, | ||||
| @ -1193,8 +1198,8 @@ void DATVDemodSink::InitDATVS2Framework() | ||||
|             p_vbitcount, | ||||
|             p_verrcount) | ||||
|         ; | ||||
|         leansdr::s2_fecdec_helper<leansdr::llr_t, leansdr::llr_sb> *fecdec = (leansdr::s2_fecdec_helper<leansdr::llr_t, leansdr::llr_sb> *) r_fecdec; | ||||
|         const int nhelpers = 2; | ||||
|         leansdr::s2_fecdec_helper<leansdr::llr_t, leansdr::llr_sb> *fecdec = (leansdr::s2_fecdec_helper<leansdr::llr_t, leansdr::llr_sb> *) r_fecdechelper; | ||||
|         const int nhelpers = 4; | ||||
|         fecdec->nhelpers = nhelpers; | ||||
|         fecdec->must_buffer = false; | ||||
|         fecdec->max_trials = m_settings.m_softLDPCMaxTrials; | ||||
|  | ||||
| @ -225,6 +225,7 @@ private: | ||||
|     void *p_s2_deinterleaver; | ||||
|     void *r_fecdec; | ||||
|     void *r_fecdecsoft; | ||||
|     void *r_fecdechelper; | ||||
|     void *p_deframer; | ||||
| 
 | ||||
|     //DECIMATION
 | ||||
|  | ||||
| @ -19,6 +19,7 @@ | ||||
| #include <QFileDialog> | ||||
| 
 | ||||
| #include "datvdvbs2ldpcdialog.h" | ||||
| #include "datvdemodsettings.h" | ||||
| #include "ui_datvdvbs2ldpcdialog.h" | ||||
| 
 | ||||
| DatvDvbS2LdpcDialog::DatvDvbS2LdpcDialog(QWidget* parent) : | ||||
| @ -46,7 +47,8 @@ void DatvDvbS2LdpcDialog::setFileName(const QString& fileName) | ||||
| 
 | ||||
| void DatvDvbS2LdpcDialog::setMaxTrials(int maxTrials) | ||||
| { | ||||
|     m_maxTrials = maxTrials < 1 ? 1 : maxTrials > 8 ? 8 : maxTrials; | ||||
|     m_maxTrials = maxTrials < 1 ? 1 : | ||||
|         maxTrials > DATVDemodSettings::m_softLDPCMaxMaxTrials ? DATVDemodSettings::m_softLDPCMaxMaxTrials : maxTrials; | ||||
|     ui->maxTrials->setValue(m_maxTrials); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -31,11 +31,17 @@ | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="QSpinBox" name="maxTrials"> | ||||
|        <property name="minimumSize"> | ||||
|         <size> | ||||
|          <width>55</width> | ||||
|          <height>0</height> | ||||
|         </size> | ||||
|        </property> | ||||
|        <property name="minimum"> | ||||
|         <number>1</number> | ||||
|        </property> | ||||
|        <property name="maximum"> | ||||
|         <number>8</number> | ||||
|         <number>25</number> | ||||
|        </property> | ||||
|        <property name="displayIntegerBase"> | ||||
|         <number>10</number> | ||||
|  | ||||
| @ -136,6 +136,10 @@ int main(int argc, char **argv) | ||||
| 	if (sizeof(ldpctool::code_type) != 1) | ||||
| 		fail("Bug: Unsupported code_type"); | ||||
| 
 | ||||
| 	int trials_count = 0; | ||||
| 	int max_count = 0; | ||||
| 	int num_decodes = 0; | ||||
| 
 | ||||
| 	while (true) | ||||
| 	{ | ||||
| 		ssize_t iosize = BLOCKS * CODE_LEN * sizeof(*code); | ||||
| @ -153,8 +157,6 @@ int main(int argc, char **argv) | ||||
| 			pos += nr; | ||||
| 		} | ||||
| 
 | ||||
| 		int iterations = 0; | ||||
| 		int num_decodes = 0; | ||||
| 
 | ||||
| 		for (int j = 0; j < BLOCKS; j += ldpctool::SIMD_WIDTH) | ||||
| 		{ | ||||
| @ -164,24 +166,31 @@ int main(int argc, char **argv) | ||||
| 				for (int i = 0; i < CODE_LEN; ++i) | ||||
| 					reinterpret_cast<ldpctool::code_type *>(simd + i)[n] = code[(j + n) * CODE_LEN + i]; | ||||
| 
 | ||||
| 			int trials = max_trials; | ||||
| 			int count = decode(simd, simd + DATA_LEN, trials, blocks); | ||||
| 			++num_decodes; | ||||
| 			int count = decode(simd, simd + DATA_LEN, max_trials, blocks); | ||||
| 			num_decodes++; | ||||
| 
 | ||||
| 			if (count < 0) | ||||
| 			{ | ||||
| 				trials_count += max_trials; | ||||
| 				max_count++; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				trials_count += max_trials - count; | ||||
| 			} | ||||
| 
 | ||||
| 			if (num_decodes == 20) | ||||
| 			{ | ||||
| 				fprintf(stderr, "ldpc_tool: trials: %d%% max: %d%% at converging to a code word\n", | ||||
| 					(trials_count*100)/(num_decodes*max_trials), (max_count*100)/num_decodes); | ||||
| 				trials_count = 0; | ||||
| 				max_count = 0; | ||||
| 				num_decodes = 0; | ||||
| 			} | ||||
| 
 | ||||
| 			for (int n = 0; n < blocks; ++n) | ||||
| 				for (int i = 0; i < CODE_LEN; ++i) | ||||
| 					code[(j + n) * CODE_LEN + i] = reinterpret_cast<ldpctool::code_type *>(simd + i)[n]; | ||||
| 
 | ||||
| 			if (count < 0) | ||||
| 			{ | ||||
| 				iterations += blocks * trials; | ||||
| 				std::cerr << "ldpc_tool: decoder failed at converging to a code word in " << trials << " trials" << std::endl; | ||||
| 				break; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				iterations += blocks * (trials - count); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		for (int i = 0; i < BLOCKS * CODE_LEN; ++i) | ||||
|  | ||||
| @ -37,6 +37,8 @@ | ||||
| #include "sdr.h" | ||||
| 
 | ||||
| #ifdef LINUX | ||||
| #include <signal.h> | ||||
| #include <sys/wait.h> | ||||
| #include "ldpctool/layered_decoder.h" | ||||
| #include "ldpctool/testbench.h" | ||||
| #include "ldpctool/algorithms.h" | ||||
| @ -2379,6 +2381,7 @@ struct s2_fecdec_helper : runnable | ||||
|     ~s2_fecdec_helper() | ||||
|     { | ||||
|         free(command); | ||||
|         killall(); | ||||
|     } | ||||
| 
 | ||||
|     void run() | ||||
| @ -2424,6 +2427,7 @@ struct s2_fecdec_helper : runnable | ||||
|         int batch_size; // Latency
 | ||||
|         int b_in;       // Jobs in input queue
 | ||||
|         int b_out;      // Jobs in output queue
 | ||||
|         int pid;        // PID of the child
 | ||||
|     }; | ||||
|     struct pool | ||||
|     { | ||||
| @ -2451,10 +2455,13 @@ struct s2_fecdec_helper : runnable | ||||
|             int nw = write(h->fd_tx, pin->bytes, iosize); | ||||
| 
 | ||||
|             if (nw < 0 && errno == EWOULDBLOCK) | ||||
|             { | ||||
|                 lseek(h->fd_tx, 0, SEEK_SET); // allow new writes on this worker
 | ||||
|                 continue; // next worker
 | ||||
|             } | ||||
|             if (nw < 0) | ||||
|                 fatal("write(LDPC helper"); | ||||
|             if (nw != iosize) | ||||
|             else if (nw != iosize) | ||||
|                 fatal("partial write(LDPC helper)"); | ||||
| 
 | ||||
|             helper_job *job = jobs.put(); | ||||
| @ -2471,9 +2478,9 @@ struct s2_fecdec_helper : runnable | ||||
|             return true; // done sent to worker
 | ||||
|         } | ||||
| 
 | ||||
|         fprintf(stderr, "s2_fecdec_helper::send_frame: WARNING: all %d workers are busy: modcod=%d sf=%d)\n", | ||||
|         fprintf(stderr, "s2_fecdec_helper::send_frame: WARNING: all %d workers were busy: modcod=%d sf=%d)\n", | ||||
|             p->nprocs, pin->pls.modcod, pin->pls.sf); | ||||
|         return false; // all workers are busy
 | ||||
|         return false; // all workers were busy
 | ||||
|     } | ||||
| 
 | ||||
|     // Return a pool of running helpers for a given modcod.
 | ||||
| @ -2494,6 +2501,42 @@ struct s2_fecdec_helper : runnable | ||||
|         return p; | ||||
|     } | ||||
| 
 | ||||
|     void killall() | ||||
|     { | ||||
|         fprintf(stderr, "s2_fecdec_helper::killall\n"); | ||||
| 
 | ||||
|         for (int i = 0; i < 32; i++) // all MODCODs
 | ||||
|         { | ||||
|             for (int j = 0; j < 2; j++) // long and short frames
 | ||||
|             { | ||||
|                 pool *p = &pools[i][j]; | ||||
| 
 | ||||
|                 if (p->procs) | ||||
|                 { | ||||
|                     for (int i = 0; i < p->nprocs; ++i) | ||||
|                     { | ||||
|                         helper_instance *h = &p->procs[i]; | ||||
|                         fprintf(stderr, "s2_fecdec_helper::killall: killing %d\n", h->pid); | ||||
|                         int rc = kill(h->pid, SIGKILL); | ||||
|                         if (rc < 0) { | ||||
|                             fatal("s2_fecdec_helper::killall"); | ||||
|                         } else { | ||||
|                             int cs; | ||||
|                             waitpid(h->pid, &cs, 0); | ||||
|                         } | ||||
|                         // reset pipes
 | ||||
|                         lseek(h->fd_tx, 0, SEEK_SET); | ||||
|                         lseek(h->fd_rx, 0, SEEK_SET); | ||||
|                     } | ||||
| 
 | ||||
|                     delete p->procs; | ||||
|                     p->procs = nullptr; | ||||
|                     p->nprocs = 0; | ||||
|                 } | ||||
|             } // long and short frames
 | ||||
|         } // all MODCODs
 | ||||
|     } | ||||
| 
 | ||||
|     // Spawn a helper process.
 | ||||
|     void spawn_helper(helper_instance *h, const s2_pls *pls) | ||||
|     { | ||||
| @ -2507,19 +2550,31 @@ struct s2_fecdec_helper : runnable | ||||
| // macOS does not have F_SETPIPE_SZ and there
 | ||||
| // is no way to change the buffer size
 | ||||
| #ifndef __APPLE__ | ||||
|         if (fcntl(tx[0], F_SETPIPE_SZ, pipesize) < 0 || | ||||
|             fcntl(rx[0], F_SETPIPE_SZ, pipesize) < 0 || | ||||
|             fcntl(tx[1], F_SETPIPE_SZ, pipesize) < 0 || | ||||
|             fcntl(rx[1], F_SETPIPE_SZ, pipesize) < 0) | ||||
|         long min_pipe_size = (long) fcntl(tx[0], F_GETPIPE_SZ); | ||||
|         long pipe_size = (long) fcntl(rx[0], F_GETPIPE_SZ); | ||||
|         min_pipe_size = std::min(min_pipe_size, pipe_size); | ||||
|         pipe_size = (long) fcntl(tx[1], F_GETPIPE_SZ); | ||||
|         min_pipe_size = std::min(min_pipe_size, pipe_size); | ||||
|         pipe_size = (long) fcntl(rx[1], F_GETPIPE_SZ); | ||||
|         min_pipe_size = std::min(min_pipe_size, pipe_size); | ||||
| 
 | ||||
|         if (min_pipe_size < pipesize) | ||||
|         { | ||||
|             fprintf(stderr, | ||||
|                     "*** Failed to increase pipe size.\n" | ||||
|                     "*** Try echo %d > /proc/sys/fs/pipe-max-size\n", | ||||
|                     pipesize); | ||||
|             if (must_buffer) | ||||
|                 fatal("F_SETPIPE_SZ"); | ||||
|             else | ||||
|                 fprintf(stderr, "*** Throughput will be suboptimal.\n"); | ||||
|             if (fcntl(tx[0], F_SETPIPE_SZ, pipesize) < 0 || | ||||
|                 fcntl(rx[0], F_SETPIPE_SZ, pipesize) < 0 || | ||||
|                 fcntl(tx[1], F_SETPIPE_SZ, pipesize) < 0 || | ||||
|                 fcntl(rx[1], F_SETPIPE_SZ, pipesize) < 0) | ||||
|             { | ||||
|                 fprintf(stderr, | ||||
|                         "*** Failed to increase pipe size from %ld.\n" | ||||
|                         "*** Try echo %d > /proc/sys/fs/pipe-max-size\n", | ||||
|                         min_pipe_size, | ||||
|                         pipesize); | ||||
|                 if (must_buffer) | ||||
|                     fatal("F_SETPIPE_SZ"); | ||||
|                 else | ||||
|                     fprintf(stderr, "*** Throughput will be suboptimal.\n"); | ||||
|             } | ||||
|         } | ||||
| #endif | ||||
|         // vfork() differs from fork(2) in that the calling thread is
 | ||||
| @ -2552,15 +2607,19 @@ struct s2_fecdec_helper : runnable | ||||
|             fatal(command); | ||||
|         } | ||||
| 
 | ||||
|         h->pid = child; | ||||
|         h->fd_tx = tx[1]; | ||||
|         close(tx[0]); | ||||
|         h->fd_rx = rx[0]; | ||||
|         close(rx[1]); | ||||
|         h->batch_size = batch_size; // TBD
 | ||||
|         h->b_in = h->b_out = 0; | ||||
|         int flags = fcntl(h->fd_tx, F_GETFL); | ||||
|         if (fcntl(h->fd_tx, F_SETFL, flags | O_NONBLOCK)) | ||||
|             fatal("fcntl(helper)"); | ||||
|         int flags_tx = fcntl(h->fd_tx, F_GETFL); | ||||
|         if (fcntl(h->fd_tx, F_SETFL, flags_tx | O_NONBLOCK)) | ||||
|             fatal("fcntl_tx(helper)"); | ||||
|         int flags_rx = fcntl(h->fd_rx, F_GETFL); | ||||
|         if (fcntl(h->fd_rx, F_SETFL, flags_rx | O_NONBLOCK)) | ||||
|             fatal("fcntl_rx(helper)"); | ||||
|     } | ||||
| 
 | ||||
|     // Receive a finished job.
 | ||||
| @ -2570,10 +2629,18 @@ struct s2_fecdec_helper : runnable | ||||
|         const s2_pls *pls = &job->pls; | ||||
|         int iosize = (pls->framebits() / 8) * sizeof(ldpc_buf[0]); | ||||
|         int nr = read(job->h->fd_rx, ldpc_buf, iosize); | ||||
| 
 | ||||
|         if (nr < 0) | ||||
|             fatal("read(LDPC helper)"); | ||||
|         if (nr != iosize) | ||||
|             fatal("partial read(LDPC helper)"); | ||||
|         { | ||||
|             if (errno != EAGAIN) { // if no data then try again next time
 | ||||
|                 fatal("s2_fecdec_helper::receive_frame read error"); | ||||
|             } | ||||
|         } | ||||
|         else if (nr != iosize) | ||||
|         { | ||||
|             fprintf(stderr, "s2_fecdec_helper::receive_frame: %d bytes read vs %d", nr, iosize); | ||||
|         } | ||||
| 
 | ||||
|         --job->h->b_out; | ||||
|         // Decode BCH.
 | ||||
|         const modcod_info *mcinfo = check_modcod(job->pls.modcod); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user