Compress/send-pass frame through compress pipeline

This commit is contained in:
Martin Pulec
2013-08-08 12:48:22 +02:00
parent 0743129c5f
commit 0c5f8d3518
18 changed files with 512 additions and 338 deletions

View File

@@ -108,6 +108,7 @@ OBJS = @OBJS@ \
src/utils/resource_manager.o \
src/utils/ring_buffer.o \
src/utils/timed_message.o \
src/utils/wait_obj.o \
src/utils/worker.o \
src/vf_split.o \
src/video.o \

View File

@@ -95,9 +95,9 @@ static void *worker(void *arg)
free_message(msg);
}
compress_frame(s->compress, s->frame);
struct video_frame *tx_frame =
compress_frame((struct compress_state *) s->compress,
s->frame, 0);
compress_pop(s->compress);
if(tx_frame) {
tx_send(s->tx, tx_frame, s->network_device);

View File

@@ -73,6 +73,7 @@
#include "rtp/pbuf.h"
#include "sender.h"
#include "stats.h"
#include "utils/wait_obj.h"
#include "video.h"
#include "video_capture.h"
#include "video_display.h"
@@ -723,6 +724,12 @@ void *ultragrid_rtp_receiver_thread(void *arg)
return 0;
}
static void uncompressed_frame_dispose(struct video_frame *frame)
{
struct wait_obj *wait_obj = (struct wait_obj *) frame->dispose_udata;
wait_obj_notify(wait_obj);
}
/**
* This function captures video and possibly compresses it.
* It then delegates sending to another thread.
@@ -736,11 +743,6 @@ static void *capture_thread(void *arg)
struct sender_data sender_data;
memset(&sender_data, 0, sizeof(sender_data));
struct video_frame *tx_frame;
struct audio_frame *audio;
//struct video_frame *splitted_frames = NULL;
int i = 0;
struct compress_state *compression = NULL;
int ret = compress_init(uv_mod, uv->requested_compression, &compression);
if(ret != 0) {
@@ -760,6 +762,10 @@ static void *capture_thread(void *arg)
sender_data.tx_module_state = uv->rxtx_state;
sender_data.send_frame = uv->rxtx->send;
sender_data.uv = uv;
sender_data.video_exporter = uv->video_exporter;
sender_data.compression = compression;
struct wait_obj *wait_obj = wait_obj_init();
if(!sender_init(&sender_data)) {
fprintf(stderr, "Error initializing sender.\n");
@@ -772,34 +778,34 @@ static void *capture_thread(void *arg)
while (!should_exit_sender) {
/* Capture and transmit video... */
tx_frame = vidcap_grab(uv->capture_device, &audio);
struct audio_frame *audio;
struct video_frame *tx_frame = vidcap_grab(uv->capture_device, &audio);
void (*old_dispose)(struct video_frame *) = NULL;
void *old_udata = NULL;
if (tx_frame != NULL) {
if(audio) {
audio_sdi_send(uv->audio, audio);
}
//TODO: Unghetto this
tx_frame = compress_frame(compression, tx_frame, i);
if(!tx_frame)
continue;
//tx_frame = vf_get_copy(tx_frame);
old_dispose = tx_frame->dispose;
old_udata = tx_frame->dispose_udata;
tx_frame->dispose = uncompressed_frame_dispose;
tx_frame->dispose_udata = wait_obj;
wait_obj_reset(wait_obj);
i = (i + 1) % 2;
// Sends frame to compression - this passes it to a sender thread
compress_frame(compression, tx_frame);
video_export(uv->video_exporter, tx_frame);
bool nonblock = true;
/* when sending uncompressed video, we simply post it for send
* and wait until done */
/* for compressed, we do not need to wait because of
* double-buffering of compression */
if(is_compress_none(compression)) {
nonblock = false;
}
sender_post_new_frame(&sender_data, tx_frame, nonblock);
// wait to frame is processed - eg by compress or sender (uncompressed video)
wait_obj_wait(wait_obj);
tx_frame->dispose = old_dispose;
tx_frame->dispose_udata = old_udata;
}
}
compress_frame(compression, NULL); // pass poisoned pill (will go through to the sender)
sender_done(&sender_data);
wait_obj_done(wait_obj);
compress_done:
module_done(CAST_MODULE(compression));

View File

