Merge branch 'aes' into trunk

Conflicts:
	src/rtp/decoders.c
This commit is contained in:
Martin Pulec
2013-07-03 13:36:35 +02:00
30 changed files with 1612 additions and 267 deletions

View File

@@ -55,4 +55,6 @@ UltraGrid - A High Definition Collaboratory
at Lawrence Berkeley Laboratory.
This product uses the RSA Data Security, Inc. MD5 Message-Digest Algorithm.
This product includes software developed by the OpenSSL Project
for use in the OpenSSL Toolkit. (http://www.openssl.org/)

View File

@@ -89,10 +89,13 @@ OBJS = @OBJS@ \
src/compat/platform_spin.o \
src/compat/platform_time.o \
src/compat/usleep.o \
src/crypto/crc_32.o \
src/crypto/crypt_aes.o \
src/crypto/crypt_aes_impl.o \
src/crypto/crypt_des.o \
src/crypto/md5.o \
src/crypto/openssl_encrypt.o \
src/crypto/openssl_decrypt.o \
src/crypto/random.o \
src/ihdtv/ihdtv.o \
src/module.o \

View File

@@ -2526,6 +2526,33 @@ fi
AC_SUBST(IMPORT_CONTROL_KEYBOARD_LIBS)
# -------------------------------------------------------------------------------------------------
# OpenSSL-libcrypto
# -------------------------------------------------------------------------------------------------
crypto=no
crypto_req=auto
AC_ARG_ENABLE(openssl,
AS_HELP_STRING([--disable-openssl], [disable OpenSSL support(default is auto)]),
[crypto_req=$enableval],
[crypto_req=auto]
)
PKG_CHECK_MODULES([CRYPTO], [libcrypto], [crypto=yes], [crypto=no])
if test $crypto_req != no -a $crypto = yes; then
AC_DEFINE([HAVE_CRYPTO], [1], [Build with OpenSSL support])
CFLAGS="$CFLAGS $CRYPTO_CFLAGS"
CXXFLAGS="$CXXFLAGS $CRYPTO_CFLAGS"
CPPFLAGS="$CPPFLAGS $CRYPTO_CFLAGS"
LIBS="$LIBS $CRYPTO_LIBS"
else
crypto=no
fi
if test $crypto_req = yes -a $crypto = no; then
AC_MSG_ERROR([OpenSSL not found]);
fi
# -------------------------------------------------------------------------------------------------
# Run subsequent configure scripts
# -------------------------------------------------------------------------------------------------
@@ -2552,6 +2579,7 @@ RESULT=\
Standalone modules .......... $build_libraries
License ..................... $license
iHDTV support ............... $ihdtv
OpenSSL-libcrypto ........... $crypto
Bluefish444 ................. $bluefish444 (audio: $blue_audio)
DeckLink .................... $decklink

View File

@@ -129,6 +129,8 @@ struct state_audio {
echo_cancellation_t *echo_state;
struct audio_export *exporter;
int resample_to;
char *requested_encryption;
};
/**
@@ -181,7 +183,8 @@ static void audio_scale_usage(void)
*/
struct state_audio * audio_cfg_init(struct module *parent, char *addrs, int recv_port, int send_port,
const char *send_cfg, const char *recv_cfg,
char *jack_cfg, char *fec_cfg, char *audio_channel_map, const char *audio_scale,
char *jack_cfg, char *fec_cfg, const char *encryption,
char *audio_channel_map, const char *audio_scale,
bool echo_cancellation, bool use_ipv6, char *mcast_if, audio_codec_t audio_codec,
int resample_to)
{
@@ -259,8 +262,12 @@ struct state_audio * audio_cfg_init(struct module *parent, char *addrs, int recv
} else {
s->echo_state = NULL;
}
if(encryption) {
s->requested_encryption = strdup(encryption);
}
s->tx_session = tx_init(&s->mod, 1500, TX_MEDIA_AUDIO, fec_cfg);
s->tx_session = tx_init(&s->mod, 1500, TX_MEDIA_AUDIO, fec_cfg, encryption);
if(!s->tx_session) {
fprintf(stderr, "Unable to initialize audio transmit.\n");
goto error;
@@ -420,6 +427,8 @@ void audio_done(struct state_audio *s)
pdb_destroy(&s->audio_participants);
}
audio_export_destroy(s->exporter);
module_done(&s->mod);
free(s->requested_encryption);
free(s);
}
}
@@ -457,7 +466,7 @@ static void *audio_receiver_thread(void *arg)
memset(&pbuf_data.buffer, 0, sizeof(struct audio_frame));
memset(&device_desc, 0, sizeof(struct audio_desc));
pbuf_data.decoder = audio_decoder_init(s->audio_channel_map, s->audio_scale);
pbuf_data.decoder = audio_decoder_init(s->audio_channel_map, s->audio_scale, s->requested_encryption);
assert(pbuf_data.decoder != NULL);
printf("Audio receiving started.\n");

View File

@@ -120,7 +120,8 @@ struct module;
struct state_audio * audio_cfg_init(struct module *parent, char *addrs, int recv_port, int send_port,
const char *send_cfg, const char *recv_cfg,
char *jack_cfg, char *fec_cfg, char *audio_channel_map, const char *audio_scale,
char *jack_cfg, char *fec_cfg, const char *encryption,
char *audio_channel_map, const char *audio_scale,
bool echo_cancellation, bool use_ipv6, char *mcast_iface, audio_codec_t audio_codec,
int resample_to);
void audio_finish(struct state_audio *s);

View File

