mirror of
https://github.com/outbackdingo/UltraGrid.git
synced 2026-03-21 12:40:19 +00:00
407 lines
12 KiB
C++
407 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 "crypto/crc.h"
|
|
#include "ldgm-session.h"
|
|
#include "timer-util.h"
|
|
|
|
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 ( 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, buf_size);
|
|
|
|
//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_us();
|
|
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 )
|
|
{
|
|
map<int, Node>::iterator it;
|
|
// 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 ) {
|
|
it = graph->nodes.find(idx);
|
|
(*it).second.neighbours.push_back(param_k + param_m + m);
|
|
it = graph->nodes.find(param_k + param_m + m);
|
|
(*it).second.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.find(i)->second.isDone() )
|
|
return true;
|
|
return false;
|
|
} /* ----- end of method LDGM_session::needs_decoding ----- */
|
|
|
|
|
|
LDGM_session::~LDGM_session() {
|
|
free(pcm);
|
|
}
|