@@ -115,6 +115,7 @@ static void *decompress_thread(void *args);
static void cleanup(struct state_video_decoder *decoder);
static bool parse_video_hdr(uint32_t *hdr, struct video_desc *desc);
namespace {
/**
* Enumerates 2 possibilities how to decode arriving data.
*/
@@ -156,6 +157,74 @@ struct fec {
struct decompress_msg;
struct main_msg;
// message definitions
typedef char *char_p;
typedef struct packet_counter *packet_counter_p;
struct ldgm_msg {
ldgm_msg(int count) : substream_count(count) {
buffer_len = new int[count];
buffer_num = new int[count];
recv_buffers = new char_p[count];
pckt_list = new packet_counter_p[count];
}
~ldgm_msg() {
delete buffer_len;
delete buffer_num;
delete recv_buffers;
for(int i = 0; i < substream_count; ++i) {
pc_destroy(pckt_list[i]);
}
delete pckt_list;
}
int *buffer_len;
int *buffer_num;
char **recv_buffers;
struct packet_counter **pckt_list;
int pt;
int k, m, c, seed;
int substream_count;
bool poisoned;
};
struct decompress_msg {
decompress_msg(int count) {
decompress_buffer = new char_p[count];
fec_buffers = new char_p[count];
buffer_len = new int[count];
buffer_num = new int[count];
}
~decompress_msg() {
delete decompress_buffer;
delete fec_buffers;
delete buffer_len;
delete buffer_num;
}
char **decompress_buffer;
int *buffer_len;
int *buffer_num;
char **fec_buffers;
bool poisoned;
};
enum main_msg_type {
RECONFIGURE,
};
struct main_msg {
virtual ~main_msg(){}
};
struct main_msg_reconfigure : public main_msg {
main_msg_reconfigure(struct video_desc d) : desc(d) {}
struct video_desc desc;
};
struct video_new_prop : public main_msg {
double set_fps;
codec_t codec;
};
}
/**
* @brief Decoder state
*/
@@ -235,73 +304,6 @@ struct state_video_decoder {
struct openssl_decrypt *decrypt; ///< decrypt state
};
// message definitions
typedef char *char_p;
typedef struct packet_counter *packet_counter_p;
struct ldgm_msg {
ldgm_msg(int count) : substream_count(count) {
buffer_len = new int[count];
buffer_num = new int[count];
recv_buffers = new char_p[count];
pckt_list = new packet_counter_p[count];
}
~ldgm_msg() {
delete buffer_len;
delete buffer_num;
delete recv_buffers;
for(int i = 0; i < substream_count; ++i) {
pc_destroy(pckt_list[i]);
}
delete pckt_list;
}
int *buffer_len;
int *buffer_num;
char **recv_buffers;
struct packet_counter **pckt_list;
int pt;
int k, m, c, seed;
int substream_count;
bool poisoned;
};
struct decompress_msg {
decompress_msg(int count) {
decompress_buffer = new char_p[count];
fec_buffers = new char_p[count];
buffer_len = new int[count];
buffer_num = new int[count];
}
~decompress_msg() {
delete decompress_buffer;
delete fec_buffers;
delete buffer_len;
delete buffer_num;
}
char **decompress_buffer;
int *buffer_len;
int *buffer_num;
char **fec_buffers;
bool poisoned;
};
enum main_msg_type {
RECONFIGURE,
};
struct main_msg {
virtual ~main_msg(){}
};
struct main_msg_reconfigure : public main_msg {
main_msg_reconfigure(struct video_desc d) : desc(d) {}
struct video_desc desc;
};
struct video_new_prop : public main_msg {
double set_fps;
codec_t codec;
};
/**
* This function blocks until video frame is displayed and decoder::frame
* can be filled with new data. Until this point, the video frame is not considered

View File

@@ -67,11 +67,11 @@
#include "transmit.h"
#include "vf_split.h"
#include "video.h"
#include "video_compress.h"
#include "video_display.h"
#include "video_export.h"
static struct sender_internal_msg *new_frame_msg(struct video_frame *frame);
static void *sender_thread(void *arg);
static void sender_finish(struct sender_data *data);
static void ultragrid_rtp_send(void *state, struct video_frame *tx_frame);
static void ultragrid_rtp_done(void *state);
static void sage_rxtx_send(void *state, struct video_frame *tx_frame);
@@ -81,9 +81,6 @@ struct sender_priv_data {
struct module mod;
pthread_mutex_t lock;
pthread_cond_t msg_ready_cv;
pthread_cond_t msg_processed_cv;
struct sender_internal_msg *msg;
pthread_t thread_id;
bool paused;
@@ -105,61 +102,6 @@ struct rx_tx sage_rxtx = {
NULL
};
enum sender_msg_type {
FRAME,
QUIT
};
struct sender_internal_msg {
enum sender_msg_type type;
void *data;
void (*deleter)(struct sender_internal_msg *);
};
static struct sender_internal_msg *new_frame_msg(struct video_frame *frame)
{
struct sender_internal_msg *msg = malloc(sizeof(struct sender_internal_msg));
msg->type = FRAME;
msg->deleter = (void (*) (struct sender_internal_msg *)) free;
msg->data = frame;
return msg;
}
void sender_post_new_frame(struct sender_data *data, struct video_frame *frame, bool nonblock) {
pthread_mutex_lock(&data->priv->lock);
while(data->priv->msg) {
pthread_cond_wait(&data->priv->msg_processed_cv, &data->priv->lock);
}
data->priv->msg = new_frame_msg(frame);
pthread_cond_signal(&data->priv->msg_ready_cv);
if(!nonblock) {
// we wait until frame is completed
while(data->priv->msg) {
pthread_cond_wait(&data->priv->msg_processed_cv, &data->priv->lock);
}
}
pthread_mutex_unlock(&data->priv->lock);
}
static void sender_finish(struct sender_data *data) {
pthread_mutex_lock(&data->priv->lock);
while(data->priv->msg) {
pthread_cond_wait(&data->priv->msg_processed_cv, &data->priv->lock);
}
data->priv->msg = malloc(sizeof(struct sender_internal_msg));
data->priv->msg->type = QUIT;
data->priv->msg->deleter = (void (*) (struct sender_internal_msg *)) free;
pthread_cond_signal(&data->priv->msg_ready_cv);
pthread_mutex_unlock(&data->priv->lock);
}
static void sender_process_external_message(struct sender_data *data, struct msg_sender *msg)
{
int ret;
@@ -192,9 +134,6 @@ static void sender_process_external_message(struct sender_data *data, struct msg
bool sender_init(struct sender_data *data) {
data->priv = calloc(1, sizeof(struct sender_priv_data));
pthread_mutex_init(&data->priv->lock, NULL);
pthread_cond_init(&data->priv->msg_ready_cv, NULL);
pthread_cond_init(&data->priv->msg_processed_cv, NULL);
data->priv->msg = NULL;
// we lock and thred unlocks after initialized
pthread_mutex_lock(&data->priv->lock);
@@ -214,12 +153,8 @@ bool sender_init(struct sender_data *data) {
}
void sender_done(struct sender_data *data) {
sender_finish(data);
pthread_join(data->priv->thread_id, NULL);
pthread_mutex_destroy(&data->priv->lock);
pthread_cond_destroy(&data->priv->msg_ready_cv);
pthread_cond_destroy(&data->priv->msg_processed_cv);
free(data->priv);
}
@@ -311,34 +246,21 @@ static void *sender_thread(void *arg) {
free_message(msg_external);
}
pthread_mutex_lock(&data->priv->lock);
struct video_frame *tx_frame = NULL;
while(!data->priv->msg) {
pthread_cond_wait(&data->priv->msg_ready_cv, &data->priv->lock);
}
struct sender_internal_msg *msg = data->priv->msg;
switch (msg->type) {
case QUIT:
data->priv->msg = NULL;
msg->deleter(msg);
pthread_cond_broadcast(&data->priv->msg_processed_cv);
pthread_mutex_unlock(&data->priv->lock);
goto exit;
case FRAME:
tx_frame = msg->data;
break;
default:
abort();
}
pthread_mutex_unlock(&data->priv->lock);
tx_frame = compress_pop(data->compression);
if (!tx_frame)
goto exit;
if(data->priv->paused) {
goto after_send;
}
video_export(data->video_exporter, tx_frame);
data->send_frame(data->tx_module_state, tx_frame);
if (tx_frame->dispose)
tx_frame->dispose(tx_frame);
after_send:
@@ -348,13 +270,6 @@ after_send:
rtp_get_bytes_sent(rtp_state->network_devices[0]));
}
pthread_mutex_lock(&data->priv->lock);
data->priv->msg = NULL;
msg->deleter(msg);
pthread_cond_broadcast(&data->priv->msg_processed_cv);
pthread_mutex_unlock(&data->priv->lock);
}
exit:

View File

@@ -71,6 +71,7 @@ struct received_message;
struct response;
struct sender_msg;
struct sender_priv_data;
struct video_compress;
enum rxtx_protocol {
ULTRAGRID_RTP,
@@ -93,6 +94,8 @@ struct sender_data {
void *tx_module_state;
struct state_uv *uv;
struct sender_priv_data *priv;
struct video_export *video_exporter;
struct compress_state *compression;
};
extern struct rx_tx ultragrid_rtp;
@@ -112,7 +115,6 @@ struct sage_rxtx_state {
bool sender_init(struct sender_data *data);
void sender_done(struct sender_data *data);
void sender_post_new_frame(struct sender_data *data, struct video_frame *frame, bool nonblock);
#endif // SENDER_H_

View File

@@ -133,11 +133,25 @@ struct video_frame {
unsigned int frame_fragment_id:14;
/// @}
/// @{
/**
* This function (if defined) is called when frame is no longer needed
* by processing queue.
* @note
* Currently, this is only used in sending workflow, not the receiving one!
* Can be called from arbitrary thread.
*/
void (*dispose)(struct video_frame *);
/**
* Additional data needed to dispose the frame
*/
void *dispose_udata;
/**
* This function (if defined) is called by vf_free() to destruct video data
* (@ref tile::data members).
*/
void (*data_deleter)(struct video_frame *);
/// @}
};
/**

68
src/utils/wait_obj.cpp Normal file
View File

@@ -0,0 +1,68 @@
/**
* @file utils/wait_obj.h
* @author Martin Pulec <pulec@cesnet.cz>
*/
/*
* Copyright (c) 2013 CESNET z.s.p.o.
* All rights reserved.
*
* 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. Neither the name of 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.
*/
#include "config.h"
#include "config_unix.h"
#include "config_win32.h"
#include "utils/wait_obj.h"
struct wait_obj *wait_obj_init()
{
return new wait_obj;
}
void wait_obj_reset(struct wait_obj *wait_obj)
{
wait_obj->reset();
}
void wait_obj_wait(struct wait_obj *wait_obj)
{
wait_obj->wait();
}
void wait_obj_notify(struct wait_obj *wait_obj)
{
wait_obj->notify();
}
void wait_obj_done(struct wait_obj *wait_obj)
{
delete wait_obj;
}

