mirror of
https://github.com/outbackdingo/UltraGrid.git
synced 2026-04-06 15:04:57 +00:00
fixed the same commit 43ba6b4e as before The reference was used instead of iterator, but the reference cannot be reused because the second assignment overrides the original node contents instead of working on the second node.
413 lines
12 KiB
C++
413 lines
12 KiB
C++
/*
|
|
* =====================================================================================
|
|
*
|
|
* Filename: ldgm-session.cpp
|
|
*
|
|
* Description:
|
|
*
|
|
* Version: 1.0
|
|
* Created: 04/12/2012 01:03:23 PM
|
|
* Revision: none
|
|
* Compiler: gcc
|
|
*
|
|
* Author: Milan Kabat (), kabat@ics.muni.cz
|
|
* Organization:
|
|
*
|
|
* =====================================================================================
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <map>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <string.h>
|
|
#include "ldgm-session.h"
|
|
#include "timer-util.h"
|
|
|
|
constexpr const int MAX_W = 128;
|
|
|
|
using namespace std;
|
|
|
|
/*
|
|
*--------------------------------------------------------------------------------------
|
|
* Class: LDGM_session
|
|
* Method: LDGM_session
|
|
* Description: constructor
|
|
*--------------------------------------------------------------------------------------
|
|
*/
|
|
void
|
|
LDGM_session::set_pcMatrix ( char* fname)
|
|
{
|
|
FILE *f;
|
|
|
|
f = fopen(fname, "rb");
|
|
if (!f)
|
|
{
|
|
printf ( "Error opening matrix file\n" );
|
|
printf ( "exiting\n" );
|
|
abort();
|
|
}
|
|
unsigned int k_f, m_f, w_f;
|
|
if (fscanf(f, "%d %d %d", &k_f, &m_f, &w_f) != 3) {
|
|
throw string("Parity matrix read error!");
|
|
}
|
|
// printf ( "In matrix file: K %d M %d Columns %d\n", k_f, m_f, w_f );
|
|
|
|
if (w_f < 2 || w_f > MAX_W) {
|
|
throw string("Invalid parameter in parity matrix (allowed range [2.." + to_string(MAX_W) + "])!");
|
|
}
|
|
|
|
if ( k_f != param_k || m_f != param_m)
|
|
{
|
|
ostringstream oss;
|
|
oss << "Parity matrix size mismatch\nExpected K = " << param_k << "% M = " << param_m <<
|
|
"\nReceived K = " << k_f << ", M = " << m_f << "\n";
|
|
throw oss.str();
|
|
}
|
|
if (fseek (f, 1, SEEK_CUR ) != 0) {
|
|
perror("fseek");
|
|
}
|
|
|
|
pcm = (int*) malloc(w_f*param_m*sizeof(int));
|
|
for ( int i = 0; i < (int)w_f*param_m; i++) {
|
|
if (fread ( pcm+i, sizeof(int), 1, f) != 1) {
|
|
throw string("Parity matrix read error!");
|
|
}
|
|
}
|
|
this->max_row_weight = w_f - 2; //w_f stores number of columns in adjacency list
|
|
|
|
/* for ( int i = 0; i < param_m; i++)
|
|
* {
|
|
* for ( int j = 0; j < w_f; j++)
|
|
* printf ( "[%3d]", (unsigned int)(pcm[i*w_f+j]) );
|
|
* printf ( "\n" );
|
|
* }
|
|
*/
|
|
|
|
|
|
|
|
|
|
fclose(f);
|
|
|
|
|
|
|
|
/*
|
|
* this->max_row_weight = 0;
|
|
* int max_weight = 0;
|
|
* for ( int i = 0; i < param_m; ++i) {
|
|
* for ( int j = 0; j < param_k; ++j) {
|
|
* if(*(matrix + i*param_k + j) == 1) {
|
|
* *(pcMatrix + i*param_k + j) = *(matrix + i*param_k + j);
|
|
* max_weight++;
|
|
* }
|
|
* }
|
|
* if ( max_weight > this->max_row_weight )
|
|
* this->max_row_weight = max_weight;
|
|
* max_weight = 0;
|
|
* }
|
|
*
|
|
* pcm = (int*) malloc (m*(max_row_weight+2)*sizeof(int*));
|
|
* struct coding_params params;
|
|
* params.m = m;
|
|
* params.k = k;
|
|
* params.max_row_weight = max_row_weight;
|
|
*
|
|
* make_compact_pcm ( matrix, pcm, params);
|
|
*/
|
|
|
|
|
|
return ;
|
|
} /* ----- end of method Coding_session::set_pcMatrix ----- */
|
|
|
|
char*
|
|
LDGM_session::encode_frame ( char* frame, int frame_size, int* out_buf_size )
|
|
{
|
|
//printf("encode_frame\n");
|
|
Timer_util interval;
|
|
interval.start();
|
|
|
|
int buf_size;
|
|
int ps;
|
|
short header_size = LDGM_session::HEADER_SIZE;
|
|
int align_coef = param_k*sizeof(int);
|
|
|
|
if ( (frame_size + header_size) % align_coef == 0 )
|
|
buf_size = frame_size + header_size;
|
|
else
|
|
buf_size = ( ( (frame_size + header_size) / align_coef ) + 1 ) * align_coef;
|
|
|
|
ps = buf_size/param_k;
|
|
|
|
packet_size = ps;
|
|
//printf ( "ps: %d\n", ps );
|
|
buf_size += param_m*ps;
|
|
*out_buf_size = buf_size;
|
|
|
|
void *out_buf;
|
|
out_buf = alloc_buf(buf_size);
|
|
if (!out_buf)
|
|
{
|
|
printf ( "Unable to allocate memory\n" );
|
|
return NULL;
|
|
}
|
|
memset(out_buf, 0, header_size);
|
|
memset((char*)out_buf + frame_size + header_size, 0, align_coef);
|
|
|
|
//Insert frame size and copy input data into buffer
|
|
|
|
int *hdr = (int*)out_buf;
|
|
*hdr = frame_size;
|
|
|
|
memcpy( ((char*)out_buf) + header_size, frame, frame_size);
|
|
|
|
//Timer_util t;
|
|
//printf("2buf_size %d\n",buf_size);
|
|
//printf("2packet_size %d\n",packet_size);
|
|
this->encode ( (char*)out_buf, ((char*)out_buf)+param_k*ps );
|
|
|
|
|
|
interval.end();
|
|
// printf("time: %e\n",elapsed/1000.0 );
|
|
this->elapsed_sum2 += interval.elapsed_time_ms();
|
|
this->no_frames2++;
|
|
|
|
return (char*)out_buf;
|
|
|
|
// printf ( "SSE: %.3lf\n", t.elapsed_time(start, end) );
|
|
|
|
/* void *out_buf_check;
|
|
* error = posix_memalign(&out_buf_check, 16, buf_size);
|
|
* memset(out_buf_check, 0, buf_size);
|
|
* hdr = (int*)out_buf_check;
|
|
* *hdr = frame_size;
|
|
* memcpy(((char*)out_buf_check)+header_size, frame, frame_size);
|
|
* clock_gettime(CLOCK_MONOTONIC, &start);
|
|
* encode_naive ( (char*)out_buf, ((char*)out_buf_check)+param_k*ps );
|
|
* clock_gettime(CLOCK_MONOTONIC, &end);
|
|
* printf ( "CPU: %.3lf\n", t.elapsed_time(start, end) );
|
|
*
|
|
* int e = memcmp(out_buf, out_buf_check, buf_size);
|
|
* printf ( "memcpy on parities: %d\n", e );
|
|
* char *a = (char*)out_buf;
|
|
* char *b = (char*)out_buf_check;
|
|
* bool equal = true;
|
|
* int idx = 0;
|
|
* for ( int i = 0; i < param_m*ps; i++)
|
|
* {
|
|
* if(a[i] != b[i])
|
|
* {
|
|
* idx = i;
|
|
* printf ( "Error at index %d: %d vs %d\n", i, (unsigned char)a[i],
|
|
* (unsigned char)b[i] );
|
|
* equal = false;
|
|
* }
|
|
* }
|
|
*
|
|
* printf ( "Parities %s match.\n", (equal)?"":"do not" );
|
|
*/
|
|
|
|
// printf ( "\n\nEncoded block:\n" );
|
|
// printf ( "%-13s\v%10d B\n", "Frame hdr size:", header_size );
|
|
// printf ( "%-13s\v%10d B\n", "Frame size:", frame_size );
|
|
// printf ( "Padding size:\t%-d B\n", buf_size-frame_size-header_size-param_m*ps );
|
|
// printf ( "Parity size:\t%-d B\n", param_m*ps );
|
|
// printf ( "-------------------------------\n");
|
|
// printf ( "Total block size:\t%d B\n", buf_size );
|
|
// printf ( "Symbol size:\t%d\n\n\n", ps );
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
char*
|
|
LDGM_session::encode_hdr_frame ( char *my_hdr, int my_hdr_size, char* frame, int frame_size, int* out_buf_size )
|
|
{
|
|
int buf_size;
|
|
int ps;
|
|
short header_size = LDGM_session::HEADER_SIZE;
|
|
int overall_size = my_hdr_size + frame_size;
|
|
int align_coef = param_k*sizeof(int);
|
|
|
|
if ( (overall_size + header_size) % align_coef == 0 )
|
|
buf_size = overall_size + header_size;
|
|
else
|
|
buf_size = ( ( (overall_size + header_size) / align_coef ) + 1 ) * align_coef;
|
|
|
|
ps = buf_size/param_k;
|
|
|
|
packet_size = ps;
|
|
// printf ( "ps: %d\n", ps );
|
|
buf_size += param_m*ps;
|
|
*out_buf_size = buf_size;
|
|
|
|
void *out_buf;
|
|
out_buf = alloc_buf(buf_size);
|
|
if (!out_buf)
|
|
{
|
|
printf ( "Unable to allocate aligned memory\n" );
|
|
return NULL;
|
|
}
|
|
memset(out_buf, 0, buf_size);
|
|
|
|
//Insert frame size and copy input data into buffer
|
|
|
|
int32_t *hdr = (int32_t*)out_buf;
|
|
*hdr = overall_size;
|
|
|
|
memcpy( ((char*)out_buf) + header_size, my_hdr, my_hdr_size);
|
|
memcpy( ((char*)out_buf) + header_size + my_hdr_size, frame, frame_size);
|
|
|
|
#if 0
|
|
int my_frame_size=my_hdr_size+frame_size;
|
|
|
|
// printf("my_frame_size: %d\n",my_frame_size );
|
|
|
|
int crc;
|
|
crc = crc32buf((char*)out_buf+header_size,my_frame_size);
|
|
|
|
memcpy( ((char*)out_buf) + 4, &crc, 4);
|
|
memcpy( ((char*)out_buf) + 8, &my_frame_size, 4);
|
|
assert(LDGM_session::HEADER_SIZE >= 12);
|
|
#endif
|
|
|
|
Timer_util interval;
|
|
interval.start();
|
|
|
|
this->encode ( (char*)out_buf, ((char*)out_buf)+param_k*ps );
|
|
|
|
interval.end();
|
|
long elapsed;
|
|
|
|
elapsed = interval.elapsed_time_us();
|
|
// printf("time: %e\n",elapsed/1000.0 );
|
|
this->elapsed_sum2+=elapsed/1000.0;
|
|
this->no_frames2++;
|
|
|
|
|
|
// gettimeofday(&t1,0);
|
|
// long elapsed;
|
|
|
|
// elapsed = (t1.tv_sec-t0.tv_sec)*1000000 + t1.tv_usec-t0.tv_usec;
|
|
// // printf("time: %e\n",elapsed/1000.0 );
|
|
// this->elapsed_sum2+=elapsed/1000.0;
|
|
// this->no_frames2++;
|
|
// i++;
|
|
|
|
// if(i%100==0){
|
|
// printf("TIME GPU: %f ms\n",this->elapsed_sum2/(double)this->no_frames2 );
|
|
// printf("time: %f ms\n",elapsed/1000.0 );
|
|
// }
|
|
|
|
// printf ( "SSE: %.3lf\n", t.elapsed_time(start, end) );
|
|
|
|
/* void *out_buf_check;
|
|
* error = posix_memalign(&out_buf_check, 16, buf_size);
|
|
* memset(out_buf_check, 0, buf_size);
|
|
* hdr = (int*)out_buf_check;
|
|
* *hdr = frame_size;
|
|
* memcpy(((char*)out_buf_check)+header_size, frame, frame_size);
|
|
* clock_gettime(CLOCK_MONOTONIC, &start);
|
|
* encode_naive ( (char*)out_buf, ((char*)out_buf_check)+param_k*ps );
|
|
* clock_gettime(CLOCK_MONOTONIC, &end);
|
|
* printf ( "CPU: %.3lf\n", t.elapsed_time(start, end) );
|
|
*
|
|
* int e = memcmp(out_buf, out_buf_check, buf_size);
|
|
* printf ( "memcpy on parities: %d\n", e );
|
|
* char *a = (char*)out_buf;
|
|
* char *b = (char*)out_buf_check;
|
|
* bool equal = true;
|
|
* int idx = 0;
|
|
* for ( int i = 0; i < param_m*ps; i++)
|
|
* {
|
|
* if(a[i] != b[i])
|
|
* {
|
|
* idx = i;
|
|
* printf ( "Error at index %d: %d vs %d\n", i, (unsigned char)a[i],
|
|
* (unsigned char)b[i] );
|
|
* equal = false;
|
|
* }
|
|
* }
|
|
*
|
|
* printf ( "Parities %s match.\n", (equal)?"":"do not" );
|
|
*/
|
|
|
|
// printf ( "\n\nEncoded block:\n" );
|
|
// printf ( "%-13s\v%10d B\n", "Frame hdr size:", header_size );
|
|
// printf ( "%-13s\v%10d B\n", "Frame size:", frame_size );
|
|
// printf ( "Padding size:\t%-d B\n", buf_size-frame_size-header_size-param_m*ps );
|
|
// printf ( "Parity size:\t%-d B\n", param_m*ps );
|
|
// printf ( "-------------------------------\n");
|
|
// printf ( "Total block size:\t%d B\n", buf_size );
|
|
// printf ( "Symbol size:\t%d\n\n\n", ps );
|
|
|
|
|
|
return (char*)out_buf;
|
|
|
|
}
|
|
|
|
/*
|
|
* === FUNCTION ======================================================================
|
|
* Name: create_edges
|
|
* Description:
|
|
* =====================================================================================
|
|
*/
|
|
void
|
|
LDGM_session::create_edges ( Tanner_graph *graph )
|
|
{
|
|
// printf ( "graph: %p, param_k: %d, param_m: %d\n", graph, param_k, param_m );
|
|
for ( int m = 0; m < param_m; ++m) {
|
|
for ( int k = 0; k < max_row_weight+2; ++k ) {
|
|
int idx = pcm [ m*(max_row_weight+2) + k];
|
|
if( idx > -1 ) {
|
|
auto &node = graph->nodes.at(idx);
|
|
node.neighbours.push_back(param_k + param_m + m);
|
|
auto &n2 = graph->nodes.at(param_k + param_m + m);
|
|
n2.neighbours.push_back(idx);
|
|
}
|
|
}
|
|
}
|
|
/* it = graph->nodes.find(0);
|
|
* while ( it != graph->nodes.end() )
|
|
* {
|
|
* printf ( "\nneighbours of node %d: ", it->first );
|
|
* for (vector<int>::iterator i = it->second.neighbours.begin();
|
|
* i != it->second.neighbours.end(); ++i)
|
|
* printf ( "%d, ", *i );
|
|
* it++;
|
|
* }
|
|
*/
|
|
|
|
//add edges representing the staircase matrix
|
|
/* for ( int i = param_k + param_m; i < param_k + 2*param_m; ++i) {
|
|
* it = graph->nodes.find(i);
|
|
* (*it).second.neighbours.push_back(i - param_m);
|
|
* it = graph->nodes.find(i - param_m);
|
|
* (*it).second.neighbours.push_back(i);
|
|
* if(i > param_m + param_k) {
|
|
* it = graph->nodes.find(i);
|
|
* (*it).second.neighbours.push_back(i - param_m - 1);
|
|
* it = graph->nodes.find(i - param_m - 1);
|
|
* (*it).second.neighbours.push_back(i);
|
|
* }
|
|
* }
|
|
*/
|
|
return ;
|
|
} /* ----- end of function create_edges ----- */
|
|
|
|
bool
|
|
LDGM_session::needs_decoding ( Tanner_graph *graph )
|
|
{
|
|
for ( int i = 0; i < param_k; i++)
|
|
if( ! graph->nodes.at(i).isDone() ) {
|
|
return true;
|
|
}
|
|
return false;
|
|
} /* ----- end of method LDGM_session::needs_decoding ----- */
|
|
|
|
|
|
LDGM_session::~LDGM_session() {
|
|
free(pcm);
|
|
}
|