@@ -52,13 +52,19 @@
#include "control.h"
#include <set>
#include "debug.h"
#include "messaging.h"
#include "module.h"
#include "stats.h"
#include "tv.h"
#define DEFAULT_CONTROL_PORT 5054
#define MAX_CLIENTS 16
using namespace std;
struct client {
int fd;
char buff[1024];
@@ -69,10 +75,14 @@ struct client {
};
struct control_state {
struct module mod;
pthread_t thread_id;
int local_fd[2];
int network_port;
struct module *root_module;
set<struct stats *> stats;
pthread_mutex_t stats_lock;
};
#define CONTROL_EXIT -1
@@ -84,6 +94,10 @@ static ssize_t write_all(int fd, const void *buf, size_t count);
static void * control_thread(void *args);
static void send_response(int fd, struct response *resp);
/**
* This function writes all data (in contrast to write() which
* can write only part of passed buffer)
*/
static ssize_t write_all(int fd, const void *buf, size_t count)
{
unsigned char *p = (unsigned char *) buf;
@@ -103,10 +117,16 @@ static ssize_t write_all(int fd, const void *buf, size_t count)
int control_init(int port, struct control_state **state, struct module *root_module)
{
struct control_state *s = (struct control_state *) malloc(sizeof(struct control_state));
control_state *s = new control_state;
s->root_module = root_module;
pthread_mutex_init(&s->stats_lock, NULL);
module_init_default(&s->mod);
s->mod.cls = MODULE_CLASS_CONTROL;
s->mod.priv_data = s;
if(port == -1) {
s->network_port = DEFAULT_CONTROL_PORT;
} else {
@@ -125,6 +145,8 @@ int control_init(int port, struct control_state **state, struct module *root_mod
return -1;
}
module_register(&s->mod, root_module);
*state = s;
return 0;
}
@@ -207,15 +229,6 @@ static int process_msg(struct control_state *s, int client_fd, char *message)
append_message_path(path, sizeof(path), (enum module_class[]){ MODULE_CLASS_COMPRESS, MODULE_CLASS_NONE });
resp = send_message(s->root_module, path, (struct message *) msg);
}
} else if(prefix_matches(message, "stats ")) {
struct msg_stats *msg = (struct msg_stats *)
new_message(sizeof(struct msg_stats));
char *stats = suffix(message, "stats ");
strncpy(msg->what, stats, sizeof(msg->what) - 1);
// resp = send_message(s->root_module, "blblbla", &data);
resp = new_response(RESPONSE_NOT_FOUND, strdup("statistics currently not working"));
} else if(strcasecmp(message, "bye") == 0) {
ret = CONTROL_CLOSE_HANDLE;
resp = new_response(RESPONSE_OK, NULL);
@@ -284,6 +297,9 @@ static bool parse_msg(char *buffer, char buffer_len, /* out */ char *message, in
return ret;
}
#define is_internal_port(x) (x == s->local_fd[1])
static void * control_thread(void *args)
{
struct control_state *s = (struct control_state *) args;
@@ -310,7 +326,7 @@ static void * control_thread(void *args)
struct client *clients = NULL;
struct client *new_client = malloc(sizeof(struct client));
struct client *new_client = (struct client *) malloc(sizeof(struct client));
new_client->fd = s->local_fd[1];
new_client->prev = NULL;
new_client->next = NULL;
@@ -319,25 +335,39 @@ static void * control_thread(void *args)
bool should_exit = false;
struct timeval last_report_sent;
const int report_interval_sec = 5;
gettimeofday(&last_report_sent, NULL);
while(!should_exit) {
fd_set set;
FD_ZERO(&set);
FD_SET(fd, &set);
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
int max_fd = fd + 1;
struct client *cur = clients;
while(cur) {
FD_SET(cur->fd, &set);
FD_SET(cur->fd, &fds);
if(cur->fd + 1 > max_fd) {
max_fd = cur->fd + 1;
}
cur = cur->next;
}
if(select(max_fd, &set, NULL, NULL, NULL) >= 1) {
if(FD_ISSET(fd, &set)) {
struct client *new_client = malloc(sizeof(struct client));
struct timeval timeout;
timeout.tv_sec = report_interval_sec;
timeout.tv_usec = 0;
struct timeval *timeout_ptr = NULL;
if(clients->next != NULL) { // some remote client
timeout_ptr = &timeout;
}
if(select(max_fd, &fds, NULL, NULL, timeout_ptr) >= 1) {
if(FD_ISSET(fd, &fds)) {
struct client *new_client = (struct client *)
malloc(sizeof(struct client));
new_client->fd = accept(fd, (struct sockaddr *) &client_addr, &len);
new_client->prev = NULL;
new_client->next = clients;
@@ -348,7 +378,7 @@ static void * control_thread(void *args)
struct client *cur = clients;
while(cur) {
if(FD_ISSET(cur->fd, &set)) {
if(FD_ISSET(cur->fd, &fds)) {
ssize_t ret = read(cur->fd, cur->buff + cur->buff_len,
sizeof(cur->buff) - cur->buff_len);
if(ret == -1) {
@@ -381,7 +411,7 @@ static void * control_thread(void *args)
cur->buff_len = cur_buffer_len;
int ret = process_msg(s, cur->fd, msg);
if(ret == CONTROL_EXIT) {
if(ret == CONTROL_EXIT && is_internal_port(cur->fd)) {
should_exit = true;
} else if(ret == CONTROL_CLOSE_HANDLE) {
shutdown(cur->fd, SHUT_RDWR);
@@ -394,6 +424,42 @@ static void * control_thread(void *args)
cur = cur->next;
}
struct timeval curr_time;
gettimeofday(&curr_time, NULL);
if(tv_diff(curr_time, last_report_sent) > report_interval_sec) {
char buffer[1025];
bool empty = true;
memset(buffer, '\0', sizeof(buffer));
strncpy(buffer + strlen(buffer), "stats", sizeof(buffer) -
strlen(buffer) - 1);
pthread_mutex_lock(&s->stats_lock);
for(set<struct stats *>::iterator it = s->stats.begin();
it != s->stats.end(); ++it) {
empty = false;
strncpy(buffer + strlen(buffer), " ", sizeof(buffer) -
strlen(buffer) - 1);
stats_format(*it, buffer + strlen(buffer),
sizeof(buffer) - strlen(buffer));
}
pthread_mutex_unlock(&s->stats_lock);
strncpy(buffer + strlen(buffer), "\r\n", sizeof(buffer) -
strlen(buffer) - 1);
if(strlen(buffer) < 1024 && !empty) {
cur = clients;
while(cur) {
if(is_internal_port(cur->fd)) { // skip local FD
cur = cur->next;
continue;
}
write_all(cur->fd, buffer, strlen(buffer));
cur = cur->next;
}
}
last_report_sent = curr_time;
}
}
struct client *cur = clients;
@@ -415,10 +481,30 @@ void control_done(struct control_state *s)
return;
}
module_done(&s->mod);
write_all(s->local_fd[0], "quit\r\n", 6);
pthread_join(s->thread_id, NULL);
close(s->local_fd[0]);
pthread_mutex_destroy(&s->stats_lock);
delete s;
}
void control_add_stats(struct control_state *s, struct stats *stats)
{
pthread_mutex_lock(&s->stats_lock);
s->stats.insert(stats);
pthread_mutex_unlock(&s->stats_lock);
}
void control_remove_stats(struct control_state *s, struct stats *stats)
{
pthread_mutex_lock(&s->stats_lock);
s->stats.erase(stats);
pthread_mutex_unlock(&s->stats_lock);
}

View File

@@ -45,8 +45,13 @@
*
*/
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
struct control_state;
struct module;
struct stats;
#define CONTROL_DEFAULT_PORT -1
@@ -55,4 +60,10 @@ struct module;
*/
int control_init(int port, struct control_state **state, struct module *root_module);
void control_done(struct control_state *s);
void control_add_stats(struct control_state *state, struct stats *stats);
void control_remove_stats(struct control_state *state, struct stats *stats);
#ifdef __cplusplus
}
#endif // __cplusplus

57
src/crypto/crc.h Normal file
View File

@@ -0,0 +1,57 @@
/*
** CRC.H - header file for SNIPPETS CRC and checksum functions
*/
#ifndef CRC__H
#define CRC__H
#include <stdlib.h> /* For size_t */
/*
** File: ARCCRC16.C
*/
void init_crc_table(void);
uint16_t crc_calc(uint16_t crc, char *buf, unsigned nbytes);
void do_file(char *fn);
/*
** File: CRC-16.C
*/
uint16_t crc16(char *data_p, uint16_t length);
/*
** File: CRC-16F.C
*/
uint16_t updcrc(uint16_t icrc, uint8_t *icp, size_t icnt);
/*
** File: CRC_32.C
*/
#define UPDC32(octet,crc) (crc_32_tab[((crc)\
^ ((uint8_t)octet)) & 0xff] ^ ((crc) >> 8))
uint32_t updateCRC32(unsigned char ch, uint32_t crc);
bool crc32file(char *name, uint32_t *crc, long *charcnt);
uint32_t crc32buf(char *buf, size_t len);
uint32_t crc32buf_with_oldcrc(char *buf, size_t len, uint32_t oldcrc);
/*
** File: CHECKSUM.C
*/
unsigned checksum(void *buffer, size_t len, unsigned int seed);
/*
** File: CHECKEXE.C
*/
void checkexe(char *fname);
#endif /* CRC__H */

206
src/crypto/crc_32.c Normal file
View File

@@ -0,0 +1,206 @@
/* Crc - 32 BIT ANSI X3.66 CRC checksum files */
#ifdef HAVE_CONFIG_H
#include "config.h"
#include "config_unix.h"
#include "config_win32.h"
#endif // HAVE_CONFIG_H
#include <stdio.h>
#include "crc.h"
#ifdef __TURBOC__
#pragma warn -cln
#endif
/**********************************************************************\
|* Demonstration program to compute the 32-bit CRC used as the frame *|
|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *|
|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *|
|* protocol). The 32-bit FCS was added via the Federal Register, *|
|* 1 June 1982, p.23798. I presume but don't know for certain that *|
|* this polynomial is or will be included in CCITT V.41, which *|
|* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *|
|* PUB 78 says that the 32-bit FCS reduces otherwise undetected *|
|* errors by a factor of 10^-5 over 16-bit FCS. *|
\**********************************************************************/
/* Need an unsigned type capable of holding 32 bits; */
typedef uint32_t UNS_32_BITS;
/* Copyright (C) 1986 Gary S. Brown. You may use this program, or
code or tables extracted from it, as desired without restriction.*/
/* First, the polynomial itself and its table of feedback terms. The */
/* polynomial is */
/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
/* Note that we take it "backwards" and put the highest-order term in */
/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
/* the MSB being 1. */
/* Note that the usual hardware shift register implementation, which */
/* is what we're using (we're merely optimizing it by doing eight-bit */
/* chunks at a time) shifts bits into the lowest-order term. In our */
/* implementation, that means shifting towards the right. Why do we */
/* do it this way? Because the calculated CRC must be transmitted in */
/* order from highest-order term to lowest-order term. UARTs transmit */
/* characters in order from LSB to MSB. By storing the CRC this way, */
/* we hand it to the UART in the order low-byte to high-byte; the UART */
/* sends each low-bit to hight-bit; and the result is transmission bit */
/* by bit from highest- to lowest-order term without requiring any bit */
/* shuffling on our part. Reception works similarly. */
/* The feedback terms table consists of 256, 32-bit entries. Notes: */
/* */
/* 1. The table can be generated at runtime if desired; code to do so */
/* is shown later. It might not be obvious, but the feedback */
/* terms simply represent the results of eight shift/xor opera- */
/* tions for all combinations of data and CRC register values. */
/* */
/* 2. The CRC accumulation logic is the same for all CRC polynomials, */
/* be they sixteen or thirty-two bits wide. You simply choose the */
/* appropriate table. Alternatively, because the table can be */
/* generated at runtime, you can start by generating the table for */
/* the polynomial in question and use exactly the same "updcrc", */
/* if your application needn't simultaneously handle two CRC */
/* polynomials. (Note, however, that XMODEM is strange.) */
/* */
/* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */
/* of course, 32-bit entries work OK if the high 16 bits are zero. */
/* */
/* 4. The values must be right-shifted by eight bits by the "updcrc" */
/* logic; the shift must be unsigned (bring in zeroes). On some */
/* hardware you could probably optimize the shift in assembler by */
/* using byte-swap instructions. */
static UNS_32_BITS crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
uint32_t updateCRC32(unsigned char ch, uint32_t crc)
{
return UPDC32(ch, crc);
}
bool crc32file(char *name, uint32_t *crc, long *charcnt)
{
register FILE *fin;
register uint32_t oldcrc32;
register int c;
oldcrc32 = 0xFFFFFFFF; *charcnt = 0;
#ifdef MSDOS
if ((fin=fopen(name, "rb"))==NULL)
#else
if ((fin=fopen(name, "r"))==NULL)
#endif
{
perror(name);
return false;
}
while ((c=getc(fin))!=EOF)
{
++*charcnt;
oldcrc32 = UPDC32(c, oldcrc32);
}
if (ferror(fin))
{
perror(name);
*charcnt = -1;
}
fclose(fin);
*crc = oldcrc32 = ~oldcrc32;
return true;
}
uint32_t crc32buf(char *buf, size_t len)
{
register uint32_t oldcrc32;
oldcrc32 = 0xFFFFFFFF;
for ( ; len; --len, ++buf)
{
oldcrc32 = UPDC32(*buf, oldcrc32);
}
return ~oldcrc32;
}
uint32_t crc32buf_with_oldcrc(char *buf, size_t len, uint32_t old_crc)
{
register uint32_t oldcrc32;
oldcrc32 = old_crc;
for ( ; len; --len, ++buf)
{
oldcrc32 = UPDC32(*buf, oldcrc32);
}
return ~oldcrc32;
}
#ifdef TEST
main(int argc, char *argv[])
{
uint32_t crc;
long charcnt;
register errors = 0;
while(--argc > 0)
{
errors |= crc32file(*++argv, &crc, &charcnt);
printf("%08lX %7ld %s\n", crc, charcnt, *argv);
}
return(errors != 0);
}
#endif /* TEST */

View File

@@ -0,0 +1,185 @@
/*
* FILE: aes_decrypt.c
* AUTHOR: Colin Perkins <csp@csperkins.org>
* Ladan Gharai
* Martin Benes <martinbenesh@gmail.com>
* Lukas Hejtmanek <xhejtman@ics.muni.cz>
* Petr Holub <hopet@ics.muni.cz>
* Milos Liska <xliska@fi.muni.cz>
* Jiri Matela <matela@ics.muni.cz>
* Dalibor Matura <255899@mail.muni.cz>
* Ian Wesley-Smith <iwsmith@cct.lsu.edu>
*
* Copyright (c) 2001-2004 University of Southern California
* Copyright (c) 2005-2010 CESNET z.s.p.o.
*
* Redistribution and use in source and binary forms, with or without
* modification, is permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
*
* This product includes software developed by the University of Southern
* California Information Sciences Institute. This product also includes
* software developed by CESNET z.s.p.o.
*
* 4. Neither the name of the University, Institute, CESNET nor the names of
* its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#include "config_unix.h"
#include "config_win32.h"
#endif // HAVE_CONFIG_H
#ifdef HAVE_CRYPTO
#include "crypto/crc.h"
#include "crypto/md5.h"
#include "crypto/openssl_decrypt.h"
#include "debug.h"
#include <string.h>
#include <openssl/aes.h>
struct openssl_decrypt {
AES_KEY key;
enum openssl_mode mode;
unsigned char ivec[AES_BLOCK_SIZE];
unsigned char ecount[AES_BLOCK_SIZE];
unsigned int num;
};
int openssl_decrypt_init(struct openssl_decrypt **state,
const char *passphrase,
enum openssl_mode mode)
{
struct openssl_decrypt *s =
(struct openssl_decrypt *)
calloc(1, sizeof(struct openssl_decrypt));
MD5_CTX context;
unsigned char hash[16];
MD5Init(&context);
MD5Update(&context, (unsigned char *) passphrase,
strlen(passphrase));
MD5Final(hash, &context);
switch(mode) {
case MODE_AES128_ECB:
AES_set_decrypt_key(hash, 128, &s->key);
break;
case MODE_AES128_CTR:
AES_set_encrypt_key(hash, 128, &s->key);
break;
default:
abort();
}
s->mode = mode;
*state = s;
return 0;
}
void openssl_decrypt_destroy(struct openssl_decrypt *s)
{
if(!s)
return;
free(s);
}
static void openssl_decrypt_block(struct openssl_decrypt *s,
unsigned char *ciphertext, unsigned char *plaintext, const char *nonce_and_counter,
int len)
{
if(nonce_and_counter) {
memcpy(s->ivec, nonce_and_counter, AES_BLOCK_SIZE);
s->num = 0;
}
switch(s->mode) {
case MODE_AES128_ECB:
assert(len == AES_BLOCK_SIZE);
AES_ecb_encrypt(ciphertext, plaintext,
&s->key, AES_DECRYPT);
break;
case MODE_AES128_CTR:
AES_ctr128_encrypt(ciphertext, plaintext, len, &s->key, s->ivec,
s->ecount, &s->num);
break;
default:
abort();
}
}
int openssl_decrypt(struct openssl_decrypt *decrypt,
const char *ciphertext, int ciphertext_len,
const char *aad, int aad_len,
char *plaintext)
{
UNUSED(ciphertext_len);
uint32_t data_len;
memcpy(&data_len, ciphertext, sizeof(uint32_t));
ciphertext += sizeof(uint32_t);
const char *nonce_and_counter = ciphertext;
ciphertext += 16;
uint32_t expected_crc;
uint32_t crc = 0xffffffff;
if(aad > 0) {
crc = crc32buf_with_oldcrc((char *) aad, aad_len, crc);
}
for(unsigned int i = 0; i < data_len; i += 16) {
int block_length = 16;
if(data_len - i < 16) block_length = data_len - i;
#ifdef HAVE_CRYPTO
openssl_decrypt_block(decrypt,
(unsigned char *) ciphertext + i,
(unsigned char *) plaintext + i,
nonce_and_counter, block_length);
#endif // HAVE_CRYPTO
nonce_and_counter = NULL;
crc = crc32buf_with_oldcrc((char *) plaintext + i, block_length, crc);
}
#ifdef HAVE_CRYPTO
openssl_decrypt_block(decrypt,
(unsigned char *) ciphertext + data_len,
(unsigned char *) &expected_crc,
0, sizeof(uint32_t));
#endif // HAVE_CRYPTO
if(crc != expected_crc) {
return 0;
}
return data_len;
}
#endif // HAVE_CRYPTO

View File

@@ -0,0 +1,93 @@
/*
* FILE: openssl_encrypt.h
* AUTHOR: Colin Perkins <csp@isi.edu>
* Martin Benes <martinbenesh@gmail.com>
* Lukas Hejtmanek <xhejtman@ics.muni.cz>
* Petr Holub <hopet@ics.muni.cz>
* Milos Liska <xliska@fi.muni.cz>
* Jiri Matela <matela@ics.muni.cz>
* Dalibor Matura <255899@mail.muni.cz>
* Ian Wesley-Smith <iwsmith@cct.lsu.edu>
*
* Copyright (c) 2001-2002 University of Southern California
* Copyright (c) 2005-2010 CESNET z.s.p.o.
*
* Redistribution and use in source and binary forms, with or without
* modification, is permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
*
* This product includes software developed by the University of Southern
* California Information Sciences Institute. This product also includes
* software developed by CESNET z.s.p.o.
*
* 4. Neither the name of the University, Institute, CESNET nor the names of
* its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef OPENSSL_DECRYPT_H_
#define OPENSSL_DECRYPT_H_
#include "crypto/openssl_encrypt.h"
struct openssl_decrypt;
/**
* Creates decryption state
*
* @param[out] state state pointer
* @param[in] passphrase key material (NULL-terminated)
* @param[in] mode mode
* @retval 0 ok
* @retval <0 failure
* @retval >0 state was not created
*/
int openssl_decrypt_init(struct openssl_decrypt **state,
const char *passphrase, enum openssl_mode mode);
/**
* Destroys decryption state
*/
void openssl_decrypt_destroy(struct openssl_decrypt *state);
/**
* Decrypts block of data
*
* @param[in] decrypt decrypt state
* @param[in] ciphertext encrypted text
* @param[in] ciphertext_len lenght of encrypted text
* @param[in] aad Aditional Authenticated Data (see openssl_encrypt documentation)
* @param[in] aad_len length of aad block
* @param[out] plaintext otput plaintext
* @retval 0 if checksum doesn't match
* @retval >0 length of output plaintext
*/
int openssl_decrypt(struct openssl_decrypt *decrypt,
const char *ciphertext, int ciphertext_len,
const char *aad, int aad_len,
char *plaintext);
#endif // OPENSSL_DECRYPT_H_

View File

@@ -0,0 +1,186 @@
/*
* FILE: aes_encrypt.c
* AUTHOR: Colin Perkins <csp@csperkins.org>
* Ladan Gharai
* Martin Benes <martinbenesh@gmail.com>
* Lukas Hejtmanek <xhejtman@ics.muni.cz>
* Petr Holub <hopet@ics.muni.cz>
* Milos Liska <xliska@fi.muni.cz>
* Jiri Matela <matela@ics.muni.cz>
* Dalibor Matura <255899@mail.muni.cz>
* Ian Wesley-Smith <iwsmith@cct.lsu.edu>
*
* Copyright (c) 2001-2004 University of Southern California
* Copyright (c) 2005-2010 CESNET z.s.p.o.
*
* Redistribution and use in source and binary forms, with or without
* modification, is permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
*
* This product includes software developed by the University of Southern
* California Information Sciences Institute. This product also includes
* software developed by CESNET z.s.p.o.
*
* 4. Neither the name of the University, Institute, CESNET nor the names of
* its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#include "config_unix.h"
#include "config_win32.h"
#endif
#ifdef HAVE_CRYPTO
#include "crypto/crc.h"
#include "crypto/md5.h"
#include "crypto/openssl_encrypt.h"
#include <string.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
struct openssl_encrypt {
AES_KEY key;
enum openssl_mode mode;
unsigned char ivec[16];
unsigned int num;
unsigned char ecount[16];
};
int openssl_encrypt_init(struct openssl_encrypt **state, const char *passphrase,
enum openssl_mode mode)
{
struct openssl_encrypt *s = (struct openssl_encrypt *)
calloc(1, sizeof(struct openssl_encrypt));
MD5_CTX context;
unsigned char hash[16];
if (!RAND_bytes(s->ivec, 8)) {
return -1;
}
MD5Init(&context);
MD5Update(&context, (unsigned char *) passphrase,
strlen(passphrase));
MD5Final(hash, &context);
AES_set_encrypt_key(hash, 128, &s->key);
s->mode = mode;
assert(s->mode == MODE_AES128_CTR); // only functional by now
*state = s;
return 0;
}
static void openssl_encrypt_block(struct openssl_encrypt *s, unsigned char *plaintext,
unsigned char *ciphertext, char *nonce_plus_counter, int len)
{
if(nonce_plus_counter) {
memcpy(nonce_plus_counter, (char *) s->ivec, 16);
/* We do start a new block so we zero the byte counter
* Please NB that counter doesn't need to be incremented
* because the counter is incremented everytime s->num == 0,
* presumably before encryption, so setting it to 0 forces
* counter increment as well.
*/
if(s->num != 0) {
s->num = 0;
}
}
switch(s->mode) {
case MODE_AES128_CTR:
AES_ctr128_encrypt(plaintext, ciphertext, len, &s->key, s->ivec,
s->ecount, &s->num);
break;
case MODE_AES128_ECB:
assert(len == AES_BLOCK_SIZE);
AES_ecb_encrypt(plaintext, ciphertext,
&s->key, AES_ENCRYPT);
break;
}
}
void openssl_encrypt_destroy(struct openssl_encrypt *s)
{
free(s);
}
int openssl_encrypt(struct openssl_encrypt *encryption,
char *plaintext, int data_len, char *aad, int aad_len, char *ciphertext) {
uint32_t crc = 0xffffffff;
memcpy(ciphertext, &data_len, sizeof(uint32_t));
ciphertext += sizeof(uint32_t);
char *nonce_and_counter = ciphertext;
ciphertext += 16;
if(aad_len > 0) {
crc = crc32buf_with_oldcrc(aad, aad_len, crc);
}
for(int i = 0; i < data_len; i+=16) {
int block_length = 16;
if(data_len - i < 16) block_length = data_len - i;
crc = crc32buf_with_oldcrc(plaintext + i, block_length, crc);
#ifdef HAVE_CRYPTO
openssl_encrypt_block(encryption,
(unsigned char *) plaintext + i,
(unsigned char *) ciphertext + i,
nonce_and_counter,
block_length);
nonce_and_counter = NULL;
#endif // HAVE_CRYPTO
}
#ifdef HAVE_CRYPTO
openssl_encrypt_block(encryption,
(unsigned char *) &crc,
(unsigned char *) ciphertext + data_len,
NULL,
sizeof(uint32_t));
#endif // HAVE_CRYPTO
return data_len + sizeof(crc) + 16 + sizeof(uint32_t);
}
int openssl_get_overhead(struct openssl_encrypt *s)
{
switch(s->mode) {
case MODE_AES128_CTR:
return sizeof(uint32_t) /* data_len */ +
16 /* nonce + counter */ + sizeof(uint32_t) /* crc */;
default:
abort();
}
}
#endif // HAVE_CRYPTO

View File

@@ -0,0 +1,113 @@
/*
* FILE: aes_encrypt.h
* AUTHOR: Colin Perkins <csp@isi.edu>
* Martin Benes <martinbenesh@gmail.com>
* Lukas Hejtmanek <xhejtman@ics.muni.cz>
* Petr Holub <hopet@ics.muni.cz>
* Milos Liska <xliska@fi.muni.cz>
* Jiri Matela <matela@ics.muni.cz>
* Dalibor Matura <255899@mail.muni.cz>
* Ian Wesley-Smith <iwsmith@cct.lsu.edu>
*
* Copyright (c) 2001-2002 University of Southern California
* Copyright (c) 2005-2010 CESNET z.s.p.o.
*
* Redistribution and use in source and binary forms, with or without
* modification, is permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
*
* This product includes software developed by the University of Southern
* California Information Sciences Institute. This product also includes
* software developed by CESNET z.s.p.o.
*
* 4. Neither the name of the University, Institute, CESNET nor the names of
* its contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef OPENSSL_ENCRYPT_H_
#define OPENSSL_ENCRYPT_H_
#ifdef __cplusplus
extern "C" {
#endif
struct openssl_encrypt;
enum openssl_mode {
MODE_AES128_CTR, // no autenticity, only integrity (CRC)
MODE_AES128_ECB // do not use
};
#define MAX_CRYPTO_EXTRA_DATA 24 // == maximal overhead of available encryptions
#define MAX_CRYPTO_PAD 0 // CTR does not need padding
#define MAX_CRYPTO_EXCEED (MAX_CRYPTO_EXTRA_DATA + MAX_CRYPTO_PAD)
/**
* Initializes encryption
* @param[out] state created state
* @param[in] passphrase key material (NULL-terminated)
* @param[in] mode
* @retval 0 success
* @retval <0 failure
* @retval >0 state not created
*/
int openssl_encrypt_init(struct openssl_encrypt **state,
const char *passphrase, enum openssl_mode mode);
/**
* Destroys state
*/
void openssl_encrypt_destroy(struct openssl_encrypt *state);
/**
* Encrypts a block of data
*
* @param[in] encryption state
* @param[in] plaintext plain text
* @param[in] plaintext_len length of plain text
* @param[in] aad Additional Authenticated Data
* this won't be encrypted but passed in plaintext along ciphertext.
* These data are autheticated only if working in some AE mode
* @param[in] aad_len length of AAD text
* @param[out] ciphertext resulting ciphertext, can be up to (plaintext_len + MAX_CRYPTO_EXCEED) length
* @returns size of writen ciphertext
*/
int openssl_encrypt(struct openssl_encrypt *encryption,
char *plaintext, int plaintext_len, char *aad, int aad_len, char *ciphertext);
/**
* Returns maximal number of bytest that the ciphertext length may exceed plaintext for selected
* encryption.
*
* @param[in] encryption state
* @returns max overhead (must be <= MAX_CRYPTO_EXCEED)
*/
int openssl_get_overhead(struct openssl_encrypt *encryption);
#ifdef __cplusplus
}
#endif
#endif // OPENSSL_ENCRYPT_H_

View File

@@ -171,7 +171,8 @@ void *recompress_init(struct module *parent,
s->required_compress = strdup(compress);
s->frame = NULL;
s->tx = tx_init(s->parent, mtu, TX_MEDIA_VIDEO, fec);
const char *requested_encryption = NULL;
s->tx = tx_init(s->parent, mtu, TX_MEDIA_VIDEO, fec, requested_encryption);
gettimeofday(&s->start_time, NULL);

View File

@@ -122,6 +122,7 @@
#define OPT_IMPORT (('I' << 8) | 'M')
#define OPT_AUDIO_CODEC (('A' << 8) | 'C')
#define OPT_CAPTURE_FILTER (('O' << 8) | 'F')
#define OPT_ENCRYPTION (('E' << 8) | 'N')
#ifdef HAVE_MACOSX
#define INITIAL_VIDEO_RECV_BUFFER_SIZE 5944320
@@ -162,6 +163,12 @@ struct state_uv {
pthread_mutex_t master_lock;
struct video_export *video_exporter;
struct sender_data sender_data;
struct module *root_module;
const char *requested_encryption;
};
static volatile int wait_to_finish = FALSE;
@@ -309,6 +316,8 @@ static void usage(void)
printf("\n");
printf("\t--capture-filter <filter>\tCapture filter(s)\n");
printf("\n");
printf("\t--encryption <passphrase>\tKey material for encryption\n");
printf("\n");
printf("\taddress(es) \tdestination address\n");
printf("\n");
printf("\t \tIf comma-separated list of addresses\n");
@@ -454,13 +463,6 @@ static void destroy_devices(struct rtp ** network_devices)
free(network_devices);
}
static struct tx *initialize_transmit(struct module *parent, unsigned requested_mtu, char *fec)
{
/* Currently this is trivial. It'll get more complex once we */
/* have multiple codecs and/or error correction. */
return tx_init(parent, requested_mtu, TX_MEDIA_VIDEO, fec);
}
#ifdef HAVE_IHDTV
static void *ihdtv_receiver_thread(void *arg)
{
@@ -504,7 +506,8 @@ static struct vcodec_state *new_decoder(struct state_uv *uv) {
if(state) {
state->messages = simple_linked_list_init();
state->decoder = decoder_init(uv->decoder_mode, uv->postprocess, uv->display_device);
state->decoder = decoder_init(uv->decoder_mode, uv->postprocess, uv->display_device,
uv->requested_encryption);
if(!state->decoder) {
fprintf(stderr, "Error initializing decoder (incorrect '-M' or '-p' option?).\n");
@@ -563,7 +566,11 @@ static void *receiver_thread(void *arg)
fr = 1;
stat_loss = stats_new_statistics("loss");
struct module *control_mod = get_module(get_root_module(uv->root_module), "control");
stat_loss = stats_new_statistics(
(struct control_state *) control_mod,
"loss");
unlock_module(control_mod);
while (!should_exit_receiver) {
/* Housekeeping and RTCP... */
@@ -712,7 +719,6 @@ static void *compress_thread(void *arg)
{
struct module *uv_mod = (struct module *)arg;
struct state_uv *uv = (struct state_uv *) uv_mod->priv_data;
struct sender_data sender_data;
struct video_frame *tx_frame;
struct audio_frame *audio;
@@ -722,17 +728,17 @@ static void *compress_thread(void *arg)
struct compress_state *compression;
int ret = compress_init(uv_mod, uv->requested_compression, &compression);
sender_data.parent = uv_mod; /// @todo should be compress thread module
sender_data.connections_count = uv->connections_count;
sender_data.tx_protocol = uv->tx_protocol;
uv->sender_data.parent = uv_mod; /// @todo should be compress thread module
uv->sender_data.connections_count = uv->connections_count;
uv->sender_data.tx_protocol = uv->tx_protocol;
if(uv->tx_protocol == ULTRAGRID_RTP) {
sender_data.network_devices = uv->network_devices;
uv->sender_data.network_devices = uv->network_devices;
} else {
sender_data.sage_tx_device = uv->sage_tx_device;
uv->sender_data.sage_tx_device = uv->sage_tx_device;
}
sender_data.tx = uv->tx;
uv->sender_data.tx = uv->tx;
if(!sender_init(&sender_data)) {
if(!sender_init(&uv->sender_data)) {
fprintf(stderr, "Error initializing sender.\n");
exit_uv(1);
pthread_mutex_unlock(&uv->master_lock);
@@ -780,13 +786,13 @@ static void *compress_thread(void *arg)
nonblock = false;
}
sender_post_new_frame(&sender_data, tx_frame, nonblock);
sender_post_new_frame(&uv->sender_data, tx_frame, nonblock);
}
}
vidcap_finish(uv_state->capture_device);
sender_done(&sender_data);
sender_done(&uv->sender_data);
compress_done:
module_done(CAST_MODULE(compression));
@@ -933,12 +939,13 @@ int main(int argc, char *argv[])
{"audio-host", required_argument, 0, 'A'},
{"audio-codec", required_argument, 0, OPT_AUDIO_CODEC},
{"capture-filter", required_argument, 0, OPT_CAPTURE_FILTER},
{"encryption", required_argument, 0, OPT_ENCRYPTION},
{0, 0, 0, 0}
};
int option_index = 0;
// uv = (struct state_uv *) calloc(1, sizeof(struct state_uv));
uv = (struct state_uv *)malloc(sizeof(struct state_uv));
uv = (struct state_uv *) calloc(1, sizeof(struct state_uv));
uv_state = uv;
uv->audio = NULL;
@@ -962,6 +969,7 @@ int main(int argc, char *argv[])
uv->sage_tx_device = NULL;
init_root_module(&root_mod, uv);
uv->root_module = &root_mod;
pthread_mutex_init(&uv->master_lock, NULL);
@@ -1178,6 +1186,9 @@ int main(int argc, char *argv[])
case OPT_CAPTURE_FILTER:
requested_capture_filter = optarg;
break;
case OPT_ENCRYPTION:
uv->requested_encryption = optarg;
break;
case '?':
default:
usage();
@@ -1225,6 +1236,10 @@ int main(int argc, char *argv[])
audio_rx_port = uv->recv_port_number + 2;
}
if(control_init(CONTROL_DEFAULT_PORT, &control, &root_mod) != 0) {
fprintf(stderr, "Warning: Unable to initialize remote control!\n:");
}
if(should_export) {
if(!enable_export(export_opts)) {
fprintf(stderr, "Export initialization failed.\n");
@@ -1281,7 +1296,8 @@ int main(int argc, char *argv[])
}
uv->audio = audio_cfg_init (&root_mod, audio_host, audio_rx_port,
audio_tx_port, audio_send, audio_recv,
jack_cfg, requested_audio_fec, audio_channel_map,
jack_cfg, requested_audio_fec, uv->requested_encryption,
audio_channel_map,
audio_scale, echo_cancellation, use_ipv6, mcast_if,
audio_codec, compressed_audio_sample_rate);
free(requested_audio_fec);
@@ -1445,8 +1461,10 @@ int main(int argc, char *argv[])
packet_rate = 0;
}
if ((uv->tx = initialize_transmit(&root_mod,
uv->requested_mtu, requested_video_fec)) == NULL) {
if ((uv->tx = tx_init(&root_mod,
uv->requested_mtu, TX_MEDIA_VIDEO,
requested_video_fec,
uv->requested_encryption)) == NULL) {
printf("Unable to initialize transmitter.\n");
exit_uv(EXIT_FAIL_TRANSMIT);
goto cleanup_wait_display;
@@ -1469,7 +1487,8 @@ int main(int argc, char *argv[])
/* following block only shows help (otherwise initialized in receiver thread */
if((uv->postprocess && strstr(uv->postprocess, "help") != NULL) ||
(uv->decoder_mode && strstr(uv->decoder_mode, "help") != NULL)) {
struct state_decoder *dec = decoder_init(uv->decoder_mode, uv->postprocess, NULL);
struct state_decoder *dec = decoder_init(uv->decoder_mode, uv->postprocess, NULL,
uv->requested_encryption);
decoder_destroy(dec);
exit_uv(EXIT_SUCCESS);
goto cleanup_wait_display;
@@ -1518,10 +1537,6 @@ int main(int argc, char *argv[])
pthread_mutex_lock(&uv->master_lock);
if(control_init(CONTROL_DEFAULT_PORT, &control, &root_mod) != 0) {
fprintf(stderr, "Warning: Unable to initialize remote control!\n:");
}
if(audio_get_display_flags(uv->audio)) {
audio_register_put_callback(uv->audio, (void (*)(void *, struct audio_frame *)) display_put_audio_frame, uv->display_device);
audio_register_reconfigure_callback(uv->audio, (int (*)(void *, int, int,
@@ -1595,6 +1610,8 @@ cleanup:
control_done(control);
module_done(&root_mod);
printf("Exit\n");
return exit_status;

View File

@@ -10,56 +10,10 @@
#include "utils/list.h"
#include "utils/lock_guard.h"
static struct module *find_child(struct module *node, const char *node_name, int index)
{
for(void *it = simple_linked_list_it_init(node->childs); it != NULL; ) {
struct module *child = (struct module *) simple_linked_list_it_next(&it);
if(strcasecmp(module_class_name(child->cls), node_name) == 0) {
if(index-- == 0) {
return child;
}
}
}
return NULL;
}
static void get_receiver_index(char *node_str, int *index) {
*index = 0;
if(strchr(node_str, '[')) {
*index = atoi(strchr(node_str, '[') + 1);
*strchr(node_str, '[') = '\0';
}
}
struct response *send_message(struct module *root, const char *const_path, struct message *msg)
{
struct module *receiver = root;
char *path, *tmp;
char *item, *save_ptr;
char buf[1024];
assert(root != NULL);
pthread_mutex_lock(&receiver->lock);
tmp = path = strdup(const_path);
while ((item = strtok_r(path, ".", &save_ptr))) {
struct module *old_receiver = receiver;
int index;
get_receiver_index(item, &index);
receiver = find_child(receiver, item, index);
if(!receiver) {
pthread_mutex_unlock(&old_receiver->lock);
break;
}
pthread_mutex_lock(&receiver->lock);
pthread_mutex_unlock(&old_receiver->lock);
path = NULL;
}
free(tmp);
struct module *receiver = get_module(root, const_path);
/**
* @invariant
* either receiver is NULL or receiver->lock is locked (exactly once)

View File

@@ -50,12 +50,14 @@ struct msg_change_fec_data {
char fec[128];
};
enum compress_change_type {
CHANGE_COMPRESS,
CHANGE_PARAMS
};
struct msg_change_compress_data {
struct message m;
enum {
CHANGE_COMPRESS,
CHANGE_PARAMS
} what;
enum compress_change_type what;
char config_string[128];
};

View File

@@ -124,6 +124,7 @@ const char *module_class_name_pairs[] = {
[MODULE_CLASS_SENDER] = "sender",
[MODULE_CLASS_TX] = "transmit",
[MODULE_CLASS_AUDIO] = "audio",
[MODULE_CLASS_CONTROL] = "control",
};
const char *module_class_name(enum module_class cls)
@@ -150,3 +151,70 @@ void append_message_path(char *buf, int buflen, enum module_class modules[])
}
}
struct module *get_root_module(struct module *node)
{
while(node->parent) {
node = node->parent;
}
assert(node->cls == MODULE_CLASS_ROOT);
return node;
}
static struct module *find_child(struct module *node, const char *node_name, int index)
{
for(void *it = simple_linked_list_it_init(node->childs); it != NULL; ) {
struct module *child = (struct module *) simple_linked_list_it_next(&it);
if(strcasecmp(module_class_name(child->cls), node_name) == 0) {
if(index-- == 0) {
return child;
}
}
}
return NULL;
}
static void get_receiver_index(char *node_str, int *index) {
*index = 0;
if(strchr(node_str, '[')) {
*index = atoi(strchr(node_str, '[') + 1);
*strchr(node_str, '[') = '\0';
}
}
struct module *get_module(struct module *root, const char *const_path)
{
struct module *receiver = root;
char *path, *tmp;
char *item, *save_ptr;
assert(root != NULL);
pthread_mutex_lock(&receiver->lock);
tmp = path = strdup(const_path);
while ((item = strtok_r(path, ".", &save_ptr))) {
struct module *old_receiver = receiver;
int index;
get_receiver_index(item, &index);
receiver = find_child(receiver, item, index);
if(!receiver) {
pthread_mutex_unlock(&old_receiver->lock);
break;
}
pthread_mutex_lock(&receiver->lock);
pthread_mutex_unlock(&old_receiver->lock);
path = NULL;
}
free(tmp);
return receiver;
}
void unlock_module(struct module *module)
{
pthread_mutex_unlock(&module->lock);
}

View File

@@ -70,6 +70,7 @@ enum module_class {
MODULE_CLASS_SENDER,
MODULE_CLASS_TX,
MODULE_CLASS_AUDIO,
MODULE_CLASS_CONTROL,
};
struct module;
@@ -77,6 +78,11 @@ struct simple_linked_list;
typedef void (*module_deleter_t)(struct module *);
/**
* @struct module
* Only members cls, deleter, priv_data and msg_queue may be directly touched
* by user. The others should be considered private.
*/
struct module {
uint32_t magic;
pthread_mutex_t lock;
@@ -86,6 +92,7 @@ struct module {
module_deleter_t deleter;
/**
* @var msg_callback
* Module may implement a push method that will respond synchronously to events.
* If not, message will be enqueued to message queue.
*/
@@ -100,6 +107,25 @@ void module_register(struct module *module_data, struct module *parent);
void module_done(struct module *module_data);
const char *module_class_name(enum module_class cls);
void append_message_path(char *buf, int buflen, enum module_class modules[]);
/**
* IMPORTANT: returned module will be locked on return and needs to be unlocked by caller
* when it is done!
*
* @retval NULL if not found
* @retval non-NULL pointer to the module
*/
struct module *get_module(struct module *root, const char *path);
/**
* @see get_module
* Caller of get_module should call this when done with module
*/
void unlock_module(struct module *module);
/**
* Returns pointer to root module. It WON'T be locked.
*
* @retval root module
*/
struct module *get_root_module(struct module *node);
#define CAST_MODULE(x) ((struct module *) x)

View File

@@ -71,6 +71,8 @@
#include "audio/codec.h"
#include "audio/resampler.h"
#include "audio/utils.h"
#include "crypto/crc.h"
#include "crypto/openssl_decrypt.h"
#include "utils/packet_counter.h"
@@ -115,6 +117,8 @@ struct state_audio_decoder {
uint32_t saved_audio_tag;
int samples_decoded;
struct openssl_decrypt *decrypt;
};
static int validate_mapping(struct channel_map *map);
@@ -168,7 +172,7 @@ static void compute_scale(struct scale_data *scale_data, float vol_avg, int samp
}
}
void *audio_decoder_init(char *audio_channel_map, const char *audio_scale)
void *audio_decoder_init(char *audio_channel_map, const char *audio_scale, const char *encryption)
{
struct state_audio_decoder *s;
bool scale_auto = false;
@@ -187,6 +191,19 @@ void *audio_decoder_init(char *audio_channel_map, const char *audio_scale)
s->resampler = resampler_init(48000);
if(encryption) {
#ifdef HAVE_CRYPTO
if(openssl_decrypt_init(&s->decrypt,
encryption, MODE_AES128_CTR) != 0) {
fprintf(stderr, "Unable to create decompress!\n");
return NULL;
}
#else
fprintf(stderr, "This " PACKAGE_NAME " version was build "
"without OpenSSL support!\n");
return NULL;
#endif // HAVE_CRYPTO
}
if(audio_channel_map) {
char *save_ptr = NULL;
@@ -311,6 +328,8 @@ void audio_decoder_destroy(void *state)
audio_codec_done(s->audio_decompress);
resampler_done(s->resampler);
openssl_decrypt_destroy(s->decrypt);
free(s);
}
@@ -333,12 +352,57 @@ int decode_audio_frame(struct coded_data *cdata, void *data)
while (cdata != NULL) {
char *data;
// for definition see rtp_callbacks.h
uint32_t *hdr = (uint32_t *)(void *) cdata->data->data;
uint32_t *audio_hdr = (uint32_t *)(void *) cdata->data->data;
uint32_t *encryption_hdr;
const int pt = cdata->data->pt;
if(pt == PT_ENCRYPT_AUDIO) {
encryption_hdr = (uint32_t *)((void *) cdata->data->data +
sizeof(audio_payload_hdr_t));
if(!decoder->decrypt) {
fprintf(stderr, "Receiving encrypted audio data but "
"no decryption key entered!\n");
ret = false; goto cleanup;
}
} else if(pt == PT_AUDIO) {
if(decoder->decrypt) {
fprintf(stderr, "Receiving unencrypted audio data "
"while expecting encrypted.\n");
ret = false; goto cleanup;
}
} else {
fprintf(stderr, "Unknown audio packet type: %d\n", pt);
abort();
}
unsigned int length;
char plaintext[cdata->data->data_len]; // plaintext will be actually shorter
if(pt == PT_AUDIO) {
length = cdata->data->data_len - sizeof(audio_payload_hdr_t);
data = cdata->data->data + sizeof(audio_payload_hdr_t);
} else {
assert(pt == PT_ENCRYPT_AUDIO);
char *ciphertext = cdata->data->data + sizeof(crypto_payload_hdr_t) +
sizeof(audio_payload_hdr_t);
int ciphertext_len = cdata->data->data_len - sizeof(audio_payload_hdr_t) -
sizeof(crypto_payload_hdr_t);
if((length = openssl_decrypt(decoder->decrypt,
ciphertext, ciphertext_len,
(char *) audio_hdr, sizeof(audio_payload_hdr_t),
plaintext
)) == 0) {
fprintf(stderr, "Warning: Packet dropped AES - wrong CRC!\n");
ret = false;
goto cleanup;
}
data = plaintext;
}
/* we receive last channel first (with m bit, last packet) */
/* thus can be set only with m-bit packet */
if(cdata->data->m) {
input_channels = ((ntohl(hdr[0]) >> 22) & 0x3ff) + 1;
input_channels = ((ntohl(audio_hdr[0]) >> 22) & 0x3ff) + 1;
}
// we have:
@@ -346,16 +410,19 @@ int decode_audio_frame(struct coded_data *cdata, void *data)
// 2) not last, but the last one was processed at first
assert(input_channels > 0);
channel = (ntohl(hdr[0]) >> 22) & 0x3ff;
int bufnum = ntohl(hdr[0]) & 0x3fffff;
sample_rate = ntohl(hdr[3]) & 0x3fffff;
bps = (ntohl(hdr[3]) >> 26) / 8;
uint32_t audio_tag = ntohl(hdr[4]);
channel = (ntohl(audio_hdr[0]) >> 22) & 0x3ff;
int bufnum = ntohl(audio_hdr[0]) & 0x3fffff;
sample_rate = ntohl(audio_hdr[3]) & 0x3fffff;
bps = (ntohl(audio_hdr[3]) >> 26) / 8;
uint32_t audio_tag = ntohl(audio_hdr[4]);
output_channels = decoder->channel_remapping ? decoder->channel_map.max_output + 1: input_channels;
output_channels = decoder->channel_remapping ?
decoder->channel_map.max_output + 1: input_channels;
/**
* TODO: obtain supported rates from device
/*
* Reconfiguration
*
* @todo obtain supported rates from device
*/
int device_sample_rate = 48000;
int device_bps = 2;
@@ -404,13 +471,9 @@ int decode_audio_frame(struct coded_data *cdata, void *data)
return FALSE;
}
}
data = cdata->data->data + sizeof(audio_payload_hdr_t);
unsigned int length = cdata->data->data_len - sizeof(audio_payload_hdr_t);
unsigned int offset = ntohl(hdr[1]);
unsigned int buffer_len = ntohl(hdr[2]);
unsigned int offset = ntohl(audio_hdr[1]);
unsigned int buffer_len = ntohl(audio_hdr[2]);
//fprintf(stderr, "%d-%d-%d ", length, bufnum, channel);

View File

@@ -54,6 +54,7 @@
struct coded_data;
int decode_audio_frame(struct coded_data *cdata, void *data);
void *audio_decoder_init(char *audio_channel_map, const char *audio_scale);
void *audio_decoder_init(char *audio_channel_map, const char *audio_scale,
const char *encryption);
void audio_decoder_destroy(void *state);

View File

@@ -44,6 +44,7 @@
#include "config_unix.h"
#include "config_win32.h"
#endif // HAVE_CONFIG_H
#include "crypto/openssl_decrypt.h"
#include "debug.h"
#include "host.h"
#include "perf.h"
@@ -170,6 +171,8 @@ struct state_decoder {
double set_fps; // "message" passed to our master
codec_t codec;
bool slow;
struct openssl_decrypt *decrypt;
};
// message definitions
@@ -202,7 +205,14 @@ static void wait_for_framebuffer_swap(struct state_decoder *decoder) {
pthread_mutex_unlock(&decoder->lock);
}
#define ENCRYPTED_ERR "Receiving encrypted video data but " \
"no decryption key entered!\n"
#define NOT_ENCRYPTED_ERR "Receiving unencrypted video data " \
"while expecting encrypted.\n"
#define SKIP_LDGM_FRAME ret = FALSE; goto cleanup;
static void *ldgm_thread(void *args) {
uint32_t tmp_ui32;
struct state_decoder *decoder = args;
struct fec fec_state;
@@ -251,6 +261,7 @@ static void *ldgm_thread(void *args) {
decompress_data->buffer_num = calloc(data->substream_count, sizeof(int));
memcpy(decompress_data->buffer_num, data->buffer_num, data->substream_count * sizeof(int));
memcpy(decompress_data->fec_buffers, data->recv_buffers, data->substream_count * sizeof(char *));
if (data->pt == PT_VIDEO_LDGM) {
if(!fec_state.state || fec_state.k != data->k ||
fec_state.m != data->m ||
@@ -274,70 +285,118 @@ static void *ldgm_thread(void *args) {
}
if (data->pt == PT_VIDEO_LDGM) {
int x,y;
for (x = 0; x < get_video_mode_tiles_x(decoder->video_mode) ; ++x) {
for (y = 0; y < get_video_mode_tiles_y(decoder->video_mode); ++y) {
int pos = x + get_video_mode_tiles_x(decoder->video_mode) * y;
char *out_buffer = NULL;
int out_len = 0;
int pos;
for (pos = 0; pos < get_video_mode_tiles_x(decoder->video_mode)
* get_video_mode_tiles_y(decoder->video_mode); ++pos) {
char *ldgm_out_buffer = NULL;
int ldgm_out_len = 0;
ldgm_decoder_decode(fec_state.state, data->recv_buffers[pos],
data->buffer_len[pos],
&out_buffer, &out_len, data->pckt_list[pos]);
ldgm_decoder_decode(fec_state.state, data->recv_buffers[pos],
data->buffer_len[pos],
&ldgm_out_buffer, &ldgm_out_len, data->pckt_list[pos]);
if(out_len == 0) {
ret = FALSE;
fprintf(stderr, "[decoder] LDGM: unable to reconstruct data.\n");
goto cleanup;
if(ldgm_out_len == 0) {
ret = FALSE;
fprintf(stderr, "[decoder] LDGM: unable to reconstruct data.\n");
goto cleanup;
}
uint32_t ldgm_pt;
char *ldgm_hdr = ldgm_out_buffer;
memcpy(&ldgm_pt, ldgm_out_buffer, sizeof(ldgm_pt));
ldgm_pt = htonl(ldgm_pt);
assert(ldgm_pt == PT_VIDEO || ldgm_pt == PT_ENCRYPT_VIDEO);
video_payload_hdr_t video_hdr;
memcpy(&video_hdr, ldgm_out_buffer + sizeof(uint32_t),
sizeof(video_payload_hdr_t));
ldgm_out_buffer += sizeof(video_payload_hdr_t) + sizeof(uint32_t);
ldgm_out_len -= sizeof(video_payload_hdr_t) + sizeof(uint32_t);
if(ldgm_pt == PT_ENCRYPT_VIDEO) {
if(!decoder->decrypt) {
fprintf(stderr, ENCRYPTED_ERR);
SKIP_LDGM_FRAME
}
check_for_mode_change(decoder, (uint32_t *)(void *) out_buffer,
&frame);
uint32_t *crypto_hdr = (uint32_t *)(void *) ldgm_out_buffer;
tmp_ui32 = ntohl(crypto_hdr[0]);
uint8_t crypto_type = tmp_ui32 >> 24;
if(!frame) {
ret = FALSE;
goto cleanup;
if(crypto_type != CRYPTO_TYPE_AES128_CTR) {
fprintf(stderr, "Unknown encryption!\n");
}
out_buffer += sizeof(video_payload_hdr_t);
out_len -= sizeof(video_payload_hdr_t);
int ciphertext_len = ldgm_out_len -
sizeof(crypto_payload_hdr_t);
char *plaintext = malloc(ciphertext_len);
char *ciphertext = (char *)
ldgm_out_buffer + sizeof(crypto_payload_hdr_t);
int plaintext_len;
if((plaintext_len = openssl_decrypt(decoder->decrypt, ciphertext,
ciphertext_len,
ldgm_hdr, sizeof(video_payload_hdr_t) + sizeof(uint32_t),
plaintext)) == 0) {
fprintf(stderr, "Warning: Packet dropped AES - wrong CRC!\n");
free(plaintext);
ret = FALSE; goto cleanup;
}
if(decoder->decoder_type == EXTERNAL_DECODER) {
decompress_data->buffer_len[pos] = out_len;
decompress_data->decompress_buffer[pos] = out_buffer;
} else { // linedecoder
wait_for_framebuffer_swap(decoder);
free(data->recv_buffers[pos]);
decompress_data->fec_buffers[pos] = data->recv_buffers[pos] =
plaintext;
struct video_frame *out_frame;
int divisor;
ldgm_out_len = plaintext_len;
ldgm_out_buffer = plaintext;
} else {
if(decoder->decrypt) {
fprintf(stderr, NOT_ENCRYPTED_ERR);
SKIP_LDGM_FRAME
}
}
if(!decoder->postprocess) {
out_frame = frame;
} else {
out_frame = decoder->pp_frame;
}
check_for_mode_change(decoder, video_hdr,
&frame);
if (!decoder->merged_fb) {
divisor = decoder->max_substreams;
} else {
divisor = 1;
}
if(!frame) {
SKIP_LDGM_FRAME
}
tile = vf_get_tile(out_frame, pos % divisor);
if(decoder->decoder_type == EXTERNAL_DECODER) {
decompress_data->buffer_len[pos] = ldgm_out_len;
decompress_data->decompress_buffer[pos] = ldgm_out_buffer;
} else { // linedecoder
wait_for_framebuffer_swap(decoder);
struct line_decoder *line_decoder =
&decoder->line_decoder[pos];
struct video_frame *out_frame;
int divisor;
int data_pos = 0;
char *src = out_buffer;
char *dst = tile->data + line_decoder->base_offset;
while(data_pos < (int) out_len) {
line_decoder->decode_line((unsigned char*)dst, (unsigned char *) src, line_decoder->src_linesize,
line_decoder->rshift, line_decoder->gshift,
line_decoder->bshift);
src += line_decoder->src_linesize;
dst += vc_get_linesize(tile->width ,frame->color_spec);
data_pos += line_decoder->src_linesize;
}
if(!decoder->postprocess) {
out_frame = frame;
} else {
out_frame = decoder->pp_frame;
}
if (!decoder->merged_fb) {
divisor = decoder->max_substreams;
} else {
divisor = 1;
}
tile = vf_get_tile(out_frame, pos % divisor);
struct line_decoder *line_decoder =
&decoder->line_decoder[pos];
int data_pos = 0;
char *src = ldgm_out_buffer;
char *dst = tile->data + line_decoder->base_offset;
while(data_pos < (int) ldgm_out_len) {
line_decoder->decode_line((unsigned char*)dst, (unsigned char *) src, line_decoder->src_linesize,
line_decoder->rshift, line_decoder->gshift,
line_decoder->bshift);
src += line_decoder->src_linesize;
dst += vc_get_linesize(tile->width ,frame->color_spec);
data_pos += line_decoder->src_linesize;
}
}
}
@@ -553,7 +612,7 @@ static void decoder_set_video_mode(struct state_decoder *decoder, unsigned int v
}
struct state_decoder *decoder_init(const char *requested_mode, const char *postprocess,
struct display *display)
struct display *display, const char *encryption)
{
struct state_decoder *s;
@@ -577,6 +636,20 @@ struct state_decoder *decoder_init(const char *requested_mode, const char *postp
int video_mode = VIDEO_NORMAL;
if(encryption) {
#ifdef HAVE_CRYPTO
if(openssl_decrypt_init(&s->decrypt,
encryption, MODE_AES128_CTR) != 0) {
fprintf(stderr, "Unable to create decompress!\n");
return NULL;
}
#else
fprintf(stderr, "This " PACKAGE_NAME " version was build "
"without OpenSSL support!\n");
return NULL;
#endif // HAVE_CRYPTO
}
if(requested_mode) {
/* these are data comming from newtork ! */
if(strcasecmp(requested_mode, "help") == 0) {
@@ -765,6 +838,8 @@ void decoder_destroy(struct state_decoder *decoder)
if(!decoder)
return;
openssl_decrypt_destroy(decoder->decrypt);
decoder_remove_display(decoder);
pthread_mutex_destroy(&decoder->lock);
@@ -1292,6 +1367,8 @@ static int check_for_mode_change(struct state_decoder *decoder, uint32_t *hdr, s
return ret;
}
#define SKIP_PACKET ret = FALSE; goto cleanup;
int decode_frame(struct coded_data *cdata, void *decode_data)
{
struct vcodec_state *pbuf_data = (struct vcodec_state *) decode_data;
@@ -1348,13 +1425,14 @@ int decode_frame(struct coded_data *cdata, void *decode_data)
}
int pt;
int contained_pt; // if packed is encrypted it encapsulates other pt
bool buffer_swapped = false;
while (cdata != NULL) {
uint32_t *hdr;
pckt = cdata->data;
pt = pckt->pt;
contained_pt = pt = pckt->pt;
hdr = (uint32_t *)(void *) pckt->data;
data_pos = ntohl(hdr[1]);
tmp = ntohl(hdr[0]);
@@ -1366,6 +1444,10 @@ int decode_frame(struct coded_data *cdata, void *decode_data)
if(pt == PT_VIDEO) {
len = pckt->data_len - sizeof(video_payload_hdr_t);
data = (char *) hdr + sizeof(video_payload_hdr_t);
if(decoder->decrypt) {
fprintf(stderr, NOT_ENCRYPTED_ERR);
SKIP_PACKET
}
} else if (pt == PT_VIDEO_LDGM) {
len = pckt->data_len - sizeof(ldgm_video_payload_hdr_t);
data = (char *) hdr + sizeof(ldgm_video_payload_hdr_t);
@@ -1375,6 +1457,16 @@ int decode_frame(struct coded_data *cdata, void *decode_data)
m = 0x1fff & (tmp >> 6);
c = 0x3f & tmp;
seed = ntohl(hdr[4]);
} else if (pt == PT_ENCRYPT_VIDEO) {
len = pckt->data_len - sizeof(video_payload_hdr_t)
- sizeof(crypto_payload_hdr_t);
data = (char *) hdr + sizeof(video_payload_hdr_t)
+ sizeof(crypto_payload_hdr_t);
contained_pt = PT_VIDEO;
if(!decoder->decrypt) {
fprintf(stderr, ENCRYPTED_ERR);
SKIP_PACKET
}
} else {
fprintf(stderr, "[decoder] Unknown packet type: %d.\n", pckt->pt);
exit_uv(1);
@@ -1411,23 +1503,38 @@ int decode_frame(struct coded_data *cdata, void *decode_data)
buffer_num[substream] = buffer_number;
buffer_len[substream] = buffer_length;
ll_insert(pckt_list[substream], data_pos, len);
if (pt == PT_VIDEO) {
/* Critical section
* each thread *MUST* wait here if this condition is true
*/
check_for_mode_change(decoder, (uint32_t *)(void *)
pckt->data, &frame);
uint32_t *video_header = hdr;
char plaintext[len]; // will be actually shorter
if(pt == PT_ENCRYPT_VIDEO) {
int data_len;
if((data_len = openssl_decrypt(decoder->decrypt,
data, len,
(char *) video_header, sizeof(video_payload_hdr_t),
plaintext)) == 0) {
fprintf(stderr, "Warning: Packet dropped AES - wrong CRC!\n");
goto next_packet;
}
data = (char *) plaintext;
len = data_len;
}
if(pt == PT_VIDEO && !frame) {
if(contained_pt == PT_VIDEO) {
/* Critical section
* each thread *MUST* wait here if this condition is true
*/
check_for_mode_change(decoder, video_header, &frame);
}
if(contained_pt == PT_VIDEO && !frame) {
ret = FALSE;
goto cleanup;
}
if (pt == PT_VIDEO && decoder->decoder_type == LINE_DECODER) {
ll_insert(pckt_list[substream], data_pos, len);
if (contained_pt == PT_VIDEO && decoder->decoder_type == LINE_DECODER) {
if(!buffer_swapped) {
wait_for_framebuffer_swap(decoder);
buffer_swapped = true;
@@ -1528,6 +1635,7 @@ int decode_frame(struct coded_data *cdata, void *decode_data)
len);
}
next_packet:
cdata = cdata->nxt;
}
@@ -1549,7 +1657,7 @@ int decode_frame(struct coded_data *cdata, void *decode_data)
ldgm_data->c = c;
ldgm_data->seed = seed;
ldgm_data->substream_count = decoder->max_substreams;
ldgm_data->pt = pt;
ldgm_data->pt = contained_pt;
ldgm_data->poisoned = false;
memcpy(ldgm_data->buffer_len, buffer_len, sizeof(buffer_len));
memcpy(ldgm_data->buffer_num, buffer_num, sizeof(buffer_num));

View File

@@ -56,7 +56,7 @@ struct tile;
int decode_frame(struct coded_data *compressed_frame, void *decode_data);
struct state_decoder *decoder_init(const char *requested_mode, const char *postprocess,
struct display *display);
struct display *display, const char *encryption);
void decoder_destroy(struct state_decoder *decoder);
bool decoder_register_video_display(struct state_decoder *decoder, struct display *display);

View File

@@ -46,9 +46,11 @@
* Packet formats:
* http://www.sitola.cz/files/4K-packet-format.pdf
*/
#define PT_VIDEO 20
#define PT_AUDIO 21
#define PT_VIDEO_LDGM 22
#define PT_VIDEO 20
#define PT_AUDIO 21
#define PT_VIDEO_LDGM 22
#define PT_ENCRYPT_VIDEO 24
#define PT_ENCRYPT_AUDIO 25
/*
* Video payload
@@ -101,6 +103,8 @@ typedef uint32_t video_payload_hdr_t[6];
*/
typedef uint32_t audio_payload_hdr_t[5];
typedef uint32_t ldgm_payload_hdr_t;
/*
* LDGM video payload
*
@@ -124,8 +128,19 @@ typedef uint32_t audio_payload_hdr_t[5];
*/
typedef uint32_t ldgm_video_payload_hdr_t[5];
/*
* Crypto video payload
*
* 1st word
* bits 0 - 8 crypto type
* bits 9 - 31 currently unused
*/
#define CRYPTO_TYPE_AES128_CTR 1u
typedef uint32_t crypto_payload_hdr_t[1];
void rtp_recv_callback(struct rtp *session, rtp_event *e);
int handle_with_buffer(struct rtp *session,rtp_event *e);
int check_for_frame_completion(struct rtp *);
void process_packet_for_display(char *);
void call_display_frame(void);

View File

@@ -231,7 +231,6 @@ static void *sender_thread(void *arg) {
struct video_frame *splitted_frames = NULL;
int tile_y_count;
struct video_desc saved_vid_desc;
struct stats *stat_data_sent = stats_new_statistics("data");
tile_y_count = data->connections_count;
memset(&saved_vid_desc, 0, sizeof(saved_vid_desc));
@@ -250,6 +249,11 @@ static void *sender_thread(void *arg) {
pthread_mutex_unlock(&data->priv->lock);
struct module *control_mod = get_module(get_root_module(&data->priv->mod), "control");
struct stats *stat_data_sent = stats_new_statistics((struct control_state *)
control_mod, "data");
unlock_module(control_mod);
while(1) {
pthread_mutex_lock(&data->priv->lock);
struct video_frame *tx_frame = NULL;

View File

@@ -3,6 +3,7 @@
#include <map>
#include <string>
#include "control.h"
#include "compat/platform_spin.h"
#include "debug.h"
#include "messaging.h"
@@ -14,49 +15,42 @@
using namespace std;
static struct response *messaging_callback(struct received_message *msg, void *udata);
struct stats {
public:
stats(string name) {
m_name = name;
m_val = 0;
stats(string name, struct control_state *control)
: m_control(control), m_name(name), m_val(0) {
platform_spin_init(&m_spin);
control_add_stats(control, this);
}
~stats() {
control_remove_stats(m_control, this);
platform_spin_destroy(&m_spin);
}
void update_int(int64_t val) {
platform_spin_lock(&m_spin);
m_val = val;
platform_spin_unlock(&m_spin);
}
struct response *process_message(void *msg) {
struct msg_stats *stats = (struct msg_stats *) msg;
if(string(stats->what).compare(m_name) == 0) {
char buf[128];
snprintf(buf, sizeof(buf), "%lu", m_val);
return new_response(RESPONSE_OK, strdup(buf));
} else {
return NULL;
}
void get_stat(char *buffer, int buffer_len) {
platform_spin_lock(&m_spin);
snprintf(buffer, buffer_len, "%s %lu", m_name.c_str(), m_val);
platform_spin_unlock(&m_spin);
}
private:
string m_name;
int64_t m_val;
void *m_messaging_subscribtion;
struct control_state *m_control;
platform_spin_t m_spin;
};
static struct response *messaging_callback(void *msg, struct module *mod)
struct stats *stats_new_statistics(struct control_state *control, char * name)
{
stats *s = (stats *) mod->priv_data;
return s->process_message(msg);
}
struct stats *stats_new_statistics(char * name)
{
return new stats(string(name));
return new stats(string(name), control);
}
void stats_update_int(struct stats *s, int64_t val)
@@ -64,6 +58,11 @@ void stats_update_int(struct stats *s, int64_t val)
return s->update_int(val);
}
void stats_format(struct stats *s, char *buffer, int buffer_len)
{
s->get_stat(buffer, buffer_len);
}
void stats_destroy(struct stats *s)
{
delete s;

View File

@@ -11,8 +11,12 @@
extern "C" {
#endif
struct stats *stats_new_statistics(char * name);
struct control_state;
struct stats;
struct stats *stats_new_statistics(struct control_state *control, char * name);
void stats_update_int(struct stats *, int64_t);
void stats_format(struct stats *s, char *buffer, int buffer_len);
void stats_destroy(struct stats *);
#ifdef __cplusplus

View File

@@ -62,7 +62,7 @@
#include "audio/audio.h"
#include "audio/codec.h"
#include "audio/utils.h"
#include "messaging.h"
#include "crypto/openssl_encrypt.h"
#include "module.h"
#include "rtp/ldgm.h"
#include "rtp/rtp.h"
@@ -72,7 +72,6 @@
#include "host.h"
#include "video_codec.h"
#include "compat/platform_spin.h"
#include "compat/platform_time.h"
#define TRANSMIT_MAGIC 0xe80ab15f
@@ -138,8 +137,9 @@ struct tx {
int last_fragment;
void *messaging_subscription;
platform_spin_t spin;
struct openssl_encrypt *encryption;
};
static bool fec_is_ldgm(struct tx *tx)
@@ -180,11 +180,12 @@ static void tx_update(struct tx *tx, struct tile *tile)
}
}
struct tx *tx_init(struct module *parent, unsigned mtu, enum tx_media_type media_type, char *fec)
struct tx *tx_init(struct module *parent, unsigned mtu, enum tx_media_type media_type,
char *fec, const char *encryption)
{
struct tx *tx;
tx = (struct tx *)malloc(sizeof(struct tx));
tx = (struct tx *) calloc(1, sizeof(struct tx));
if (tx != NULL) {
module_init_default(&tx->mod);
tx->mod.cls = MODULE_CLASS_TX;
@@ -208,6 +209,20 @@ struct tx *tx_init(struct module *parent, unsigned mtu, enum tx_media_type media
return NULL;
}
}
if(encryption) {
#ifdef HAVE_CRYPTO
if(openssl_encrypt_init(&tx->encryption,
encryption, MODE_AES128_CTR) != 0) {
fprintf(stderr, "Unable to initialize encryption\n");
return NULL;
}
#else
fprintf(stderr, "This " PACKAGE_NAME " version was build "
"without OpenSSL support!\n");
return NULL;
#endif // HAVE_CRYPTO
}
platform_spin_init(&tx->spin);
module_register(&tx->mod, parent);
@@ -372,17 +387,42 @@ tx_send_tile(struct tx *tx, struct video_frame *frame, int pos, struct rtp *rtp_
platform_spin_unlock(&tx->spin);
}
static uint32_t format_interl_fps_hdr_row(enum interlacing_t interlacing, double input_fps)
{
unsigned int fpsd, fd, fps, fi;
uint32_t tmp;
tmp = interlacing << 29;
fps = round(input_fps);
fpsd = 1;
if(fabs(input_fps - round(input_fps) / 1.001) < 0.005)
fd = 1;
else
fd = 0;
fi = 0;
tmp |= fps << 19;
tmp |= fpsd << 15;
tmp |= fd << 14;
tmp |= fi << 13;
return htonl(tmp);
}
static void
tx_send_base(struct tx *tx, struct tile *tile, struct rtp *rtp_session,
uint32_t ts, int send_m,
codec_t color_spec, double input_fps,
codec_t color_spec, double fps,
enum interlacing_t interlacing, unsigned int substream,
int fragment_offset)
{
int m, data_len;
// see definition in rtp_callback.h
video_payload_hdr_t video_hdr;
ldgm_video_payload_hdr_t ldgm_hdr;
uint32_t hdr_data[100];
uint32_t *ldgm_payload_hdr = hdr_data;
uint32_t *video_hdr = ldgm_payload_hdr + 1;
uint32_t *ldgm_hdr = video_hdr + sizeof(video_payload_hdr_t)/sizeof(uint32_t);
uint32_t *encryption_hdr;
int pt = PT_VIDEO; /* A value specified in our packet format */
char *data;
unsigned int pos;
@@ -395,11 +435,10 @@ tx_send_base(struct tx *tx, struct tile *tile, struct rtp *rtp_session,
#endif
long delta;
uint32_t tmp;
unsigned int fps, fpsd, fd, fi;
int mult_pos[FEC_MAX_MULT];
int mult_index = 0;
int mult_first_sent = 0;
int hdrs_len = 40 + (sizeof(video_payload_hdr_t));
int hdrs_len = 40 + (sizeof(video_payload_hdr_t)); // for computing max payload size
char *data_to_send;
int data_to_send_len;
@@ -423,6 +462,24 @@ tx_send_base(struct tx *tx, struct tile *tile, struct rtp *rtp_session,
m = 0;
pos = 0;
char *rtp_hdr;
int rtp_hdr_len;
if(tx->encryption && !fec_is_ldgm(tx)) {
/*
* Important
* Crypto and video header must be in specified order placed one right after
* the another since both will be sent as a RTP header.
*/
encryption_hdr = video_hdr + sizeof(video_payload_hdr_t)/sizeof(uint32_t);
encryption_hdr[0] = htonl(CRYPTO_TYPE_AES128_CTR << 24);
hdrs_len += sizeof(crypto_payload_hdr_t) + openssl_get_overhead(tx->encryption);
rtp_hdr = (char *) video_hdr;
rtp_hdr_len = sizeof(crypto_payload_hdr_t) + sizeof(video_payload_hdr_t);
pt = PT_ENCRYPT_VIDEO;
}
video_hdr[3] = htonl(tile->width << 16 | tile->height);
video_hdr[4] = get_fourcc(color_spec);
video_hdr[2] = htonl(data_to_send_len);
@@ -431,28 +488,39 @@ tx_send_base(struct tx *tx, struct tile *tile, struct rtp *rtp_session,
video_hdr[0] = htonl(tmp);
/* word 6 */
tmp = interlacing << 29;
fps = round(input_fps);
fpsd = 1;
if(fabs(input_fps - round(input_fps) / 1.001) < 0.005)
fd = 1;
else
fd = 0;
fi = 0;
tmp |= fps << 19;
tmp |= fpsd << 15;
tmp |= fd << 14;
tmp |= fi << 13;
video_hdr[5] = htonl(tmp);
char *hdr;
int hdr_len;
video_hdr[5] = format_interl_fps_hdr_row(interlacing, fps);
if(fec_is_ldgm(tx)) {
hdrs_len = 40 + (sizeof(ldgm_video_payload_hdr_t));
ldgm_encoder_encode(tx->fec_state, (char *) &video_hdr, sizeof(video_hdr),
tile->data, tile->data_len, &data_to_send, &data_to_send_len);
char *tmp_data = NULL;
char *ldgm_input_data;
int ldgm_input_len;
int ldgm_payload_hdr_len = sizeof(ldgm_payload_hdr_t) + sizeof(video_payload_hdr_t);
if(tx->encryption) {
ldgm_input_len = tile->data_len + sizeof(crypto_payload_hdr_t) +
MAX_CRYPTO_EXCEED;
ldgm_input_data = tmp_data = malloc(ldgm_input_len);
char *ciphertext = tmp_data + sizeof(crypto_payload_hdr_t);
encryption_hdr = (uint32_t *)(void *) tmp_data;
encryption_hdr[0] = htonl(CRYPTO_TYPE_AES128_CTR << 24);
ldgm_payload_hdr[0] = ntohl(PT_ENCRYPT_VIDEO);
#ifdef HAVE_CRYPTO
int ret = openssl_encrypt(tx->encryption,
tile->data, tile->data_len,
(char *) ldgm_payload_hdr, ldgm_payload_hdr_len,
ciphertext);
#endif
ldgm_input_len = sizeof(crypto_payload_hdr_t) + ret;
} else {
ldgm_input_data = tile->data;
ldgm_input_len = tile->data_len;
ldgm_payload_hdr[0] = ntohl(PT_VIDEO);
}
ldgm_encoder_encode(tx->fec_state, (char *) ldgm_payload_hdr,
ldgm_payload_hdr_len,
ldgm_input_data, ldgm_input_len, &data_to_send, &data_to_send_len);
free(tmp_data);
tmp = substream << 22;
tmp |= 0x3fffff & tx->buffer;
// see definition in rtp_callback.h
@@ -466,11 +534,19 @@ tx_send_base(struct tx *tx, struct tile *tile, struct rtp *rtp_session,
pt = PT_VIDEO_LDGM;
hdr = (char *) &ldgm_hdr;
hdr_len = sizeof(ldgm_hdr);
rtp_hdr = (char *) ldgm_hdr;
rtp_hdr_len = sizeof(ldgm_video_payload_hdr_t);
} else if(!tx->encryption) {
rtp_hdr = (char *) video_hdr;
rtp_hdr_len = sizeof(video_payload_hdr_t);
}
uint32_t *hdr_offset; // data offset pointer - contains field that needs to be updated
// every cycle
if(fec_is_ldgm(tx)) {
hdr_offset = ldgm_hdr + 1;
} else {
hdr = (char *) &video_hdr;
hdr_len = sizeof(video_hdr);
hdr_offset = video_hdr + 1;
}
do {
@@ -480,11 +556,7 @@ tx_send_base(struct tx *tx, struct tile *tile, struct rtp *rtp_session,
int offset = pos + fragment_offset;
video_hdr[1] = htonl(offset);
if(fec_is_ldgm(tx)) {
ldgm_hdr[1] = htonl(offset);
}
*hdr_offset = htonl(offset);
data = data_to_send + pos;
data_len = tx->mtu - hdrs_len;
@@ -498,14 +570,24 @@ tx_send_base(struct tx *tx, struct tile *tile, struct rtp *rtp_session,
pos += data_len;
GET_STARTTIME;
if(data_len) { /* check needed for FEC_MULT */
char encrypted_data[data_len + MAX_CRYPTO_EXCEED];
if(tx->encryption && tx->fec_scheme != FEC_LDGM) {
data_len = openssl_encrypt(tx->encryption,
data, data_len,
(char *) video_hdr, sizeof(video_payload_hdr_t),
encrypted_data);
data = encrypted_data;
}
rtp_send_data_hdr(rtp_session, ts, pt, m, 0, 0,
hdr, hdr_len,
rtp_hdr, rtp_hdr_len,
data, data_len, 0, 0, 0);
if(m && tx->fec_scheme != FEC_NONE) {
int i;
for(i = 0; i < 5; ++i) {
rtp_send_data_hdr(rtp_session, ts, pt, m, 0, 0,
hdr, hdr_len,
rtp_hdr, rtp_hdr_len,
data, data_len, 0, 0, 0);
}
}
@@ -543,7 +625,7 @@ tx_send_base(struct tx *tx, struct tile *tile, struct rtp *rtp_session,
*/
void audio_tx_send(struct tx* tx, struct rtp *rtp_session, audio_frame2 * buffer)
{
const int pt = PT_AUDIO; /* PT set for audio in our packet format */
int pt; /* PT set for audio in our packet format */
unsigned int pos = 0u,
m = 0u;
int channel;
@@ -551,7 +633,9 @@ void audio_tx_send(struct tx* tx, struct rtp *rtp_session, audio_frame2 * buffer
int data_len;
char *data;
// see definition in rtp_callback.h
audio_payload_hdr_t payload_hdr;
uint32_t hdr_data[100];
uint32_t *audio_hdr = hdr_data;
uint32_t *crypto_hdr = audio_hdr + sizeof(audio_payload_hdr_t) / sizeof(uint32_t);
uint32_t timestamp;
#ifdef HAVE_LINUX
struct timespec start, stop;
@@ -564,12 +648,21 @@ void audio_tx_send(struct tx* tx, struct rtp *rtp_session, audio_frame2 * buffer
int mult_pos[FEC_MAX_MULT];
int mult_index = 0;
int mult_first_sent = 0;
int rtp_hdr_len;
platform_spin_lock(&tx->spin);
timestamp = get_local_mediatime();
perf_record(UVP_SEND, timestamp);
if(tx->encryption) {
rtp_hdr_len = sizeof(crypto_payload_hdr_t) + sizeof(audio_payload_hdr_t);
pt = PT_ENCRYPT_AUDIO;
} else {
rtp_hdr_len = sizeof(audio_payload_hdr_t);
pt = PT_AUDIO; /* PT set for audio in our packet format */
}
for(channel = 0; channel < buffer->ch_count; ++channel)
{
chan_data = buffer->data[channel];
@@ -586,17 +679,17 @@ void audio_tx_send(struct tx* tx, struct rtp *rtp_session, audio_frame2 * buffer
uint32_t tmp;
tmp = channel << 22; /* bits 0-9 */
tmp |= tx->buffer; /* bits 10-31 */
payload_hdr[0] = htonl(tmp);
audio_hdr[0] = htonl(tmp);
payload_hdr[2] = htonl(buffer->data_len[channel]);
audio_hdr[2] = htonl(buffer->data_len[channel]);
/* fourth word */
tmp = (buffer->bps * 8) << 26;
tmp |= buffer->sample_rate;
payload_hdr[3] = htonl(tmp);
audio_hdr[3] = htonl(tmp);
/* fifth word */
payload_hdr[4] = htonl(get_audio_tag(buffer->codec));
audio_hdr[4] = htonl(get_audio_tag(buffer->codec));
do {
if(tx->fec_scheme == FEC_MULT) {
@@ -610,15 +703,25 @@ void audio_tx_send(struct tx* tx, struct rtp *rtp_session, audio_frame2 * buffer
if(channel == buffer->ch_count - 1)
m = 1;
}
payload_hdr[1] = htonl(pos);
audio_hdr[1] = htonl(pos);
pos += data_len;
GET_STARTTIME;
if(data_len) { /* check needed for FEC_MULT */
char encrypted_data[data_len + MAX_CRYPTO_EXCEED];
if(tx->encryption) {
crypto_hdr[0] = htonl(CRYPTO_TYPE_AES128_CTR << 24);
data_len = openssl_encrypt(tx->encryption,
data, data_len,
(char *) audio_hdr, sizeof(audio_payload_hdr_t),
encrypted_data);
data = encrypted_data;
}
rtp_send_data_hdr(rtp_session, timestamp, pt, m, 0, /* contributing sources */
0, /* contributing sources length */
(char *) &payload_hdr, sizeof(payload_hdr),
(char *) audio_hdr, rtp_hdr_len,
data, data_len,
0, 0, 0);
}
@@ -650,3 +753,4 @@ void audio_tx_send(struct tx* tx, struct rtp *rtp_session, audio_frame2 * buffer
platform_spin_unlock(&tx->spin);
}

View File

@@ -64,7 +64,8 @@ enum tx_media_type {
TX_MEDIA_VIDEO
};
struct tx *tx_init(struct module *parent, unsigned mtu, enum tx_media_type media_type, char *fec);
struct tx *tx_init(struct module *parent, unsigned mtu, enum tx_media_type media_type,
char *fec, const char *encryption);
void tx_send_tile(struct tx *tx_session, struct video_frame *frame, int pos, struct rtp *rtp_session);
void tx_send(struct tx *tx_session, struct video_frame *frame, struct rtp *rtp_session);
void audio_tx_send(struct tx *tx_session, struct rtp *rtp_session, audio_frame2 *buffer);

View File

@@ -59,7 +59,6 @@
#include "video_compress/jpeg.h"
#include "libgpujpeg/gpujpeg_encoder.h"
#include "libgpujpeg/gpujpeg_common.h"
#include "messaging.h"
#include "video_codec.h"
#include <pthread.h>
#include <stdlib.h>
@@ -80,7 +79,6 @@ struct compress_jpeg_state {
struct video_desc saved_desc;
int restart_interval;
void *messaging_subscription;
platform_spin_t spin;
};