94
src/utils/wait_obj.h Normal file
View File

@@ -0,0 +1,94 @@
/**
* @file utils/wait_obj.h
* @author Martin Pulec <pulec@cesnet.cz>
*/
/*
* Copyright (c) 2013 CESNET z.s.p.o.
* All rights reserved.
*
* 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. Neither the name of 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 UTILS_WAIT_OBJ_H_
#define UTILS_WAIT_OBJ_H_
#ifdef __cplusplus
#include "utils/lock_guard.h"
struct wait_obj {
public:
wait_obj() : m_val(false) {
pthread_mutex_init(&m_lock, NULL);
pthread_cond_init(&m_cv, NULL);
}
~wait_obj() {
pthread_mutex_destroy(&m_lock);
pthread_cond_destroy(&m_cv);
}
void wait() {
lock_guard guard(m_lock);
while (!m_val)
pthread_cond_wait(&m_cv, &m_lock);
}
void reset() {
lock_guard guard(m_lock);
m_val = false;
}
void notify() {
lock_guard guard(m_lock);
m_val = true;
pthread_cond_signal(&m_cv);
}
private:
pthread_mutex_t m_lock;
pthread_cond_t m_cv;
bool m_val;
};
#endif // __cplusplus
struct wait_obj;
//
// C wrapper
//
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
struct wait_obj *wait_obj_init(void);
void wait_obj_reset(struct wait_obj *);
void wait_obj_wait(struct wait_obj *);
void wait_obj_notify(struct wait_obj *);
void wait_obj_done(struct wait_obj *);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // VIDEO_H_

View File

@@ -57,8 +57,10 @@
#include "video_compress/none.h"
#include "video_compress/uyvy.h"
#include "lib_common.h"
#include "utils/message_queue.h"
#include "utils/worker.h"
namespace {
/* *_str are symbol names inside library */
/**
* @brief This struct describes individual compress module
@@ -81,6 +83,12 @@ struct compress_t {
const char *compress_frame_str;
compress_tile_t compress_tile_func; ///< compress function for Tile API
const char *compress_tile_str;
/**
* Async readback function.
* If not defined, synchronous API is supposed.
*/
compress_pop_t compress_pop_func;
const char *compress_pop_str;
void *handle; ///< for modular build, dynamically loaded library handle
};
@@ -99,8 +107,17 @@ struct compress_state_real {
* uses tile API. In this case returned tiles are
* arranged to frame.
* @see compress_t */
message_queue *queue;
int buffer_index;
};
struct msg_frame : public msg {
msg_frame(struct video_frame *f) : frame(f) {}
struct video_frame *frame;
};
}
/**
* @brief Video compress state.
*
@@ -140,6 +157,7 @@ struct compress_t compress_modules[] = {
MK_NAME(fastdxt_init),
MK_NAME(NULL),
MK_NAME(fastdxt_compress_tile),
MK_NAME(NULL),
NULL
},
#endif
@@ -150,6 +168,7 @@ struct compress_t compress_modules[] = {
MK_NAME(dxt_glsl_compress_init),
MK_NAME(dxt_glsl_compress),
MK_NAME(NULL),
MK_NAME(NULL),
NULL
},
#endif
@@ -160,6 +179,7 @@ struct compress_t compress_modules[] = {
MK_NAME(jpeg_compress_init),
MK_NAME(jpeg_compress),
MK_NAME(NULL),
MK_NAME(NULL),
NULL
},
#endif
@@ -170,6 +190,7 @@ struct compress_t compress_modules[] = {
MK_NAME(uyvy_compress_init),
MK_NAME(uyvy_compress),
MK_NAME(NULL),
MK_NAME(NULL),
NULL
},
#endif
@@ -180,6 +201,7 @@ struct compress_t compress_modules[] = {
MK_NAME(libavcodec_compress_init),
MK_NAME(NULL),
MK_NAME(libavcodec_compress_tile),
MK_NAME(NULL),
NULL
},
#endif
@@ -190,6 +212,7 @@ struct compress_t compress_modules[] = {
MK_NAME(cuda_dxt_compress_init),
MK_NAME(NULL),
MK_NAME(cuda_dxt_compress_tile),
MK_NAME(NULL),
NULL
},
#endif
@@ -199,6 +222,7 @@ struct compress_t compress_modules[] = {
MK_STATIC(none_compress_init),
MK_STATIC(none_compress),
MK_STATIC(NULL),
MK_NAME(NULL),
NULL
},
};
@@ -341,7 +365,7 @@ int compress_init(struct module *parent, const char *config_string, struct compr
struct compress_state_real *s;
compress_state_proxy *proxy;
proxy = malloc(sizeof(compress_state_proxy));
proxy = (compress_state_proxy *) malloc(sizeof(compress_state_proxy));
module_init_default(&proxy->mod);
proxy->mod.cls = MODULE_CLASS_COMPRESS;
@@ -374,11 +398,11 @@ static int compress_init_real(struct module *parent, const char *config_string,
struct compress_state_real **state)
{
struct compress_state_real *s;
char *compress_options = NULL;
if(!config_string)
const char *compress_options = NULL;
if(!config_string)
return -1;
if(strcmp(config_string, "help") == 0)
{
show_compress_help();
@@ -386,15 +410,17 @@ static int compress_init_real(struct module *parent, const char *config_string,
}
pthread_once(&compression_list_initialized, init_compressions);
s = (struct compress_state_real *) calloc(1, sizeof(struct compress_state_real));
s->queue = new message_queue(1);
s->state_count = 1;
int i;
for(i = 0; i < compress_modules_count; ++i) {
if(strncasecmp(config_string, available_compress_modules[i]->name,
strlen(available_compress_modules[i]->name)) == 0) {
s->handle = available_compress_modules[i];
if(config_string[strlen(available_compress_modules[i]->name)] == ':')
if(config_string[strlen(available_compress_modules[i]->name)] == ':')
compress_options = config_string +
strlen(available_compress_modules[i]->name) + 1;
else
@@ -409,7 +435,7 @@ static int compress_init_real(struct module *parent, const char *config_string,
strncpy(s->compress_options, compress_options, sizeof(s->compress_options) - 1);
s->compress_options[sizeof(s->compress_options) - 1] = '\0';
if(s->handle->init_func) {
s->state = calloc(1, sizeof(struct module *));
s->state = (struct module **) calloc(1, sizeof(struct module *));
s->state[0] = s->handle->init_func(parent, s->compress_options);
if(!s->state[0]) {
fprintf(stderr, "Compression initialization failed: %s\n", config_string);
@@ -457,27 +483,45 @@ const char *get_compress_name(compress_state_proxy *proxy)
* same index.
* @return compressed frame, may be NULL if compression failed
*/
struct video_frame *compress_frame(compress_state_proxy *proxy, struct video_frame *frame, int buffer_index)
void compress_frame(compress_state_proxy *proxy, struct video_frame *frame)
{
struct video_frame *ret;
if(!proxy)
return NULL;
if (!proxy)
abort();
struct compress_state_real *s = proxy->ptr;
if (frame == NULL) { // pass poisoned pill
s->queue->push(new msg_frame(NULL));
return;
}
struct msg_change_compress_data *msg = NULL;
while ((msg = (struct msg_change_compress_data *) check_message(&proxy->mod))) {
compress_process_message(proxy, msg);
}
struct compress_state_real *s = proxy->ptr;
struct video_frame *sync_api_frame;
if(s->handle->compress_frame_func) {
ret = s->handle->compress_frame_func(s->state[0], frame, buffer_index);
sync_api_frame = s->handle->compress_frame_func(s->state[0], frame, s->buffer_index);
} else if(s->handle->compress_tile_func) {
ret = compress_frame_tiles(s, frame, buffer_index, &proxy->mod);
sync_api_frame = compress_frame_tiles(s, frame, s->buffer_index, &proxy->mod);
} else {
ret = NULL;
sync_api_frame = NULL;
}
return ret;
s->buffer_index = (s->buffer_index + 1) % 2;
// returned frame is different, so we may dispose the previous one
if (sync_api_frame != frame) {
frame->dispose(frame);
}
msg_frame *frame_msg;
if (s->handle->compress_pop_func) {
abort(); // not yet implemented
} else {
frame_msg = new msg_frame(sync_api_frame);
}
s->queue->push(frame_msg);
}
/**
@@ -489,7 +533,7 @@ struct video_frame *compress_frame(compress_state_proxy *proxy, struct video_fra
* @brief Auxiliary structure passed to worker thread.
*/
struct compress_worker_data {
void *state; ///< compress driver status
struct module *state; ///< compress driver status
struct tile *tile; ///< uncompressed tile to be compressed
struct video_desc desc; ///< IN - src video description; OUT - compressed description
int buffer_index; ///< buffer index @see compress_frame
@@ -531,7 +575,7 @@ static void vf_write_desc(struct video_frame *buf, struct video_desc desc)
/**
* Compresses video frame with tiles API
*
*
* @param[in] s compress state
* @param[in] frame uncompressed frame
* @param buffer_index 0 or 1 - driver should have 2 output buffers, filling the selected one.
@@ -544,7 +588,7 @@ static struct video_frame *compress_frame_tiles(struct compress_state_real *s, s
int buffer_index, struct module *parent)
{
if(frame->tile_count != s->state_count) {
s->state = realloc(s->state, frame->tile_count * sizeof(struct module *));
s->state = (struct module **) realloc(s->state, frame->tile_count * sizeof(struct module *));
for(unsigned int i = s->state_count; i < frame->tile_count; ++i) {
s->state[i] = s->handle->init_func(parent, s->compress_options);
if(!s->state[i]) {
@@ -575,7 +619,8 @@ static struct video_frame *compress_frame_tiles(struct compress_state_real *s, s
}
for(unsigned int i = 0; i < frame->tile_count; ++i) {
struct compress_worker_data *data = wait_task(task_handle[i]);
struct compress_worker_data *data = (struct compress_worker_data *)
wait_task(task_handle[i]);
if(i == 0) { // update metadata from first tile
data->desc.tile_count = frame->tile_count;
@@ -604,7 +649,7 @@ static void compress_done(struct module *mod)
if(!mod)
return;
compress_state_proxy *proxy = mod->priv_data;
compress_state_proxy *proxy = (compress_state_proxy *) mod->priv_data;
struct compress_state_real *s = proxy->ptr;
compress_done_real(s);
@@ -625,19 +670,28 @@ static void compress_done_real(struct compress_state_real *s)
module_done(s->state[i]);
}
free(s->state);
delete s->queue;
free(s);
}
/**
* @brief Returns whether we are using dummy (none) compression or not.
* @param proxy video compress state
* @retval TRUE video compress is a dummy one
* @retval FALSE We are using some non-trivial video compression.
*/
int is_compress_none(compress_state_proxy *proxy)
struct video_frame *compress_pop(compress_state_proxy *proxy)
{
assert(proxy != NULL);
struct video_frame *ret = NULL;
if(!proxy)
return NULL;
return strcmp("none", get_compress_name(proxy)) == 0 ? TRUE : FALSE;
struct compress_state_real *s = proxy->ptr;
if(s->handle->compress_pop_func) {
// ret = s->handle->compress_pop_func(s->state[0], frame, buffer_index);
} else {
msg *message = s->queue->pop();
msg_frame *frame_msg = dynamic_cast<msg_frame *>(message);
assert(frame_msg != NULL);
ret = frame_msg->frame;
delete frame_msg;
}
return ret;
}

View File

@@ -90,15 +90,23 @@ typedef struct video_frame * (*compress_frame_t)(struct module *state, struct v
*/
typedef struct tile * (*compress_tile_t)(struct module *state, struct tile *tile,
struct video_desc *desc, int buffer_index);
/**
* @brief Gets back tile/frame from driver
*
* @param[in] state driver internal state
* @param[out] desc output video desc (only for tiles - for frames this is directly in metadata_
* @retval !=NULL compressed tile/frame
* @retval NULL signal that queue has finished
*/
typedef void * (*compress_pop_t)(struct module *state, struct video_desc *desc);
/// @}
void show_compress_help(void);
int compress_init(struct module *parent, const char *config_string, struct compress_state **);
const char *get_compress_name(struct compress_state *);
int is_compress_none(struct compress_state *);
struct video_frame *compress_frame(struct compress_state *, struct video_frame*, int buffer_index);
void compress_frame(struct compress_state *, struct video_frame*);
struct video_frame *compress_pop(struct compress_state *);
#ifdef __cplusplus
}

View File

@@ -1,32 +1,25 @@
/*
* FILE: dxt_glsl_compress.h
* AUTHORS: 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>
/**
* @file video_compress/dxt_glsl.h
* @author Martin Pulec <pulec@cesnet.cz>
*
* Copyright (c) 2005-2010 CESNET z.s.p.o.
* @brief This is an umbrella header for video functions.
*/
/*
* Copyright (c) 2011-2013 CESNET z.s.p.o.
* All rights reserved.
*
* 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 CESNET z.s.p.o.
*
* 4. Neither the name of the CESNET nor the names of its contributors may be
*
* 3. Neither the name of CESNET nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
@@ -42,9 +35,9 @@
* 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"
@@ -54,6 +47,14 @@
struct video_frame;
struct module;
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
struct module *dxt_glsl_compress_init(struct module *parent, const char *opts);
struct video_frame *dxt_glsl_compress(struct module *mod, struct video_frame * tx, int buffer_index);
#ifdef __cplusplus
}
#endif // __cplusplus

View File

@@ -1,32 +1,25 @@
/*
* FILE: video_compress.h
* AUTHORS: 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>
/**
* @file video_compress/fastdxt.h
* @author Martin Pulec <pulec@cesnet.cz>
*
* Copyright (c) 2005-2010 CESNET z.s.p.o.
* @brief This is an umbrella header for video functions.
*/
/*
* Copyright (c) 2011-2013 CESNET z.s.p.o.
* All rights reserved.
*
* 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 CESNET z.s.p.o.
*
* 4. Neither the name of the CESNET nor the names of its contributors may be
*
* 3. Neither the name of CESNET nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
@@ -42,7 +35,6 @@
* 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
@@ -51,10 +43,18 @@
#include "config_win32.h"
#endif // HAVE_CONFIG_H
struct modul;
struct module;
struct tile;
struct video_desc;
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
struct module *fastdxt_init(struct module *parent, const char *num_threads_str);
struct tile *fastdxt_compress_tile(struct module *mod, struct tile * tx, struct video_desc *desc, int buffer_index);
#ifdef __cplusplus
}
#endif // __cplusplus

View File

@@ -1,32 +1,25 @@
/*
* FILE: dxt_glsl_compress.h
* AUTHORS: 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>
/**
* @file video_compress/jpeg.h
* @author Martin Pulec <pulec@cesnet.cz>
*
* Copyright (c) 2005-2010 CESNET z.s.p.o.
* @brief This is an umbrella header for video functions.
*/
/*
* Copyright (c) 2011-2013 CESNET z.s.p.o.
* All rights reserved.
*
* 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 CESNET z.s.p.o.
*
* 4. Neither the name of the CESNET nor the names of its contributors may be
*
* 3. Neither the name of CESNET nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
@@ -42,18 +35,26 @@
* 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 __cplusplus
extern "C" {
#endif // __cplusplus
struct module;
struct video_frame;
struct module *jpeg_compress_init(struct module *parent, const char *opts);
struct video_frame *jpeg_compress(struct module *mod, struct video_frame * tx, int buffer_index);
#ifdef __cplusplus
}
#endif // __cplusplus

View File

@@ -1,32 +1,25 @@
/*
* FILE: video_compress.h
* AUTHORS: 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>
/**
* @file video_compress/libavcodec.h
* @author Martin Pulec <pulec@cesnet.cz>
*
* Copyright (c) 2005-2010 CESNET z.s.p.o.
* @brief This is an umbrella header for video functions.
*/
/*
* Copyright (c) 2013 CESNET z.s.p.o.
* All rights reserved.
*
* 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 CESNET z.s.p.o.
*
* 4. Neither the name of the CESNET nor the names of its contributors may be
*
* 3. Neither the name of CESNET nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
@@ -42,9 +35,12 @@
* 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 __cplusplus
extern "C" {
#endif // __cplusplus
struct module;
struct tile;
struct video_desc;
@@ -53,3 +49,7 @@ struct module *libavcodec_compress_init(struct module *parent, const char
struct tile *libavcodec_compress_tile(struct module *mod, struct tile *tx, struct video_desc *desc,
int buffer);
#ifdef __cplusplus
}
#endif // __cplusplus

View File

@@ -1,14 +1,16 @@
/**
* @file none.h
* @author Martin Benes <martinbenesh@gmail.com>
* @author Lukas Hejtmanek <xhejtman@ics.muni.cz>
* @author Petr Holub <hopet@ics.muni.cz>
* @author Milos Liska <xliska@fi.muni.cz>
* @author Jiri Matela <matela@ics.muni.cz>
* @author Dalibor Matura <255899@mail.muni.cz>
* @author Martin Pulec <pulec@cesnet.cz>
* @author Ian Wesley-Smith <iwsmith@cct.lsu.edu>
*/
/*
* FILE: none.h
* AUTHORS: 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) 2005-2010 CESNET z.s.p.o.
* Copyright (c) 2005-2013 CESNET z.s.p.o.
*
* Redistribution and use in source and binary forms, with or without
* modification, is permitted provided that the following conditions
@@ -45,11 +47,9 @@
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#include "config_unix.h"
#include "config_win32.h"
#endif // HAVE_CONFIG_H
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
struct module;
struct video_frame;
@@ -57,3 +57,7 @@ struct video_frame;
struct module *none_compress_init(struct module *parent, const char *opts);
struct video_frame *none_compress(struct module *mod, struct video_frame * tx, int buffer_index);
#ifdef __cplusplus
}
#endif // __cplusplus

View File

@@ -1,32 +1,25 @@
/*
* FILE: dxt_glsl_compress.h
* AUTHORS: 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>
/**
* @file video_compress/uyvy.h
* @author Martin Pulec <pulec@cesnet.cz>
*
* Copyright (c) 2005-2010 CESNET z.s.p.o.
* @brief This is an umbrella header for video functions.
*/
/*
* Copyright (c) 2012-2013 CESNET z.s.p.o.
* All rights reserved.
*
* 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 CESNET z.s.p.o.
*
* 4. Neither the name of the CESNET nor the names of its contributors may be
*
* 3. Neither the name of CESNET nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
@@ -42,12 +35,19 @@
* 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 __cplusplus
extern "C" {
#endif // __cplusplus
struct module;
struct video_frame;
struct module *uyvy_compress_init(struct module *parent, const char *opts);
struct video_frame *uyvy_compress(struct module *mod, struct video_frame * tx, int buffer);
#ifdef __cplusplus
}
#endif // __cplusplus

View File

@@ -56,6 +56,8 @@
#include "video_decompress.h"
#include "video_decompress/jpeg.h"
namespace {
struct thread_data {
thread_data() :
m_in(1), m_out(1),
@@ -112,6 +114,8 @@ struct state_decompress_jpeg_to_dxt {
};
} // namespace
static int reconfigure_thread(struct thread_data *s, struct video_desc desc, int ppb);
static void *worker_thread(void *arg)