mirror of
https://github.com/outbackdingo/UltraGrid.git
synced 2026-04-07 19:05:47 +00:00
New packet format for video
+ tons of changes + TODO: fps is now temporarily located in packet. change its location when assesed final position
This commit is contained in:
@@ -314,7 +314,7 @@ ihdtv_send(ihdtv_connection * connection, struct video_frame *tx_frame,
|
||||
packet_1.offset = packet_relative_offset;
|
||||
vector1[0].iov_base = &packet_1;
|
||||
vector1[0].iov_len = 16; // we only use the header
|
||||
vector1[1].iov_base = tile_get(tx_frame, 0, 0)->data + offset_absolut_1;
|
||||
vector1[1].iov_base = vf_get_tile(tx_frame, 0)->data + offset_absolut_1;
|
||||
vector1[1].iov_len = connection->video_data_per_packet;
|
||||
if (sendmsg(connection->tx_socket_1, &msg1, 0) == -1) {
|
||||
perror("Sending data to address 1");
|
||||
@@ -324,7 +324,7 @@ ihdtv_send(ihdtv_connection * connection, struct video_frame *tx_frame,
|
||||
packet_2.offset = packet_relative_offset;
|
||||
vector2[0].iov_base = &packet_2;
|
||||
vector2[0].iov_len = 16; // we only use the header
|
||||
vector2[1].iov_base = tile_get(tx_frame, 0, 0)->data + offset_absolut_2;
|
||||
vector2[1].iov_base = vf_get_tile(tx_frame, 0)->data + offset_absolut_2;
|
||||
vector2[1].iov_len = connection->video_data_per_packet;
|
||||
if (sendmsg(connection->tx_socket_2, &msg2, 0) == -1) {
|
||||
perror("Sending data to address 2");
|
||||
@@ -339,7 +339,7 @@ ihdtv_send(ihdtv_connection * connection, struct video_frame *tx_frame,
|
||||
packet_1.offset = packet_relative_offset;
|
||||
vector1[0].iov_base = &packet_1;
|
||||
vector1[0].iov_len = 16; // we only use the header
|
||||
vector1[1].iov_base = tile_get(tx_frame, 0, 0)->data + offset_absolut_1;
|
||||
vector1[1].iov_base = vf_get_tile(tx_frame, 0)->data + offset_absolut_1;
|
||||
vector1[1].iov_len = connection->video_data_per_last_packet;
|
||||
if (sendmsg(connection->tx_socket_1, &msg1, 0) == -1) {
|
||||
perror("Sending data to address 1");
|
||||
@@ -349,7 +349,7 @@ ihdtv_send(ihdtv_connection * connection, struct video_frame *tx_frame,
|
||||
packet_2.offset = packet_relative_offset;
|
||||
vector2[0].iov_base = &packet_2;
|
||||
vector2[0].iov_len = 16; // we only use the header
|
||||
vector2[1].iov_base = tile_get(tx_frame, 0, 0)->data + offset_absolut_2;
|
||||
vector2[1].iov_base = vf_get_tile(tx_frame, 0)->data + offset_absolut_2;
|
||||
vector2[1].iov_len = connection->video_data_per_last_packet;
|
||||
if (sendmsg(connection->tx_socket_2, &msg2, 0) == -1) {
|
||||
perror("Sending data to address 2");
|
||||
|
||||
@@ -49,9 +49,6 @@
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Revision: 1.30 $
|
||||
* $Date: 2010/02/05 14:06:17 $
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@@ -100,7 +97,8 @@ struct state_uv {
|
||||
struct timeval start_time, curr_time;
|
||||
struct pdb *participants;
|
||||
|
||||
char *decoder_options;
|
||||
char *decoder_mode;
|
||||
char *postprocess;
|
||||
|
||||
uint32_t ts;
|
||||
struct tx *tx;
|
||||
@@ -118,7 +116,8 @@ struct state_uv {
|
||||
|
||||
long packet_rate = 13600;
|
||||
volatile int should_exit = FALSE;
|
||||
static sem_t should_exit_sem;
|
||||
volatile int wait_to_finish = FALSE;
|
||||
volatile int threads_joined = FALSE;
|
||||
|
||||
uint32_t RTT = 0; /* this is computed by handle_rr in rtp_callback */
|
||||
struct video_frame *frame_buffer = NULL;
|
||||
@@ -143,16 +142,20 @@ static void signal_handler(int signal)
|
||||
#endif /* WIN32 */
|
||||
|
||||
void exit_uv(int status) {
|
||||
wait_to_finish = TRUE;
|
||||
should_exit = TRUE;
|
||||
display_finish(uv_state->display_device);
|
||||
platform_sem_post(&should_exit_sem);
|
||||
if(!threads_joined) {
|
||||
display_finish(uv_state->display_device);
|
||||
audio_finish(uv_state->audio);
|
||||
}
|
||||
wait_to_finish = FALSE;
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
/* TODO -c -p -b are deprecated options */
|
||||
printf("\nUsage: uv [-d <display_device>] [-t <capture_device>] [-r <audio_playout>] [-s <audio_caputre>] \n");
|
||||
printf(" [-m <mtu>] [-c] [-i] address(es)\n\n");
|
||||
printf(" [-m <mtu>] [-c] [-i] [-M <video_mode>] [-p <postprocess>] address(es)\n\n");
|
||||
printf
|
||||
("\t-d <display_device> \tselect display device, use '-d help' to get\n");
|
||||
printf("\t \tlist of supported devices\n");
|
||||
@@ -171,6 +174,10 @@ static void usage(void)
|
||||
printf("\n");
|
||||
printf("\t-j <settings> \tJACK Audio Connection Kit settings (see '-j help')\n");
|
||||
printf("\n");
|
||||
printf("\t-M <video_mode> \treceived video mode (eg tiled-4K, stereo, dual)\n");
|
||||
printf("\n");
|
||||
printf("\t-p <postprocess> \tpostprocess module\n");
|
||||
printf("\n");
|
||||
printf("\taddress(es) \tdestination address\n");
|
||||
printf("\n");
|
||||
printf("\t \tIf comma-separated list of addresses\n");
|
||||
@@ -401,10 +408,10 @@ static void *receiver_thread(void *arg)
|
||||
struct timeval last_tile_received;
|
||||
struct state_decoder *dec_state;
|
||||
|
||||
dec_state = decoder_init(uv->decoder_options);
|
||||
dec_state = decoder_init(uv->decoder_mode, uv->postprocess);
|
||||
if(!dec_state) {
|
||||
fprintf(stderr, "Error initializing decoder ('-M' option).\n");
|
||||
should_exit = TRUE;
|
||||
exit_uv(1);
|
||||
} else {
|
||||
decoder_register_video_display(dec_state, uv->display_device);
|
||||
}
|
||||
@@ -511,7 +518,7 @@ static void *sender_thread(void *arg)
|
||||
/* we have more than one connection */
|
||||
if(tile_y_count > 1) {
|
||||
/* it is simply stripping frame */
|
||||
splitted_frames = vf_alloc(1, tile_y_count);
|
||||
splitted_frames = vf_alloc(tile_y_count);
|
||||
}
|
||||
|
||||
while (!should_exit) {
|
||||
@@ -537,7 +544,7 @@ static void *sender_thread(void *arg)
|
||||
vf_split_horizontal(splitted_frames, tx_frame,
|
||||
tile_y_count);
|
||||
for (i = 0; i < tile_y_count; ++i) {
|
||||
tx_send_tile(uv->tx, splitted_frames, 0, i,
|
||||
tx_send_tile(uv->tx, splitted_frames, i,
|
||||
uv->network_devices[i]);
|
||||
}
|
||||
}
|
||||
@@ -600,13 +607,15 @@ int main(int argc, char *argv[])
|
||||
uv = (struct state_uv *)malloc(sizeof(struct state_uv));
|
||||
uv_state = uv;
|
||||
|
||||
uv->audio = NULL;
|
||||
uv->ts = 0;
|
||||
uv->display_device = NULL;
|
||||
uv->requested_display = "none";
|
||||
uv->requested_capture = "none";
|
||||
uv->requested_compression = FALSE;
|
||||
uv->compress_options = NULL;
|
||||
uv->decoder_options = NULL;
|
||||
uv->decoder_mode = NULL;
|
||||
uv->postprocess = NULL;
|
||||
uv->requested_mtu = 0;
|
||||
uv->use_ihdtv_protocol = 0;
|
||||
uv->participants = NULL;
|
||||
@@ -615,10 +624,8 @@ int main(int argc, char *argv[])
|
||||
perf_init();
|
||||
perf_record(UVP_INIT, 0);
|
||||
|
||||
platform_sem_init(&should_exit_sem, 0, 0);
|
||||
|
||||
while ((ch =
|
||||
getopt_long(argc, argv, "d:t:m:r:s:vc:ihj:M:", getopt_options,
|
||||
getopt_long(argc, argv, "d:t:m:r:s:vc:ihj:M:p:", getopt_options,
|
||||
&option_index)) != -1) {
|
||||
switch (ch) {
|
||||
case 'd':
|
||||
@@ -643,7 +650,10 @@ int main(int argc, char *argv[])
|
||||
uv->requested_mtu = atoi(optarg);
|
||||
break;
|
||||
case 'M':
|
||||
uv->decoder_options = optarg;
|
||||
uv->decoder_mode = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
uv->postprocess = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
printf("%s\n", ULTRAGRID_VERSION);
|
||||
@@ -851,7 +861,8 @@ int main(int argc, char *argv[])
|
||||
return EXIT_FAIL_TRANSMIT;
|
||||
}
|
||||
|
||||
if (strcmp("none", uv->requested_display) != 0) {
|
||||
if (strcmp("none", uv->requested_display) != 0 ||
|
||||
uv->postprocess || uv->decoder_mode) {
|
||||
if (pthread_create
|
||||
(&receiver_thread_id, NULL, receiver_thread,
|
||||
(void *)uv) != 0) {
|
||||
@@ -878,12 +889,6 @@ int main(int argc, char *argv[])
|
||||
if (strcmp("none", uv->requested_display) != 0)
|
||||
display_run(uv->display_device);
|
||||
|
||||
platform_sem_wait(&should_exit_sem);
|
||||
/* here we let modules know that they should exit in order to avoid waitin on
|
||||
* semaphores or so. Finishing for video display is signalized in exit_uv because
|
||||
* it occupies this thread */
|
||||
audio_finish(uv->audio);
|
||||
|
||||
if (strcmp("none", uv->requested_display) != 0)
|
||||
pthread_join(receiver_thread_id, NULL);
|
||||
|
||||
@@ -893,6 +898,10 @@ int main(int argc, char *argv[])
|
||||
/* also wait for audio threads */
|
||||
audio_join(uv->audio);
|
||||
|
||||
while(wait_to_finish)
|
||||
;
|
||||
threads_joined = TRUE;
|
||||
|
||||
audio_done(uv->audio);
|
||||
tx_done(uv->tx);
|
||||
destroy_devices(uv->network_devices);
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
struct state_decoder;
|
||||
|
||||
struct video_frame * reconfigure_decoder(struct state_decoder * const decoder, struct video_desc desc,
|
||||
struct tile_info tileinfo,
|
||||
struct video_frame *frame);
|
||||
|
||||
enum decoder_type_t {
|
||||
@@ -85,10 +84,11 @@ struct state_decoder {
|
||||
/* requested values */
|
||||
int requested_pitch;
|
||||
int rshift, gshift, bshift;
|
||||
int max_substreams;
|
||||
|
||||
struct display *display;
|
||||
codec_t *native_codecs;
|
||||
int native_count;
|
||||
size_t native_count;
|
||||
|
||||
/* actual values */
|
||||
enum decoder_type_t decoder_type;
|
||||
@@ -108,25 +108,50 @@ struct state_decoder {
|
||||
struct vo_postprocess *postprocess;
|
||||
struct video_frame *pp_frame;
|
||||
};
|
||||
|
||||
unsigned int video_mode;
|
||||
|
||||
unsigned merged_fb:1;
|
||||
};
|
||||
|
||||
struct state_decoder *decoder_init(char *requested_mode)
|
||||
struct state_decoder *decoder_init(char *requested_mode, char *postprocess)
|
||||
{
|
||||
struct state_decoder *s;
|
||||
|
||||
s = (struct state_decoder *) calloc(1, sizeof(struct state_decoder));
|
||||
s->native_codecs = NULL;
|
||||
s->postprocess = NULL;
|
||||
s->video_mode = VIDEO_NORMAL;
|
||||
|
||||
if(requested_mode) {
|
||||
s->postprocess = vo_postprocess_init(requested_mode);
|
||||
if(!s->postprocess) {
|
||||
fprintf(stderr, "Initializing postprocessor \"%s\" failed.\n", requested_mode);
|
||||
/* these are data comming from newtork ! */
|
||||
if(strcasecmp(requested_mode, "help") == 0) {
|
||||
printf("Video mode options\n\n");
|
||||
printf("-M {tiled-4K | 3D | dual-link }\n");
|
||||
free(s);
|
||||
return NULL;
|
||||
} else if(strcasecmp(requested_mode, "tiled-4K") == 0) {
|
||||
s->video_mode = VIDEO_4K;
|
||||
} else if(strcasecmp(requested_mode, "3D") == 0) {
|
||||
s->video_mode = VIDEO_STEREO;
|
||||
} else if(strcasecmp(requested_mode, "dual-link") == 0) {
|
||||
s->video_mode = VIDEO_DUAL;
|
||||
} else {
|
||||
fprintf(stderr, "[decoder] Unknown video mode (see -M help)\n");
|
||||
free(s);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
s->max_substreams = get_video_mode_tiles_x(s->video_mode)
|
||||
* get_video_mode_tiles_y(s->video_mode);
|
||||
|
||||
if(postprocess) {
|
||||
s->postprocess = vo_postprocess_init(postprocess);
|
||||
if(!s->postprocess) {
|
||||
fprintf(stderr, "Initializing postprocessor \"%s\" failed.\n", postprocess);
|
||||
free(s);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
s->postprocess = NULL;
|
||||
}
|
||||
|
||||
return s;
|
||||
@@ -157,6 +182,9 @@ void decoder_register_video_display(struct state_decoder *decoder, struct displa
|
||||
|
||||
void decoder_destroy(struct state_decoder *decoder)
|
||||
{
|
||||
if(!decoder)
|
||||
return;
|
||||
|
||||
if(decoder->ext_decoder_funcs) {
|
||||
decoder->ext_decoder_funcs->done(decoder->ext_decoder_state);
|
||||
decoder->ext_decoder_funcs = NULL;
|
||||
@@ -180,7 +208,7 @@ void decoder_destroy(struct state_decoder *decoder)
|
||||
}
|
||||
|
||||
static codec_t choose_codec_and_decoder(struct state_decoder * const decoder, struct video_desc desc,
|
||||
struct tile_info tile_info, codec_t *in_codec, decoder_t *decode_line)
|
||||
codec_t *in_codec, decoder_t *decode_line)
|
||||
{
|
||||
codec_t out_codec;
|
||||
*decode_line = NULL;
|
||||
@@ -191,9 +219,9 @@ static codec_t choose_codec_and_decoder(struct state_decoder * const decoder, st
|
||||
*in_codec = UYVY;
|
||||
}
|
||||
|
||||
int native;
|
||||
size_t native;
|
||||
/* first check if the codec is natively supported */
|
||||
for(native = 0; native < decoder->native_count; ++native)
|
||||
for(native = 0u; native < decoder->native_count; ++native)
|
||||
{
|
||||
out_codec = decoder->native_codecs[native];
|
||||
if(out_codec == DVS8 || out_codec == Vuy2)
|
||||
@@ -201,8 +229,7 @@ static codec_t choose_codec_and_decoder(struct state_decoder * const decoder, st
|
||||
if(*in_codec == out_codec) {
|
||||
if((out_codec == DXT1 || out_codec == DXT1_YUV ||
|
||||
out_codec == DXT5)
|
||||
&& (tile_info.x_count > 1 ||
|
||||
tile_info.y_count > 1))
|
||||
&& desc.video_mode != VIDEO_NORMAL)
|
||||
continue; /* it is a exception, see NOTES #1 */
|
||||
if(*in_codec == RGBA || /* another exception - we may change shifts */
|
||||
*in_codec == RGB)
|
||||
@@ -268,12 +295,12 @@ after_decoder_lookup:
|
||||
}
|
||||
|
||||
struct video_frame * reconfigure_decoder(struct state_decoder * const decoder, struct video_desc desc,
|
||||
struct tile_info tile_info,
|
||||
struct video_frame *frame_display)
|
||||
{
|
||||
codec_t out_codec, in_codec;
|
||||
decoder_t decode_line;
|
||||
struct video_frame *frame;
|
||||
int display_mode;
|
||||
|
||||
assert(decoder != NULL);
|
||||
assert(decoder->native_codecs != NULL);
|
||||
@@ -295,23 +322,22 @@ struct video_frame * reconfigure_decoder(struct state_decoder * const decoder, s
|
||||
free(decoder->ext_recv_buffer);
|
||||
decoder->ext_recv_buffer = NULL;
|
||||
}
|
||||
if(decoder->pp_frame) {
|
||||
vo_postprocess_done(decoder->postprocess);
|
||||
decoder->pp_frame = NULL;
|
||||
}
|
||||
|
||||
desc.width *= get_video_mode_tiles_x(decoder->video_mode);
|
||||
desc.height *= get_video_mode_tiles_y(decoder->video_mode);
|
||||
|
||||
out_codec = choose_codec_and_decoder(decoder, desc, tile_info, &in_codec, &decode_line);
|
||||
out_codec = choose_codec_and_decoder(decoder, desc, &in_codec, &decode_line);
|
||||
struct video_desc display_desc = desc;
|
||||
|
||||
if(decoder->postprocess) {
|
||||
decoder->pp_frame = vo_postprocess_reconfigure(decoder->postprocess, desc, tile_info);
|
||||
struct video_desc_ti desc_ti;
|
||||
vo_postprocess_get_out_desc(decoder->postprocess, &desc_ti);
|
||||
desc = desc_ti.desc;
|
||||
tile_info = desc_ti.ti;
|
||||
struct video_desc pp_desc = desc;
|
||||
pp_desc.color_spec = out_codec;
|
||||
decoder->pp_frame = vo_postprocess_reconfigure(decoder->postprocess, pp_desc);
|
||||
vo_postprocess_get_out_desc(decoder->postprocess, &display_desc, &display_mode);
|
||||
}
|
||||
|
||||
struct video_desc cur_desc = desc;
|
||||
cur_desc.color_spec = out_codec;
|
||||
if(!video_desc_eq(decoder->display_desc, cur_desc))
|
||||
display_desc.color_spec = out_codec;
|
||||
if(!video_desc_eq(decoder->display_desc, display_desc))
|
||||
{
|
||||
/*
|
||||
* TODO: put frame should be definitely here. On the other hand, we cannot be sure
|
||||
@@ -319,9 +345,9 @@ struct video_frame * reconfigure_decoder(struct state_decoder * const decoder, s
|
||||
*/
|
||||
//display_put_frame(decoder->display, frame);
|
||||
/* reconfigure VO and give it opportunity to pass us pitch */
|
||||
display_reconfigure(decoder->display, cur_desc);
|
||||
display_reconfigure(decoder->display, display_desc);
|
||||
frame_display = display_get_frame(decoder->display);
|
||||
decoder->display_desc = cur_desc;
|
||||
decoder->display_desc = display_desc;
|
||||
}
|
||||
if(decoder->postprocess) {
|
||||
frame = decoder->pp_frame;
|
||||
@@ -329,7 +355,7 @@ struct video_frame * reconfigure_decoder(struct state_decoder * const decoder, s
|
||||
frame = frame_display;
|
||||
}
|
||||
|
||||
int len = sizeof(int);
|
||||
size_t len = sizeof(int);
|
||||
int ret;
|
||||
ret = display_get_property(decoder->display, DISPLAY_PROPERTY_RSHIFT,
|
||||
&decoder->rshift, &len);
|
||||
@@ -354,20 +380,42 @@ struct video_frame * reconfigure_decoder(struct state_decoder * const decoder, s
|
||||
decoder->requested_pitch = PITCH_DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!decoder->postprocess) { /* otherwise we need postprocessor mode, which we obtained before */
|
||||
ret = display_get_property(decoder->display, DISPLAY_PROPERTY_VIDEO_MODE,
|
||||
&display_mode, &len);
|
||||
if(!ret) {
|
||||
debug_msg("Failed to get video display mode.");
|
||||
display_mode = DISPLAY_PROPERTY_VIDEO_MERGED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int linewidth;
|
||||
if(display_mode == DISPLAY_PROPERTY_VIDEO_SEPARATE_TILES) {
|
||||
linewidth = desc.width / get_video_mode_tiles_x(decoder->video_mode);
|
||||
} else {
|
||||
linewidth = desc.width;
|
||||
}
|
||||
|
||||
|
||||
if(!decoder->postprocess) {
|
||||
if(decoder->requested_pitch == PITCH_DEFAULT)
|
||||
decoder->pitch = vc_get_linesize(desc.width / frame->grid_width, out_codec);
|
||||
decoder->pitch = vc_get_linesize(linewidth, out_codec);
|
||||
else
|
||||
decoder->pitch = decoder->requested_pitch;
|
||||
|
||||
} else {
|
||||
decoder->pitch = vc_get_linesize(desc.width, out_codec);
|
||||
decoder->pitch = vc_get_linesize(linewidth, out_codec);
|
||||
}
|
||||
|
||||
int src_x_tiles = get_video_mode_tiles_x(desc.video_mode);
|
||||
int src_y_tiles = get_video_mode_tiles_y(desc.video_mode);
|
||||
|
||||
if(decoder->decoder_type == LINE_DECODER) {
|
||||
decoder->line_decoder = malloc(tile_info.x_count * tile_info.y_count *
|
||||
decoder->line_decoder = malloc(src_x_tiles * src_y_tiles *
|
||||
sizeof(struct line_decoder));
|
||||
if(frame->grid_width == 1 && frame->grid_height == 1 && tile_info.x_count == 1 && tile_info.y_count == 1) {
|
||||
if(display_mode == DISPLAY_PROPERTY_VIDEO_MERGED && desc.video_mode == VIDEO_NORMAL) {
|
||||
struct line_decoder *out = &decoder->line_decoder[0];
|
||||
out->base_offset = 0;
|
||||
out->src_bpp = get_bpp(in_codec);
|
||||
@@ -381,16 +429,16 @@ struct video_frame * reconfigure_decoder(struct state_decoder * const decoder, s
|
||||
out->src_linesize = vc_get_linesize(desc.width, in_codec);
|
||||
out->dst_linesize = vc_get_linesize(desc.width, out_codec);
|
||||
decoder->merged_fb = TRUE;
|
||||
} else if(frame->grid_width == 1 && frame->grid_height == 1
|
||||
&& (tile_info.x_count != 1 || tile_info.y_count != 1)) {
|
||||
} else if(display_mode == DISPLAY_PROPERTY_VIDEO_MERGED
|
||||
&& desc.video_mode != VIDEO_NORMAL) {
|
||||
int x, y;
|
||||
for(x = 0; x < tile_info.x_count; ++x) {
|
||||
for(y = 0; y < tile_info.y_count; ++y) {
|
||||
for(x = 0; x < src_x_tiles; ++x) {
|
||||
for(y = 0; y < src_y_tiles; ++y) {
|
||||
struct line_decoder *out = &decoder->line_decoder[x +
|
||||
tile_info.x_count * y];
|
||||
out->base_offset = y * (desc.height / tile_info.y_count)
|
||||
src_x_tiles * y];
|
||||
out->base_offset = y * (desc.height / src_y_tiles)
|
||||
* decoder->pitch +
|
||||
vc_get_linesize(x * desc.width / tile_info.x_count, out_codec);
|
||||
vc_get_linesize(x * desc.width / src_x_tiles, out_codec);
|
||||
|
||||
out->src_bpp = get_bpp(in_codec);
|
||||
out->dst_bpp = get_bpp(out_codec);
|
||||
@@ -403,18 +451,18 @@ struct video_frame * reconfigure_decoder(struct state_decoder * const decoder, s
|
||||
|
||||
out->dst_pitch = decoder->pitch;
|
||||
out->src_linesize =
|
||||
vc_get_linesize(desc.width / tile_info.x_count, in_codec);
|
||||
vc_get_linesize(desc.width / src_x_tiles, in_codec);
|
||||
out->dst_linesize =
|
||||
vc_get_linesize(desc.width / tile_info.x_count, out_codec);
|
||||
vc_get_linesize(desc.width / src_x_tiles, out_codec);
|
||||
}
|
||||
}
|
||||
decoder->merged_fb = TRUE;
|
||||
} else if(frame->grid_width == tile_info.x_count && frame->grid_height == tile_info.y_count) {
|
||||
} else if (display_mode == DISPLAY_PROPERTY_VIDEO_SEPARATE_TILES) {
|
||||
int x, y;
|
||||
for(x = 0; x < tile_info.x_count; ++x) {
|
||||
for(y = 0; y < tile_info.y_count; ++y) {
|
||||
for(x = 0; x < src_x_tiles; ++x) {
|
||||
for(y = 0; y < src_y_tiles; ++y) {
|
||||
struct line_decoder *out = &decoder->line_decoder[x +
|
||||
tile_info.x_count * y];
|
||||
src_x_tiles * y];
|
||||
out->base_offset = 0;
|
||||
out->src_bpp = get_bpp(in_codec);
|
||||
out->dst_bpp = get_bpp(out_codec);
|
||||
@@ -424,10 +472,10 @@ struct video_frame * reconfigure_decoder(struct state_decoder * const decoder, s
|
||||
|
||||
out->decode_line = decode_line;
|
||||
out->src_linesize =
|
||||
vc_get_linesize(desc.width / tile_info.x_count, in_codec);
|
||||
vc_get_linesize(desc.width / src_x_tiles, in_codec);
|
||||
out->dst_pitch =
|
||||
out->dst_linesize =
|
||||
vc_get_linesize(desc.width / tile_info.x_count, out_codec);
|
||||
vc_get_linesize(desc.width / src_x_tiles, out_codec);
|
||||
}
|
||||
}
|
||||
decoder->merged_fb = FALSE;
|
||||
@@ -436,18 +484,17 @@ struct video_frame * reconfigure_decoder(struct state_decoder * const decoder, s
|
||||
int buf_size;
|
||||
int i;
|
||||
|
||||
desc.width /= tile_info.x_count;
|
||||
desc.height /= tile_info.y_count;
|
||||
desc.width /= src_x_tiles;
|
||||
desc.height /= src_y_tiles;
|
||||
decoder->ext_decoder_state = decoder->ext_decoder_funcs->init();
|
||||
buf_size = decoder->ext_decoder_funcs->reconfigure(decoder->ext_decoder_state, desc,
|
||||
decoder->rshift, decoder->gshift, decoder->bshift, decoder->pitch, out_codec);
|
||||
|
||||
decoder->ext_recv_buffer = malloc((tile_info.x_count * tile_info.y_count + 1) * sizeof(char *));
|
||||
decoder->total_bytes = calloc(1, (tile_info.x_count * tile_info.y_count) * sizeof(int));
|
||||
for (i = 0; i < tile_info.x_count * tile_info.y_count; ++i)
|
||||
decoder->rshift, decoder->gshift, decoder->bshift, decoder->pitch , out_codec);
|
||||
decoder->ext_recv_buffer = malloc((src_x_tiles * src_y_tiles + 1) * sizeof(char *));
|
||||
decoder->total_bytes = calloc(1, (src_x_tiles * src_y_tiles) * sizeof(int));
|
||||
for (i = 0; i < src_x_tiles * src_y_tiles; ++i)
|
||||
decoder->ext_recv_buffer[i] = malloc(buf_size);
|
||||
decoder->ext_recv_buffer[i] = NULL;
|
||||
if(frame->grid_width == tile_info.x_count && frame->grid_height == tile_info.y_count) {
|
||||
if(display_mode == DISPLAY_PROPERTY_VIDEO_SEPARATE_TILES) {
|
||||
decoder->merged_fb = FALSE;
|
||||
} else {
|
||||
decoder->merged_fb = TRUE;
|
||||
@@ -462,17 +509,18 @@ void decode_frame(struct coded_data *cdata, struct video_frame *frame, struct st
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t offset;
|
||||
uint32_t aux;
|
||||
struct tile_info tile_info;
|
||||
enum interlacing_t interlacing;
|
||||
int len;
|
||||
codec_t color_spec;
|
||||
rtp_packet *pckt;
|
||||
unsigned char *source;
|
||||
payload_hdr_t *hdr;
|
||||
video_payload_hdr_t *hdr;
|
||||
uint32_t data_pos;
|
||||
int prints=0;
|
||||
double fps;
|
||||
struct tile *tile = NULL;
|
||||
uint32_t tmp;
|
||||
uint32_t substream;
|
||||
|
||||
perf_record(UVP_DECODEFRAME, frame);
|
||||
|
||||
@@ -485,25 +533,23 @@ void decode_frame(struct coded_data *cdata, struct video_frame *frame, struct st
|
||||
|
||||
while (cdata != NULL) {
|
||||
pckt = cdata->data;
|
||||
hdr = (payload_hdr_t *) pckt->data;
|
||||
width = ntohs(hdr->width);
|
||||
height = ntohs(hdr->height);
|
||||
color_spec = hdr->colorspc;
|
||||
len = ntohs(hdr->length);
|
||||
hdr = (video_payload_hdr_t *) pckt->data;
|
||||
width = ntohs(hdr->hres);
|
||||
height = ntohs(hdr->vres);
|
||||
color_spec = get_codec_from_fcc(ntohl(hdr->fourcc));
|
||||
len = pckt->data_len - sizeof(video_payload_hdr_t);
|
||||
data_pos = ntohl(hdr->offset);
|
||||
tmp = ntohl(hdr->substream_bufnum_il);
|
||||
interlacing = (enum interlacing_t) (tmp & 0x3);
|
||||
substream = tmp >> 22;
|
||||
fps = ntohl(hdr->fps)/65536.0;
|
||||
aux = ntohl(hdr->aux);
|
||||
tile_info = ntoh_uint2tileinfo(hdr->tileinfo);
|
||||
|
||||
if(aux & AUX_TILED) {
|
||||
width = width * tile_info.x_count;
|
||||
height = height * tile_info.y_count;
|
||||
} else {
|
||||
tile_info.x_count = 1;
|
||||
tile_info.y_count = 1;
|
||||
tile_info.pos_x = 0;
|
||||
tile_info.pos_y = 0;
|
||||
|
||||
if(substream >= decoder->max_substreams) {
|
||||
fprintf(stderr, "[decoder] received substream ID %d. Expecting %d substreams. Did you set -M option?\n", substream, decoder->max_substreams);
|
||||
exit_uv(1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Critical section
|
||||
* each thread *MUST* wait here if this condition is true
|
||||
@@ -511,37 +557,38 @@ void decode_frame(struct coded_data *cdata, struct video_frame *frame, struct st
|
||||
if (!(decoder->received_vid_desc.width == width &&
|
||||
decoder->received_vid_desc.height == height &&
|
||||
decoder->received_vid_desc.color_spec == color_spec &&
|
||||
decoder->received_vid_desc.aux == aux &&
|
||||
decoder->received_vid_desc.interlacing == interlacing &&
|
||||
//decoder->received_vid_desc.video_type == video_type &&
|
||||
decoder->received_vid_desc.fps == fps
|
||||
)) {
|
||||
decoder->received_vid_desc.width = width;
|
||||
decoder->received_vid_desc.height = height;
|
||||
decoder->received_vid_desc.color_spec = color_spec;
|
||||
decoder->received_vid_desc.aux = aux;
|
||||
decoder->received_vid_desc.interlacing = interlacing;
|
||||
decoder->received_vid_desc.video_mode = decoder->video_mode;
|
||||
decoder->received_vid_desc.fps = fps;
|
||||
|
||||
frame = reconfigure_decoder(decoder, decoder->received_vid_desc,
|
||||
tile_info, frame);
|
||||
frame);
|
||||
}
|
||||
|
||||
if(!decoder->postprocess) {
|
||||
if (aux & AUX_TILED && !decoder->merged_fb) {
|
||||
tile = tile_get(frame, tile_info.pos_x, tile_info.pos_y);
|
||||
if (!decoder->merged_fb) {
|
||||
tile = vf_get_tile(frame, substream);
|
||||
} else {
|
||||
tile = tile_get(frame, 0, 0);
|
||||
tile = vf_get_tile(frame, 0);
|
||||
}
|
||||
} else {
|
||||
if (aux & AUX_TILED && !decoder->merged_fb) {
|
||||
tile = tile_get(decoder->pp_frame, tile_info.pos_x, tile_info.pos_y);
|
||||
if (!decoder->merged_fb) {
|
||||
tile = vf_get_tile(decoder->pp_frame, substream);
|
||||
} else {
|
||||
tile = tile_get(decoder->pp_frame, 0, 0);
|
||||
tile = vf_get_tile(decoder->pp_frame, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(decoder->decoder_type == LINE_DECODER) {
|
||||
struct line_decoder *line_decoder =
|
||||
&decoder->line_decoder[tile_info.pos_x +
|
||||
tile_info.pos_y * tile_info.x_count];
|
||||
&decoder->line_decoder[substream];
|
||||
|
||||
/* End of critical section */
|
||||
|
||||
@@ -564,7 +611,7 @@ void decode_frame(struct coded_data *cdata, struct video_frame *frame, struct st
|
||||
line_decoder->dst_bpp;
|
||||
|
||||
/* pointer to data payload in packet */
|
||||
source = (unsigned char*)(pckt->data + sizeof(payload_hdr_t));
|
||||
source = (unsigned char*)(pckt->data + sizeof(video_payload_hdr_t));
|
||||
|
||||
/* copy whole packet that can span several lines.
|
||||
* we need to clip data (v210 case) or center data (RGBA, R10k cases)
|
||||
@@ -617,34 +664,41 @@ void decode_frame(struct coded_data *cdata, struct video_frame *frame, struct st
|
||||
y += line_decoder->dst_pitch; /* next line */
|
||||
}
|
||||
} else if(decoder->decoder_type == EXTERNAL_DECODER) {
|
||||
int pos = tile_info.pos_x + tile_info.x_count * tile_info.pos_y;
|
||||
memcpy(decoder->ext_recv_buffer[pos] + data_pos, (unsigned char*)(pckt->data + sizeof(payload_hdr_t)),
|
||||
//int pos = (substream >> 3) & 0x7 + (substream & 0x7) * frame->grid_width;
|
||||
memcpy(decoder->ext_recv_buffer[substream] + data_pos, (unsigned char*)(pckt->data + sizeof(video_payload_hdr_t)),
|
||||
len);
|
||||
decoder->total_bytes[pos] = max(decoder->total_bytes[pos], data_pos + len);
|
||||
decoder->total_bytes[substream] = max(decoder->total_bytes[substream], data_pos + len);
|
||||
}
|
||||
|
||||
cdata = cdata->nxt;
|
||||
}
|
||||
|
||||
if(decoder->decoder_type == EXTERNAL_DECODER) {
|
||||
int tile_width = decoder->received_vid_desc.width / tile_info.x_count;
|
||||
int tile_height = decoder->received_vid_desc.height / tile_info.y_count;
|
||||
int tile_width = decoder->received_vid_desc.width; // get_video_mode_tiles_x(decoder->video_mode);
|
||||
int tile_height = decoder->received_vid_desc.height; // get_video_mode_tiles_y(decoder->video_mode);
|
||||
int x, y;
|
||||
for (x = 0; x < tile_info.x_count; ++x) {
|
||||
for (y = 0; y < tile_info.y_count; ++y) {
|
||||
struct video_frame *output;
|
||||
if(decoder->postprocess) {
|
||||
output = decoder->pp_frame;
|
||||
} else {
|
||||
output = frame;
|
||||
}
|
||||
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;
|
||||
if(decoder->merged_fb) {
|
||||
tile = tile_get(frame, 0, 0);
|
||||
tile = vf_get_tile(output, 0);
|
||||
out = tile->data + y * decoder->pitch * tile_height +
|
||||
vc_get_linesize(tile_width, decoder->out_codec) * x;
|
||||
} else {
|
||||
tile = tile_get(frame, x, y);
|
||||
tile = vf_get_tile(output, x);
|
||||
out = tile->data;
|
||||
}
|
||||
decoder->ext_decoder_funcs->decompress(decoder->ext_decoder_state,
|
||||
(unsigned char *) out,
|
||||
(unsigned char *) decoder->ext_recv_buffer[x + tile_info.x_count * y],
|
||||
decoder->total_bytes[x + tile_info.x_count * y]);
|
||||
(unsigned char *) decoder->ext_recv_buffer[pos],
|
||||
decoder->total_bytes[pos]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ struct tile;
|
||||
*/
|
||||
void decode_frame(struct coded_data *compressed_frame, struct video_frame *framebuffer, struct state_decoder *s);
|
||||
|
||||
struct state_decoder *decoder_init(char *requested_mode);
|
||||
struct state_decoder *decoder_init(char *requested_mode, char *postprocess);
|
||||
void decoder_destroy(struct state_decoder *decoder);
|
||||
|
||||
void decoder_register_video_display(struct state_decoder *decoder, struct display *display);
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
* http://www.cesnet.cz/doc/techzpravy/2010/4k-packet-format/
|
||||
*/
|
||||
|
||||
#if 0
|
||||
typedef struct {
|
||||
uint16_t width; /* pixels */
|
||||
uint16_t height; /* pixels */
|
||||
@@ -58,6 +59,30 @@ typedef struct {
|
||||
uint32_t aux; /* auxiliary data */
|
||||
uint32_t tileinfo; /* info about tile position (if tiled) */
|
||||
} payload_hdr_t;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
/* first word */
|
||||
uint32_t substream_bufnum_il; /* bits 0 - 9 substream
|
||||
bits 10 - 29 buffer
|
||||
bits 30 - 31 interlace */
|
||||
|
||||
/* second word */
|
||||
uint32_t offset;
|
||||
|
||||
/* third word */
|
||||
uint32_t length;
|
||||
|
||||
/* fourth word */
|
||||
uint16_t hres;
|
||||
uint16_t vres;
|
||||
|
||||
/* fifth word */
|
||||
uint32_t fourcc;
|
||||
|
||||
/* temporary */
|
||||
uint32_t fps;
|
||||
} __attribute__((__packed__)) video_payload_hdr_t;
|
||||
|
||||
typedef struct {
|
||||
/* first word */
|
||||
|
||||
@@ -67,29 +67,25 @@ void vf_split(struct video_frame *out, struct video_frame *src,
|
||||
|
||||
out->color_spec = src->color_spec;
|
||||
out->fps = src->fps;
|
||||
out->aux = src->aux | AUX_TILED;
|
||||
//out->aux = src->aux | AUX_TILED;
|
||||
|
||||
assert(tile_get(src, 0, 0)->width % x_count == 0u && tile_get(src, 0, 0)->height % y_count == 0u);
|
||||
assert(vf_get_tile(src, 0)->width % x_count == 0u && vf_get_tile(src, 0)->height % y_count == 0u);
|
||||
|
||||
for(tile_idx = 0u; tile_idx < x_count * y_count; ++tile_idx) {
|
||||
out->tiles[tile_idx].width = tile_get(src, 0, 0)->width / x_count;
|
||||
out->tiles[tile_idx].height = tile_get(src, 0, 0)->height / y_count;
|
||||
out->tiles[tile_idx].width = vf_get_tile(src, 0)->width / x_count;
|
||||
out->tiles[tile_idx].height = vf_get_tile(src, 0)->height / y_count;
|
||||
|
||||
out->tiles[tile_idx].tile_info.x_count = x_count;
|
||||
out->tiles[tile_idx].tile_info.y_count = y_count;
|
||||
out->tiles[tile_idx].tile_info.pos_x = tile_idx % x_count;
|
||||
out->tiles[tile_idx].tile_info.pos_y = tile_idx / x_count;
|
||||
out->tiles[tile_idx].linesize = vc_get_linesize(out->tiles[tile_idx].width,
|
||||
src->color_spec);
|
||||
out->tiles[tile_idx].data_len = out->tiles[tile_idx].linesize * out->tiles[tile_idx].height;
|
||||
}
|
||||
|
||||
cur_tiles = &out->tiles[0];
|
||||
for(line_idx = 0u; line_idx < tile_get(src, 0, 0)->height; ++line_idx, ++tile_line) {
|
||||
for(line_idx = 0u; line_idx < vf_get_tile(src, 0)->height; ++line_idx, ++tile_line) {
|
||||
unsigned int cur_tile_idx;
|
||||
unsigned int byte = 0u;
|
||||
|
||||
if (line_idx % (tile_get(src, 0, 0)->height / y_count) == 0u) /* next tiles*/
|
||||
if (line_idx % (vf_get_tile(src, 0)->height / y_count) == 0u) /* next tiles*/
|
||||
{
|
||||
tile_line = 0u;
|
||||
if (line_idx != 0u)
|
||||
@@ -123,7 +119,7 @@ void vf_split_horizontal(struct video_frame *out, struct video_frame *src,
|
||||
unsigned int i;
|
||||
|
||||
for(i = 0u; i < y_count; ++i) {
|
||||
out->aux = src->aux | AUX_TILED;
|
||||
//out->aux = src->aux | AUX_TILED;
|
||||
out->fps = src->fps;
|
||||
out->color_spec = src->color_spec;
|
||||
out->tiles[i].width = src->tiles[0].width;
|
||||
|
||||
@@ -48,9 +48,6 @@
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Revision: 1.5.2.6 $
|
||||
* $Date: 2010/02/05 13:56:49 $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -82,8 +79,9 @@ extern long packet_rate;
|
||||
#endif /* HAVE_MACOSX */
|
||||
|
||||
void
|
||||
tx_send_base(struct tx *tx, struct tile *frame, struct rtp *rtp_session, uint32_t ts, int send_m,
|
||||
codec_t color_spec, double fps, int aux);
|
||||
tx_send_base(struct tx *tx, struct tile *tile, struct rtp *rtp_session,
|
||||
uint32_t ts, int send_m, codec_t color_spec, double fps,
|
||||
enum interlacing_t interlacing, unsigned int substream);
|
||||
|
||||
struct tx {
|
||||
uint32_t magic;
|
||||
@@ -122,36 +120,37 @@ tx_send(struct tx *tx, struct video_frame *frame, struct rtp *rtp_session)
|
||||
|
||||
ts = get_local_mediatime();
|
||||
|
||||
for(i = 0; i < frame->grid_width; ++i)
|
||||
for(i = 0; i < frame->tile_count; ++i)
|
||||
{
|
||||
for(j = 0; j < frame->grid_height; ++j) {
|
||||
int last = FALSE;
|
||||
|
||||
if (i == frame->grid_width - 1 &&
|
||||
j == frame->grid_height - 1)
|
||||
last = TRUE;
|
||||
tx_send_base(tx, tile_get(frame, i, j), rtp_session, ts, last,
|
||||
frame->color_spec, frame->fps, frame->aux);
|
||||
}
|
||||
int last = FALSE;
|
||||
|
||||
if (i == frame->tile_count - 1)
|
||||
last = TRUE;
|
||||
tx_send_base(tx, vf_get_tile(frame, i), rtp_session, ts, last,
|
||||
frame->color_spec, frame->fps, frame->interlacing,
|
||||
i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
tx_send_tile(struct tx *tx, struct video_frame *frame, int x_pos, int y_pos, struct rtp *rtp_session)
|
||||
tx_send_tile(struct tx *tx, struct video_frame *frame, int pos, struct rtp *rtp_session)
|
||||
{
|
||||
struct tile *tile;
|
||||
|
||||
tile = tile_get(frame, x_pos, y_pos);
|
||||
tile = vf_get_tile(frame, pos);
|
||||
uint32_t ts = 0;
|
||||
ts = get_local_mediatime();
|
||||
tx_send_base(tx, tile, rtp_session, ts, TRUE, frame->color_spec, frame->fps, frame->aux);
|
||||
tx_send_base(tx, tile, rtp_session, ts, TRUE, frame->color_spec, frame->fps, frame->interlacing, pos);
|
||||
}
|
||||
|
||||
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 fps, int aux)
|
||||
tx_send_base(struct tx *tx, struct tile *tile, struct rtp *rtp_session,
|
||||
uint32_t ts, int send_m, codec_t color_spec, double fps,
|
||||
enum interlacing_t interlacing, unsigned int substream)
|
||||
{
|
||||
int m, data_len;
|
||||
payload_hdr_t payload_hdr;
|
||||
video_payload_hdr_t payload_hdr;
|
||||
int pt = 96; /* A dynamic payload type for the tests... */
|
||||
char *data;
|
||||
unsigned int pos;
|
||||
@@ -161,6 +160,7 @@ tx_send_base(struct tx *tx, struct tile *tile, struct rtp *rtp_session, uint32_t
|
||||
struct timespec start, stop;
|
||||
#endif /* HAVE_MACOSX */
|
||||
long delta;
|
||||
uint32_t tmp;
|
||||
|
||||
assert(tx->magic == TRANSMIT_MAGIC);
|
||||
|
||||
@@ -169,19 +169,21 @@ tx_send_base(struct tx *tx, struct tile *tile, struct rtp *rtp_session, uint32_t
|
||||
m = 0;
|
||||
pos = 0;
|
||||
|
||||
payload_hdr.width = htons(tile->width);
|
||||
payload_hdr.height = htons(tile->height);
|
||||
payload_hdr.colorspc = color_spec;
|
||||
payload_hdr.fps = htonl((int)(fps * 65536));
|
||||
payload_hdr.aux = htonl(aux);
|
||||
payload_hdr.tileinfo = hton_tileinfo2uint(tile->tile_info);
|
||||
payload_hdr.hres = htons(tile->width);
|
||||
payload_hdr.vres = htons(tile->height);
|
||||
payload_hdr.fourcc = htonl(get_fourcc(color_spec));
|
||||
payload_hdr.length = htonl(tile->data_len);
|
||||
payload_hdr.fps = htonl(fps * 65536.0);
|
||||
tmp = substream << 22;
|
||||
tmp |= tx->buffer << 2;
|
||||
tmp |= interlacing;
|
||||
payload_hdr.substream_bufnum_il = htonl(tmp);
|
||||
|
||||
do {
|
||||
payload_hdr.offset = htonl(pos);
|
||||
payload_hdr.flags = htons(1 << 15);
|
||||
|
||||
data = tile->data + pos;
|
||||
data_len = tx->mtu - 40 - (sizeof(payload_hdr_t));
|
||||
data_len = tx->mtu - 40 - (sizeof(video_payload_hdr_t));
|
||||
data_len = (data_len / 48) * 48;
|
||||
if (pos + data_len >= tile->data_len) {
|
||||
if (send_m)
|
||||
@@ -189,10 +191,9 @@ tx_send_base(struct tx *tx, struct tile *tile, struct rtp *rtp_session, uint32_t
|
||||
data_len = tile->data_len - pos;
|
||||
}
|
||||
pos += data_len;
|
||||
payload_hdr.length = htons(data_len);
|
||||
GET_STARTTIME;
|
||||
rtp_send_data_hdr(rtp_session, ts, pt, m, 0, 0,
|
||||
(char *)&payload_hdr, sizeof(payload_hdr_t),
|
||||
(char *)&payload_hdr, sizeof(video_payload_hdr_t),
|
||||
data, data_len, 0, 0, 0);
|
||||
do {
|
||||
GET_STOPTIME;
|
||||
@@ -202,6 +203,8 @@ tx_send_base(struct tx *tx, struct tile *tile, struct rtp *rtp_session, uint32_t
|
||||
} while (packet_rate - delta > 0);
|
||||
|
||||
} while (pos < tile->data_len);
|
||||
|
||||
tx->buffer ++;
|
||||
}
|
||||
|
||||
void audio_tx_send(struct tx* tx, struct rtp *rtp_session, audio_frame * buffer)
|
||||
|
||||
@@ -54,7 +54,7 @@ struct video_frame;
|
||||
|
||||
struct tx *tx_init(unsigned mtu);
|
||||
void tx_done(struct tx *tx_session);
|
||||
void tx_send_tile(struct tx *tx_session, struct video_frame *frame, int x_pos, int y_pos, struct rtp *rtp_session);
|
||||
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_frame *buffer);
|
||||
|
||||
|
||||
@@ -55,32 +55,16 @@
|
||||
#include <string.h>
|
||||
#include "video.h"
|
||||
|
||||
struct video_frame * vf_alloc(int grid_width, int grid_height)
|
||||
struct video_frame * vf_alloc(int count)
|
||||
{
|
||||
struct video_frame *buf;
|
||||
|
||||
buf = (struct video_frame *) malloc(sizeof(struct video_frame));
|
||||
|
||||
buf->tiles = (struct tiles *)
|
||||
calloc(1, sizeof(struct tile) * grid_width *
|
||||
grid_height);
|
||||
buf->grid_width = grid_width;
|
||||
buf->grid_height = grid_height;
|
||||
calloc(1, sizeof(struct tile) * count);
|
||||
buf->tile_count = count;
|
||||
|
||||
int x, y;
|
||||
for(x = 0; x < grid_width; ++x) {
|
||||
for(y = 0; y < grid_height; ++y) {
|
||||
buf->tiles[x + y * grid_width].tile_info.x_count =
|
||||
grid_width;
|
||||
buf->tiles[x + y * grid_width].tile_info.y_count =
|
||||
grid_height;
|
||||
buf->tiles[x + y * grid_width].tile_info.pos_x =
|
||||
x;
|
||||
buf->tiles[x + y * grid_width].tile_info.pos_y =
|
||||
y;
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -92,11 +76,11 @@ void vf_free(struct video_frame *buf)
|
||||
free(buf);
|
||||
}
|
||||
|
||||
struct tile * tile_get(struct video_frame *buf, int grid_x_pos, int grid_y_pos)
|
||||
struct tile * vf_get_tile(struct video_frame *buf, int pos)
|
||||
{
|
||||
assert (grid_x_pos < buf->grid_width && grid_y_pos < buf->grid_height);
|
||||
assert (pos < buf->tile_count);
|
||||
|
||||
return &buf->tiles[grid_x_pos + grid_y_pos * buf->grid_width];
|
||||
return &buf->tiles[pos];
|
||||
}
|
||||
|
||||
int video_desc_eq(struct video_desc a, struct video_desc b)
|
||||
@@ -104,7 +88,56 @@ int video_desc_eq(struct video_desc a, struct video_desc b)
|
||||
return a.width == b.width &&
|
||||
a.height == b.height &&
|
||||
a.color_spec == b.color_spec &&
|
||||
fabs(a.fps - b.fps) < 0.01 &&
|
||||
fabs(a.fps - b.fps) < 0.01;// &&
|
||||
// TODO: remove these obsolete constants
|
||||
(a.aux & (~AUX_RGB & ~AUX_YUV & ~AUX_10Bit)) == (b.aux & (~AUX_RGB & ~AUX_YUV & ~AUX_10Bit));
|
||||
//(a.aux & (~AUX_RGB & ~AUX_YUV & ~AUX_10Bit)) == (b.aux & (~AUX_RGB & ~AUX_YUV & ~AUX_10Bit));
|
||||
}
|
||||
|
||||
int get_video_mode_tiles_x(int video_type)
|
||||
{
|
||||
int ret;
|
||||
switch(video_type) {
|
||||
case VIDEO_NORMAL:
|
||||
case VIDEO_DUAL:
|
||||
ret = 1;
|
||||
break;
|
||||
case VIDEO_4K:
|
||||
case VIDEO_STEREO:
|
||||
ret = 2;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int get_video_mode_tiles_y(int video_type)
|
||||
{
|
||||
int ret;
|
||||
switch(video_type) {
|
||||
case VIDEO_NORMAL:
|
||||
case VIDEO_STEREO:
|
||||
ret = 1;
|
||||
break;
|
||||
case VIDEO_4K:
|
||||
case VIDEO_DUAL:
|
||||
ret = 2;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *get_interlacing_description(enum interlacing_t interlacing)
|
||||
{
|
||||
switch (interlacing) {
|
||||
case PROGRESSIVE:
|
||||
return "progressive";
|
||||
case UPPER_FIELD_FIRST:
|
||||
return "interlaced (upper field first)";
|
||||
case LOWER_FIELD_FIRST:
|
||||
return "interlaced (lower field first)";
|
||||
case INTERLACED_MERGED:
|
||||
return "interlaced merged";
|
||||
case SEGMENTED_FRAME:
|
||||
return "progressive segmented";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,13 +65,29 @@ typedef enum {
|
||||
JPEG
|
||||
} codec_t;
|
||||
|
||||
enum interlacing_t {
|
||||
PROGRESSIVE = 0,
|
||||
UPPER_FIELD_FIRST = 1,
|
||||
LOWER_FIELD_FIRST = 2,
|
||||
INTERLACED_MERGED = 3,
|
||||
SEGMENTED_FRAME = 4
|
||||
};
|
||||
|
||||
#define VIDEO_NORMAL 0u
|
||||
#define VIDEO_DUAL 1u
|
||||
#define VIDEO_STEREO 2u
|
||||
#define VIDEO_4K 3u
|
||||
|
||||
|
||||
|
||||
/* please note that tiles have also its own widths and heights */
|
||||
struct video_desc {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
codec_t color_spec;
|
||||
int aux;
|
||||
double fps;
|
||||
enum interlacing_t interlacing;
|
||||
unsigned int video_mode;
|
||||
};
|
||||
|
||||
/* contains full information both about video and about tiles.
|
||||
@@ -84,12 +100,11 @@ struct video_desc_ti {
|
||||
struct video_frame
|
||||
{
|
||||
codec_t color_spec;
|
||||
int aux;
|
||||
enum interlacing_t interlacing;
|
||||
double fps;
|
||||
struct tile *tiles;
|
||||
|
||||
unsigned int grid_width; /* tiles */
|
||||
unsigned int grid_height;
|
||||
unsigned int tile_count;
|
||||
};
|
||||
|
||||
struct tile {
|
||||
@@ -102,25 +117,23 @@ struct tile {
|
||||
*/
|
||||
unsigned int data_len; /* relative to data pos, not framebuffer size! */
|
||||
unsigned int linesize;
|
||||
|
||||
struct tile_info tile_info;
|
||||
};
|
||||
|
||||
struct video_frame * vf_alloc(int grid_width, int grid_height);
|
||||
struct video_frame * vf_alloc(int count);
|
||||
void vf_free(struct video_frame *buf);
|
||||
struct tile * tile_get(struct video_frame *buf, int grid_x_pos, int grid_y_pos);
|
||||
struct tile * vf_get_tile(struct video_frame *buf, int pos);
|
||||
int video_desc_eq(struct video_desc, struct video_desc);
|
||||
int get_video_mode_tiles_x(int video_mode);
|
||||
int get_video_mode_tiles_y(int video_mode);
|
||||
const char *get_interlacing_description(enum interlacing_t);
|
||||
|
||||
/*
|
||||
* Currently used (pre 1.0) is only AUX_{INTERLACED, PROGRESSIVE, SF, TILED}
|
||||
*/
|
||||
#define AUX_INTERLACED (1<<0)
|
||||
#define AUX_PROGRESSIVE (1<<1)
|
||||
#define AUX_SF (1<<2)
|
||||
#define AUX_RGB (1<<3) /* if device supports both, set both */
|
||||
#define AUX_YUV (1<<4)
|
||||
#define AUX_10Bit (1<<5)
|
||||
#define AUX_TILED (1<<6)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -486,8 +486,7 @@ vidcap_decklink_init(char *fmt, unsigned int flags)
|
||||
device_found[i] = false;
|
||||
|
||||
if(s->stereo) {
|
||||
s->frame = vf_alloc(2, 1);
|
||||
s->frame->aux = AUX_TILED;
|
||||
s->frame = vf_alloc(2);
|
||||
if (s->devices_cnt > 1) {
|
||||
fprintf(stderr, "[DeckLink] Passed more than one device while setting 3D mode. "
|
||||
"In this mode, only one device needs to be passed.");
|
||||
@@ -495,25 +494,13 @@ vidcap_decklink_init(char *fmt, unsigned int flags)
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (s->devices_cnt > 1) {
|
||||
double x_cnt = sqrt(s->devices_cnt);
|
||||
|
||||
int x_count = x_cnt - round(x_cnt) == 0.0 ? x_cnt : s->devices_cnt;
|
||||
int y_count = s->devices_cnt / x_cnt;
|
||||
s->frame = vf_alloc(x_count, y_count);
|
||||
s->frame->aux = AUX_TILED;
|
||||
} else {
|
||||
s->frame = vf_alloc(1, 1);
|
||||
s->frame->aux = 0;
|
||||
}
|
||||
s->frame = vf_alloc(s->devices_cnt);
|
||||
}
|
||||
|
||||
/* TODO: make sure that all devices are have compatible properties */
|
||||
for (int i = 0; i < s->devices_cnt; ++i)
|
||||
{
|
||||
int x_pos = i % s->frame->tiles[0].tile_info.x_count;
|
||||
int y_pos = i / s->frame->tiles[0].tile_info.x_count;
|
||||
struct tile * tile = tile_get(s->frame, x_pos, y_pos);
|
||||
struct tile * tile = vf_get_tile(s->frame, i);
|
||||
dnum = 0;
|
||||
deckLink = NULL;
|
||||
// Create an IDeckLinkIterator object to enumerate all DeckLink cards in the system
|
||||
@@ -619,13 +606,13 @@ vidcap_decklink_init(char *fmt, unsigned int flags)
|
||||
switch(displayMode->GetFieldDominance()) {
|
||||
case bmdLowerFieldFirst:
|
||||
case bmdUpperFieldFirst:
|
||||
s->frame->aux |= AUX_INTERLACED;
|
||||
s->frame->interlacing = INTERLACED_MERGED;
|
||||
break;
|
||||
case bmdProgressiveFrame:
|
||||
s->frame->aux |= AUX_PROGRESSIVE;
|
||||
s->frame->interlacing = PROGRESSIVE;
|
||||
break;
|
||||
case bmdProgressiveSegmentedFrame:
|
||||
s->frame->aux |= AUX_SF;
|
||||
s->frame->interlacing = SEGMENTED_FRAME;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -201,8 +201,8 @@ void *vidcap_dvs_init_impl(char *fmt, unsigned int flags)
|
||||
s = (struct vidcap_dvs_state *)
|
||||
calloc(1, sizeof(struct vidcap_dvs_state));
|
||||
|
||||
s->frame = vf_alloc(1, 1);
|
||||
s->tile = tile_get(s->frame, 0, 0);
|
||||
s->frame = vf_alloc(1);
|
||||
s->tile = vf_get_tile(s->frame, 0);
|
||||
|
||||
if (s == NULL) {
|
||||
debug_msg("Unable to allocate DVS state\n");
|
||||
@@ -290,7 +290,18 @@ void *vidcap_dvs_init_impl(char *fmt, unsigned int flags)
|
||||
s->tile->width = s->mode->width;
|
||||
s->tile->height = s->mode->height;
|
||||
s->frame->fps = s->mode->fps;
|
||||
s->frame->aux = s->mode->aux;
|
||||
switch(s->mode->aux) {
|
||||
case AUX_PROGRESSIVE:
|
||||
s->frame->interlacing = PROGRESSIVE;
|
||||
break;
|
||||
case AUX_INTERLACED:
|
||||
s->frame->interlacing = INTERLACED_MERGED;
|
||||
break;
|
||||
case AUX_SF:
|
||||
s->frame->interlacing = SEGMENTED_FRAME;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
s->tile->linesize = vc_get_linesize(s->tile->width, s->frame->color_spec);
|
||||
s->tile->data_len = s->tile->linesize * s->tile->height;
|
||||
|
||||
@@ -103,7 +103,7 @@ struct frame_mode {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
double fps;
|
||||
int interlacing; /* AUX_* */
|
||||
int aux; /* AUX_* */
|
||||
unsigned int magic;
|
||||
};
|
||||
|
||||
@@ -191,7 +191,7 @@ static const struct frame_mode frame_modes[] = {
|
||||
};
|
||||
|
||||
struct vidcap_quad_state {
|
||||
int device_cnt;
|
||||
int devices_cnt;
|
||||
int fd[MAX_TILES];
|
||||
struct pollfd pfd[MAX_TILES];
|
||||
int audio_fd;
|
||||
@@ -353,7 +353,7 @@ vidcap_quad_init(char *init_fmt, unsigned int flags)
|
||||
int i;
|
||||
char *save_ptr = NULL;
|
||||
char *fmt_dup, *item;
|
||||
int tile_x_cnt, tile_y_cnt;
|
||||
int devices[4];
|
||||
|
||||
printf("vidcap_quad_init\n");
|
||||
|
||||
@@ -383,8 +383,23 @@ vidcap_quad_init(char *init_fmt, unsigned int flags)
|
||||
}
|
||||
|
||||
fmt_dup = strdup(init_fmt);
|
||||
item = strtok_r(fmt_dup, ":", &save_ptr);
|
||||
|
||||
|
||||
|
||||
item = strtok_r(NULL, ":", &save_ptr);
|
||||
assert(item != NULL);
|
||||
char *devices_str = strdup(item);
|
||||
s->devices_cnt = 0;
|
||||
char *ptr, *saveptr2 = NULL;
|
||||
ptr = strtok_r(devices_str, ",", &saveptr2);
|
||||
do {
|
||||
devices[s->devices_cnt] = atoi(ptr);
|
||||
++s->devices_cnt;
|
||||
} while (ptr = strtok_r(NULL, ",", &saveptr2));
|
||||
free(devices_str);
|
||||
|
||||
item = strtok_r(fmt_dup, ":", &save_ptr);
|
||||
assert(item);
|
||||
frame_mode_number = atoi(item);
|
||||
if(frame_mode_number < 0 ||
|
||||
(unsigned int) frame_mode_number >=
|
||||
@@ -397,25 +412,10 @@ vidcap_quad_init(char *init_fmt, unsigned int flags)
|
||||
"via sysfs.");
|
||||
return NULL;
|
||||
}
|
||||
if((item = strtok_r(NULL, ":", &save_ptr)) != NULL)
|
||||
{
|
||||
tile_x_cnt = atoi(item);
|
||||
item = strtok_r(NULL, ":", &save_ptr);
|
||||
if (item == NULL) {
|
||||
fprintf(stderr, "quad: One tile dimension entered, expected zero or 2 values (see -g help)!");
|
||||
return NULL;
|
||||
}
|
||||
tile_y_cnt = atoi(item);
|
||||
s->device_cnt = tile_x_cnt * tile_y_cnt;
|
||||
} else {
|
||||
tile_x_cnt = 1;
|
||||
tile_y_cnt = 1;
|
||||
s->device_cnt = 1;
|
||||
}
|
||||
|
||||
free(fmt_dup);
|
||||
|
||||
s->frame = vf_alloc(tile_x_cnt, tile_y_cnt);
|
||||
s->frame = vf_alloc(s->devices_cnt);
|
||||
|
||||
/* CHECK IF QUAD CAN WORK CORRECTLY */
|
||||
|
||||
@@ -428,7 +428,7 @@ vidcap_quad_init(char *init_fmt, unsigned int flags)
|
||||
memset((void *) s->fd, 0, sizeof(s->fd));
|
||||
//memset((void *) s->frame, 0, sizeof(s->frame));
|
||||
|
||||
for(i = 0; i < s->device_cnt; ++i) {
|
||||
for(i = 0; i < s->devices_cnt; ++i) {
|
||||
char dev_name[MAXLEN];
|
||||
unsigned int cap;
|
||||
unsigned int val;
|
||||
@@ -443,10 +443,7 @@ vidcap_quad_init(char *init_fmt, unsigned int flags)
|
||||
unsigned long int mode;
|
||||
const struct codec_info_t *c_info;
|
||||
|
||||
int tile_x = i % tile_x_cnt;
|
||||
int tile_y = i / tile_x_cnt;
|
||||
|
||||
snprintf(dev_name, sizeof(dev_name), devfile_fmt, i);
|
||||
snprintf(dev_name, sizeof(dev_name), devfile_fmt, devices[i]);
|
||||
|
||||
memset (&buf, 0, sizeof (buf));
|
||||
if(stat (dev_name, &buf) < 0) {
|
||||
@@ -622,19 +619,26 @@ vidcap_quad_init(char *init_fmt, unsigned int flags)
|
||||
/*Get video standard*/
|
||||
/*frame_mode = get_video_standard (s->fd);*/
|
||||
|
||||
struct tile *tile = tile_get(s->frame, tile_x, tile_y);
|
||||
struct tile *tile = vf_get_tile(s->frame, i);
|
||||
|
||||
s->frame->color_spec = c_info->codec;
|
||||
s->frame->fps = frame_mode->fps;
|
||||
s->frame->aux = frame_mode->interlacing;
|
||||
switch(frame_mode->aux) {
|
||||
case AUX_PROGRESSIVE:
|
||||
s->frame->interlacing = PROGRESSIVE;
|
||||
break;
|
||||
case AUX_INTERLACED:
|
||||
s->frame->interlacing = INTERLACED_MERGED;
|
||||
break;
|
||||
case AUX_SF:
|
||||
s->frame->interlacing = SEGMENTED_FRAME;
|
||||
break;
|
||||
}
|
||||
tile->width = frame_mode->width;
|
||||
tile->height = frame_mode->height;
|
||||
tile->linesize = vc_get_linesize(frame_mode->width, c_info->codec);
|
||||
tile->data_len = tile->linesize * tile->height;
|
||||
|
||||
if(s->device_cnt > 1) {
|
||||
s->frame->aux |= AUX_TILED;
|
||||
}
|
||||
|
||||
if((tile->data = (char *)
|
||||
malloc (tile->data_len)) == NULL) {
|
||||
@@ -665,7 +669,7 @@ vidcap_quad_done(void *state)
|
||||
|
||||
if (s != NULL) {
|
||||
int i;
|
||||
for (i = 0; i < s->device_cnt; ++i) {
|
||||
for (i = 0; i < s->devices_cnt; ++i) {
|
||||
if(s->frame->tiles[i].data != NULL)
|
||||
free(s->frame->tiles[i].data);
|
||||
if(s->fd[i] != 0)
|
||||
@@ -697,19 +701,17 @@ static void * vidcap_grab_thread(void *args)
|
||||
if (should_exit)
|
||||
break;
|
||||
|
||||
//for(cur_dev = 0; cur_dev < s->device_cnt; ++cur_dev)
|
||||
while (return_vec != (1 << s->device_cnt) - 1)
|
||||
//for(cur_dev = 0; cur_dev < s->devices_cnt; ++cur_dev)
|
||||
while (return_vec != (1 << s->devices_cnt) - 1)
|
||||
{
|
||||
if(poll (s->pfd, s->device_cnt, 1000/23) < 0) {
|
||||
if(poll (s->pfd, s->devices_cnt, 1000/23) < 0) {
|
||||
//fprintf (stderr, "%s: ", device);
|
||||
perror ("unable to poll device file");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(cur_dev = 0; cur_dev < s->device_cnt; ++cur_dev) {
|
||||
int x_til_cnt = s->frame->tiles[0].tile_info.x_count;
|
||||
struct tile *tile = tile_get(s->frame, cur_dev % x_til_cnt,
|
||||
cur_dev / x_til_cnt);
|
||||
for(cur_dev = 0; cur_dev < s->devices_cnt; ++cur_dev) {
|
||||
struct tile *tile = vf_get_tile(s->frame, cur_dev);
|
||||
|
||||
|
||||
if (s->pfd[cur_dev].revents & POLLIN) {
|
||||
@@ -754,11 +756,9 @@ static void * vidcap_grab_thread(void *args)
|
||||
}
|
||||
}
|
||||
|
||||
while (poll (s->pfd, s->device_cnt, 0) > 0) {
|
||||
for(cur_dev = 0; cur_dev < s->device_cnt; ++cur_dev) {
|
||||
int x_til_cnt = s->frame->tiles[0].tile_info.x_count;
|
||||
struct tile *tile = tile_get(s->frame, cur_dev % x_til_cnt,
|
||||
cur_dev / x_til_cnt);
|
||||
while (poll (s->pfd, s->devices_cnt, 0) > 0) {
|
||||
for(cur_dev = 0; cur_dev < s->devices_cnt; ++cur_dev) {
|
||||
struct tile *tile = vf_get_tile(s->frame, cur_dev);
|
||||
|
||||
if (s->pfd[cur_dev].revents & POLLIN) {
|
||||
unsigned int ret;
|
||||
@@ -847,8 +847,58 @@ vidcap_quad_grab(void *state, struct audio_frame **audio)
|
||||
static void print_output_modes()
|
||||
{
|
||||
unsigned int i;
|
||||
printf("usage: -t quad:<mode>:[<x_tiles_count>:<y_tiles_count>]\n\twhere mode is one of following.\n");
|
||||
printf("Available output modes:\n");
|
||||
printf("usage: -t quad:<device(s)>:<mode>\n\twhere mode is one of following.\n");
|
||||
printf("\nAvailable devices (inputs):\n");
|
||||
|
||||
for(i = 0; i < 16; ++i) {
|
||||
char dev_name[MAXLEN];
|
||||
struct stat buf;
|
||||
|
||||
snprintf(dev_name, sizeof(dev_name), devfile_fmt, i);
|
||||
|
||||
memset (&buf, 0, sizeof (buf));
|
||||
if(stat (dev_name, &buf) < 0) {
|
||||
break;
|
||||
} else {
|
||||
struct util_info *info;
|
||||
char type;
|
||||
int num;
|
||||
unsigned long int id;
|
||||
char name[MAXLEN];
|
||||
|
||||
/* Check if it is a character device or not */
|
||||
if(!S_ISCHR (buf.st_mode)) {
|
||||
fprintf (stderr, "not a character device\n");
|
||||
continue;
|
||||
}
|
||||
if(!(buf.st_rdev & 0x0080)) {
|
||||
fprintf (stderr, "not a receiver\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check the minor number to determine if it is a receive or transmit device */
|
||||
type = (buf.st_rdev & 0x0080) ? 'r' : 't';
|
||||
|
||||
/* Get the receiver or transmitter number */
|
||||
num = buf.st_rdev & 0x007f;
|
||||
|
||||
/* Build the path to sysfs file */
|
||||
snprintf (name, sizeof (name), sys_fmt, type, num, "dev");
|
||||
|
||||
if (util_strtoul (name, &id) < 0) {
|
||||
fprintf (stderr, "unable to get the firmware version");
|
||||
continue;
|
||||
}
|
||||
if ((info = getinfo (id)) == NULL) {
|
||||
printf ("\tUnknown device\n");
|
||||
} else {
|
||||
printf ("\t%d) %s\n", i,
|
||||
info->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("\nAvailable output modes:\n");
|
||||
for(i = 0; i < sizeof(frame_modes)/sizeof(struct frame_mode); ++i) {
|
||||
if(frame_modes[i].magic == FMODE_MAGIC)
|
||||
printf("\t%2u: %s\n", i, frame_modes[i].name);
|
||||
@@ -859,3 +909,4 @@ static void print_output_modes()
|
||||
|
||||
#endif /* HAVE_QUAD */
|
||||
#endif /* HAVE_MACOSX */
|
||||
|
||||
|
||||
@@ -623,7 +623,17 @@ static int qt_open_grabber(struct qt_grabber_state *s, char *fmt)
|
||||
s->qt_mode->height,
|
||||
s->qt_mode->fps,
|
||||
s->qt_mode->aux);
|
||||
s->frame->aux = s->qt_mode->aux & (AUX_INTERLACED|AUX_PROGRESSIVE|AUX_SF);
|
||||
switch(s->qt_mode->aux & (AUX_INTERLACED|AUX_PROGRESSIVE|AUX_SF)) {
|
||||
case AUX_PROGRESSIVE:
|
||||
s->frame->interlacing = PROGRESSIVE;
|
||||
break;
|
||||
case AUX_INTERLACED:
|
||||
s->frame->interlacing = INTERLACED_MERGED;
|
||||
break;
|
||||
case AUX_SF:
|
||||
s->frame->interlacing = SEGMENTED_FRAME;
|
||||
break;
|
||||
}
|
||||
free(device);
|
||||
free(input);
|
||||
break;
|
||||
@@ -807,8 +817,8 @@ void *vidcap_quicktime_init(char *fmt, unsigned int flags)
|
||||
|
||||
s = (struct qt_grabber_state *)calloc(1,sizeof(struct qt_grabber_state));
|
||||
|
||||
s->frame = vf_alloc(1, 1);
|
||||
s->tile = tile_get(s->frame, 0, 0);
|
||||
s->frame = vf_alloc(1);
|
||||
s->tile = vf_get_tile(s->frame, 0);
|
||||
|
||||
if (s != NULL) {
|
||||
s->magic = MAGIC_QT_GRABBER;
|
||||
|
||||
@@ -104,6 +104,7 @@ struct testcard_state {
|
||||
|
||||
struct audio_frame audio;
|
||||
char **tiles_data;
|
||||
int tiles_cnt_horizontal;
|
||||
|
||||
char *audio_data;
|
||||
volatile int audio_start, audio_end;
|
||||
@@ -398,10 +399,10 @@ static int configure_tiling(struct testcard_state *s, const char *fmt)
|
||||
grid_h = atoi(token);
|
||||
free(tmp);
|
||||
|
||||
s->tiled = vf_alloc(grid_w, grid_h);
|
||||
s->tiled = vf_alloc(grid_w * grid_h);
|
||||
s->tiles_cnt_horizontal = grid_h;
|
||||
s->tiled->color_spec = s->frame->color_spec;
|
||||
s->tiled->fps = s->frame->fps;
|
||||
s->tiled->aux = s->frame->aux | AUX_TILED;
|
||||
|
||||
tile_cnt = grid_w *
|
||||
grid_h;
|
||||
@@ -423,10 +424,6 @@ static int configure_tiling(struct testcard_state *s, const char *fmt)
|
||||
s->tiled->tiles[x].width = s->frame->tiles[0].width/ grid_w;
|
||||
s->tiled->tiles[x].height = s->frame->tiles[0].height / grid_h;
|
||||
s->tiled->tiles[x].data_len = s->frame->tiles[0].data_len / (grid_w * grid_h);
|
||||
s->tiled->tiles[x].tile_info.x_count = grid_w;
|
||||
s->tiled->tiles[x].tile_info.y_count = grid_h;
|
||||
s->tiled->tiles[x].tile_info.pos_x = x;
|
||||
s->tiled->tiles[x].tile_info.pos_y = 0;
|
||||
|
||||
s->tiled->tiles[x].data =
|
||||
s->tiles_data[x] = (char *) realloc(s->tiled->tiles[x].data,
|
||||
@@ -447,7 +444,6 @@ static int configure_tiling(struct testcard_state *s, const char *fmt)
|
||||
s->tiled->tiles[y * grid_w + x].data =
|
||||
s->tiles_data[x] +
|
||||
y * s->tiled->tiles[x].height * s->tiled->tiles[x].linesize;
|
||||
s->tiled->tiles[y * grid_w + x].tile_info.pos_y = y;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,7 +475,7 @@ void *vidcap_testcard_init(char *fmt, unsigned int flags)
|
||||
if (!s)
|
||||
return NULL;
|
||||
|
||||
s->frame = vf_alloc(1, 1);
|
||||
s->frame = vf_alloc(1);
|
||||
|
||||
char *tmp;
|
||||
|
||||
@@ -489,19 +485,14 @@ void *vidcap_testcard_init(char *fmt, unsigned int flags)
|
||||
free(s);
|
||||
return NULL;
|
||||
}
|
||||
tile_get(s->frame, 0, 0)->width = atoi(tmp);
|
||||
if(tile_get(s->frame, 0, 0)->width % 2 != 0) {
|
||||
fprintf(stderr, "[testcard] Width must be multiple of 2.\n");
|
||||
free(s);
|
||||
return NULL;
|
||||
}
|
||||
vf_get_tile(s->frame, 0)->width = atoi(tmp);
|
||||
tmp = strtok(NULL, ":");
|
||||
if (!tmp) {
|
||||
fprintf(stderr, "Wrong format for testcard '%s'\n", fmt);
|
||||
free(s);
|
||||
return NULL;
|
||||
}
|
||||
tile_get(s->frame, 0, 0)->height = atoi(tmp);
|
||||
vf_get_tile(s->frame, 0)->height = atoi(tmp);
|
||||
tmp = strtok(NULL, ":");
|
||||
if (!tmp) {
|
||||
free(s);
|
||||
@@ -537,16 +528,16 @@ void *vidcap_testcard_init(char *fmt, unsigned int flags)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
aligned_x = tile_get(s->frame, 0, 0)->width;
|
||||
aligned_x = vf_get_tile(s->frame, 0)->width;
|
||||
if (h_align) {
|
||||
aligned_x = (aligned_x + h_align - 1) / h_align * h_align;
|
||||
}
|
||||
|
||||
rect_size = (tile_get(s->frame, 0, 0)->width + rect_size - 1) / rect_size;
|
||||
rect_size = (vf_get_tile(s->frame, 0)->width + rect_size - 1) / rect_size;
|
||||
|
||||
tile_get(s->frame, 0, 0)->linesize = aligned_x * bpp;
|
||||
s->frame->aux = AUX_PROGRESSIVE;
|
||||
s->size = aligned_x * tile_get(s->frame, 0, 0)->height * bpp;
|
||||
vf_get_tile(s->frame, 0)->linesize = aligned_x * bpp;
|
||||
s->frame->interlacing = PROGRESSIVE;
|
||||
s->size = aligned_x * vf_get_tile(s->frame, 0)->height * bpp;
|
||||
|
||||
filename = strtok(NULL, ":");
|
||||
if (filename && strcmp(filename, "p") != 0
|
||||
@@ -581,7 +572,7 @@ void *vidcap_testcard_init(char *fmt, unsigned int flags)
|
||||
struct testcard_rect r;
|
||||
int col_num = 0;
|
||||
s->pixmap.w = aligned_x;
|
||||
s->pixmap.h = tile_get(s->frame, 0, 0)->height * 2;
|
||||
s->pixmap.h = vf_get_tile(s->frame, 0)->height * 2;
|
||||
s->pixmap.data = malloc(s->pixmap.w * s->pixmap.h * sizeof(int));
|
||||
|
||||
if (filename) {
|
||||
@@ -591,10 +582,10 @@ void *vidcap_testcard_init(char *fmt, unsigned int flags)
|
||||
strip_fmt = filename;
|
||||
}
|
||||
|
||||
for (j = 0; j < tile_get(s->frame, 0, 0)->height; j += rect_size) {
|
||||
for (j = 0; j < vf_get_tile(s->frame, 0)->height; j += rect_size) {
|
||||
int grey = 0xff010101;
|
||||
if (j == rect_size * 2) {
|
||||
r.w = tile_get(s->frame, 0, 0)->width;
|
||||
r.w = vf_get_tile(s->frame, 0)->width;
|
||||
r.h = rect_size / 4;
|
||||
r.x = 0;
|
||||
r.y = j;
|
||||
@@ -602,7 +593,7 @@ void *vidcap_testcard_init(char *fmt, unsigned int flags)
|
||||
r.y = j + rect_size * 3 / 4;
|
||||
testcard_fillRect(&s->pixmap, &r, 0);
|
||||
}
|
||||
for (i = 0; i < tile_get(s->frame, 0, 0)->width; i += rect_size) {
|
||||
for (i = 0; i < vf_get_tile(s->frame, 0)->width; i += rect_size) {
|
||||
r.w = rect_size;
|
||||
r.h = rect_size;
|
||||
r.x = i;
|
||||
@@ -623,42 +614,42 @@ void *vidcap_testcard_init(char *fmt, unsigned int flags)
|
||||
s->data = s->pixmap.data;
|
||||
if (codec == UYVY || codec == v210 || codec == Vuy2) {
|
||||
rgb2yuv422((unsigned char *) s->data, aligned_x,
|
||||
tile_get(s->frame, 0, 0)->height);
|
||||
vf_get_tile(s->frame, 0)->height);
|
||||
}
|
||||
|
||||
if (codec == v210) {
|
||||
s->data =
|
||||
(char *)tov210((unsigned char *) s->data, aligned_x,
|
||||
aligned_x, tile_get(s->frame, 0, 0)->height, bpp);
|
||||
aligned_x, vf_get_tile(s->frame, 0)->height, bpp);
|
||||
}
|
||||
|
||||
if (codec == R10k) {
|
||||
toR10k((unsigned char *) s->data, tile_get(s->frame, 0, 0)->width,
|
||||
tile_get(s->frame, 0, 0)->height);
|
||||
toR10k((unsigned char *) s->data, vf_get_tile(s->frame, 0)->width,
|
||||
vf_get_tile(s->frame, 0)->height);
|
||||
}
|
||||
|
||||
if(codec == RGB) {
|
||||
s->data =
|
||||
(char *)toRGB((unsigned char *) s->data, tile_get(s->frame, 0, 0)->width,
|
||||
tile_get(s->frame, 0, 0)->height);
|
||||
(char *)toRGB((unsigned char *) s->data, vf_get_tile(s->frame, 0)->width,
|
||||
vf_get_tile(s->frame, 0)->height);
|
||||
}
|
||||
|
||||
if(codec == RGBA) {
|
||||
toRGB((unsigned char *) s->data, tile_get(s->frame, 0, 0)->width,
|
||||
tile_get(s->frame, 0, 0)->height);
|
||||
toRGB((unsigned char *) s->data, vf_get_tile(s->frame, 0)->width,
|
||||
vf_get_tile(s->frame, 0)->height);
|
||||
}
|
||||
}
|
||||
|
||||
tile_get(s->frame, 0, 0)->data = malloc(2 * s->size);
|
||||
vf_get_tile(s->frame, 0)->data = malloc(2 * s->size);
|
||||
|
||||
memcpy(tile_get(s->frame, 0, 0)->data, s->data, s->size);
|
||||
memcpy(tile_get(s->frame, 0, 0)->data + s->size, tile_get(s->frame, 0, 0)->data, s->size);
|
||||
memcpy(vf_get_tile(s->frame, 0)->data, s->data, s->size);
|
||||
memcpy(vf_get_tile(s->frame, 0)->data + s->size, vf_get_tile(s->frame, 0)->data, s->size);
|
||||
if(s->pixmap.data)
|
||||
free(s->pixmap.data);
|
||||
else
|
||||
free(tile_get(s->frame, 0, 0)->data);
|
||||
free(vf_get_tile(s->frame, 0)->data);
|
||||
|
||||
s->data = tile_get(s->frame, 0, 0)->data;
|
||||
s->data = vf_get_tile(s->frame, 0)->data;
|
||||
|
||||
tmp = strtok(NULL, ":");
|
||||
if (tmp) {
|
||||
@@ -678,16 +669,14 @@ void *vidcap_testcard_init(char *fmt, unsigned int flags)
|
||||
s->count = 0;
|
||||
gettimeofday(&(s->last_frame_time), NULL);
|
||||
|
||||
printf("Testcard capture set to %dx%d, bpp %f\n", tile_get(s->frame, 0, 0)->width,
|
||||
tile_get(s->frame, 0, 0)->height, bpp);
|
||||
printf("Testcard capture set to %dx%d, bpp %f\n", vf_get_tile(s->frame, 0)->width,
|
||||
vf_get_tile(s->frame, 0)->height, bpp);
|
||||
|
||||
tile_get(s->frame, 0, 0)->data_len = s->size;
|
||||
vf_get_tile(s->frame, 0)->data_len = s->size;
|
||||
|
||||
if(strip_fmt != NULL) {
|
||||
if(configure_tiling(s, strip_fmt) != 0)
|
||||
return NULL;
|
||||
} else {
|
||||
s->frame->aux &= ~AUX_TILED;
|
||||
}
|
||||
|
||||
if(flags & VIDCAP_FLAG_ENABLE_AUDIO) {
|
||||
@@ -768,9 +757,9 @@ struct video_frame *vidcap_testcard_grab(void *arg, struct audio_frame **audio)
|
||||
}
|
||||
|
||||
|
||||
tile_get(state->frame, 0, 0)->data += tile_get(state->frame, 0, 0)->linesize;
|
||||
if(tile_get(state->frame, 0, 0)->data > state->data + state->size)
|
||||
tile_get(state->frame, 0, 0)->data = state->data;
|
||||
vf_get_tile(state->frame, 0)->data += vf_get_tile(state->frame, 0)->linesize;
|
||||
if(vf_get_tile(state->frame, 0)->data > state->data + state->size)
|
||||
vf_get_tile(state->frame, 0)->data = state->data;
|
||||
|
||||
/*char line[state->frame.src_linesize * 2 + state->pan];
|
||||
unsigned int i;
|
||||
@@ -800,8 +789,7 @@ struct video_frame *vidcap_testcard_grab(void *arg, struct audio_frame **audio)
|
||||
if (state->tiled) {
|
||||
/* update tile data instead */
|
||||
int i;
|
||||
int count = state->tiled->grid_width *
|
||||
state->tiled->grid_height;
|
||||
int count = state->tiled->tile_count;
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
/* shift - for semantics of vars refer to configure_tiling*/
|
||||
@@ -810,7 +798,7 @@ struct video_frame *vidcap_testcard_grab(void *arg, struct audio_frame **audio)
|
||||
* keep in mind that we have two "pictures" for
|
||||
* every tile stored sequentially */
|
||||
if(state->tiled->tiles[i].data >= state->tiles_data[i] +
|
||||
state->tiled->tiles[i].data_len * state->tiled->grid_height) {
|
||||
state->tiled->tiles[i].data_len * state->tiles_cnt_horizontal) {
|
||||
state->tiled->tiles[i].data = state->tiles_data[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,8 +162,8 @@ void *vidcap_testcard2_init(char *fmt, unsigned int flags)
|
||||
|
||||
char *tmp;
|
||||
|
||||
s->frame = vf_alloc(1, 1);
|
||||
s->tile = tile_get(s->frame, 0, 0);
|
||||
s->frame = vf_alloc(1);
|
||||
s->tile = vf_get_tile(s->frame, 0);
|
||||
|
||||
tmp = strtok(fmt, ":");
|
||||
if (!tmp) {
|
||||
@@ -226,7 +226,7 @@ void *vidcap_testcard2_init(char *fmt, unsigned int flags)
|
||||
|
||||
rect_size = (s->tile->width + rect_size - 1) / rect_size;
|
||||
|
||||
s->frame->aux = AUX_PROGRESSIVE;
|
||||
s->frame->interlacing = AUX_PROGRESSIVE;
|
||||
s->size = s->aligned_x * s->tile->height * bpp;
|
||||
|
||||
{
|
||||
|
||||
@@ -126,6 +126,30 @@ double get_bpp(codec_t codec)
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t get_fourcc(codec_t codec)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (codec_info[i].name != NULL) {
|
||||
if (codec == codec_info[i].codec)
|
||||
return codec_info[i].fcc;
|
||||
i++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
codec_t get_codec_from_fcc(uint32_t fourcc)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (codec_info[i].name != NULL) {
|
||||
if (fourcc == codec_info[i].fcc)
|
||||
return codec_info[i].codec;
|
||||
i++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_halign(codec_t codec)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@@ -71,6 +71,8 @@ extern const struct line_decode_from_to line_decoders[]; /* defined int .c */
|
||||
|
||||
void show_codec_help(char *mode);
|
||||
double get_bpp(codec_t codec);
|
||||
uint32_t get_fourcc(codec_t codec);
|
||||
codec_t get_codec_from_fcc(uint32_t fourcc);
|
||||
int get_haligned(int width_pixels, codec_t codec);
|
||||
|
||||
int vc_get_linesize(unsigned int width, codec_t codec);
|
||||
|
||||
@@ -86,21 +86,19 @@ static void configure_with(struct video_compress *s, struct video_frame *frame)
|
||||
int h_align = 0;
|
||||
enum dxt_format format;
|
||||
|
||||
assert(tile_get(frame, 0, 0)->width % 4 == 0);
|
||||
s->out = vf_alloc(frame->grid_width, frame->grid_height);
|
||||
assert(vf_get_tile(frame, 0)->width % 4 == 0);
|
||||
s->out = vf_alloc(frame->tile_count);
|
||||
|
||||
for (x = 0; x < frame->grid_width; ++x) {
|
||||
for (y = 0; y < frame->grid_height; ++y) {
|
||||
if (tile_get(frame, x, y)->width != tile_get(frame, 0, 0)->width ||
|
||||
tile_get(frame, x, y)->width != tile_get(frame, 0, 0)->width)
|
||||
for (x = 0; x < frame->tile_count; ++x) {
|
||||
if (vf_get_tile(frame, x)->width != vf_get_tile(frame, 0)->width ||
|
||||
vf_get_tile(frame, x)->width != vf_get_tile(frame, 0)->width)
|
||||
error_with_code_msg(128,"[RTDXT] Requested to compress tiles of different size!");
|
||||
|
||||
tile_get(s->out, x, y)->width = tile_get(frame, 0, 0)->width;
|
||||
tile_get(s->out, x, y)->height = tile_get(frame, 0, 0)->height;
|
||||
}
|
||||
vf_get_tile(s->out, x)->width = vf_get_tile(frame, 0)->width;
|
||||
vf_get_tile(s->out, x)->height = vf_get_tile(frame, 0)->height;
|
||||
}
|
||||
|
||||
s->out->aux = frame->aux;
|
||||
s->out->interlacing = PROGRESSIVE;
|
||||
s->out->fps = frame->fps;
|
||||
s->out->color_spec = s->color_spec;
|
||||
|
||||
@@ -140,41 +138,36 @@ static void configure_with(struct video_compress *s, struct video_frame *frame)
|
||||
}
|
||||
|
||||
/* We will deinterlace the output frame */
|
||||
if(s->out->aux & AUX_INTERLACED)
|
||||
if(frame->interlacing == INTERLACED_MERGED)
|
||||
s->interlaced_input = TRUE;
|
||||
else
|
||||
s->interlaced_input = FALSE;
|
||||
s->out->aux &= ~AUX_INTERLACED;
|
||||
|
||||
s->dxt_height = (s->out->tiles[0].height + 3) / 4 * 4;
|
||||
|
||||
if(s->out->color_spec == DXT1) {
|
||||
s->encoder = dxt_encoder_create(DXT_TYPE_DXT1, s->out->tiles[0].width, s->dxt_height, format);
|
||||
s->out->aux |= AUX_RGB;
|
||||
s->out->tiles[0].data_len = s->out->tiles[0].width * s->dxt_height / 2;
|
||||
} else if(s->out->color_spec == DXT5){
|
||||
s->encoder = dxt_encoder_create(DXT_TYPE_DXT5_YCOCG, s->out->tiles[0].width, s->dxt_height, format);
|
||||
s->out->aux |= AUX_YUV; /* YCoCg */
|
||||
s->out->tiles[0].data_len = s->out->tiles[0].width * s->dxt_height;
|
||||
}
|
||||
|
||||
for (x = 0; x < frame->grid_width; ++x) {
|
||||
for (y = 0; y < frame->grid_height; ++y) {
|
||||
tile_get(s->out, x, y)->linesize = s->out->tiles[0].width;
|
||||
switch(format) {
|
||||
case DXT_FORMAT_RGBA:
|
||||
tile_get(s->out, x, y)->linesize *= 4;
|
||||
break;
|
||||
case DXT_FORMAT_RGB:
|
||||
tile_get(s->out, x, y)->linesize *= 3;
|
||||
break;
|
||||
case DXT_FORMAT_YUV422:
|
||||
tile_get(s->out, x, y)->linesize *= 2;
|
||||
break;
|
||||
}
|
||||
tile_get(s->out, x, y)->data_len = s->out->tiles[0].data_len;
|
||||
tile_get(s->out, x, y)->data = (char *) malloc(s->out->tiles[0].data_len);
|
||||
for (x = 0; x < frame->tile_count; ++x) {
|
||||
vf_get_tile(s->out, x)->linesize = s->out->tiles[0].width;
|
||||
switch(format) {
|
||||
case DXT_FORMAT_RGBA:
|
||||
vf_get_tile(s->out, x)->linesize *= 4;
|
||||
break;
|
||||
case DXT_FORMAT_RGB:
|
||||
vf_get_tile(s->out, x)->linesize *= 3;
|
||||
break;
|
||||
case DXT_FORMAT_YUV422:
|
||||
vf_get_tile(s->out, x)->linesize *= 2;
|
||||
break;
|
||||
}
|
||||
vf_get_tile(s->out, x)->data_len = s->out->tiles[0].data_len;
|
||||
vf_get_tile(s->out, x)->data = (char *) malloc(s->out->tiles[0].data_len);
|
||||
}
|
||||
|
||||
if(!s->encoder) {
|
||||
@@ -238,41 +231,39 @@ struct video_frame * dxt_glsl_compress(void *arg, struct video_frame * tx)
|
||||
if(!s->configured)
|
||||
configure_with(s, tx);
|
||||
|
||||
for (x = 0; x < tx->grid_width; ++x) {
|
||||
for (y = 0; y < tx->grid_height; ++y) {
|
||||
struct tile *in_tile = tile_get(tx, x, y);
|
||||
struct tile *out_tile = tile_get(s->out, x, y);
|
||||
|
||||
line1 = (unsigned char *) in_tile->data;
|
||||
line2 = (unsigned char *) s->decoded;
|
||||
|
||||
for (i = 0; i < (int) in_tile->height; ++i) {
|
||||
s->decoder(line2, line1, out_tile->linesize,
|
||||
0, 8, 16);
|
||||
line1 += vc_get_linesize(in_tile->width, tx->color_spec);
|
||||
line2 += out_tile->linesize;
|
||||
}
|
||||
|
||||
/* if height % 4 != 0, copy last line to align */
|
||||
if(s->dxt_height != out_tile->height) {
|
||||
int y;
|
||||
line1 = s->decoded + out_tile->linesize * (out_tile->height - 1);
|
||||
for (y = out_tile->height; y < s->dxt_height; ++y)
|
||||
{
|
||||
memcpy(line2, line1, out_tile->linesize);
|
||||
line2 += out_tile->linesize;
|
||||
}
|
||||
line2 += out_tile->linesize;
|
||||
}
|
||||
|
||||
if(s->interlaced_input)
|
||||
vc_deinterlace((unsigned char *) s->decoded, out_tile->linesize,
|
||||
s->dxt_height);
|
||||
|
||||
dxt_encoder_compress(s->encoder,
|
||||
(unsigned char *) s->decoded,
|
||||
(unsigned char *) out_tile->data);
|
||||
for (x = 0; x < tx->tile_count; ++x) {
|
||||
struct tile *in_tile = vf_get_tile(tx, x);
|
||||
struct tile *out_tile = vf_get_tile(s->out, x);
|
||||
|
||||
line1 = (unsigned char *) in_tile->data;
|
||||
line2 = (unsigned char *) s->decoded;
|
||||
|
||||
for (i = 0; i < (int) in_tile->height; ++i) {
|
||||
s->decoder(line2, line1, out_tile->linesize,
|
||||
0, 8, 16);
|
||||
line1 += vc_get_linesize(in_tile->width, tx->color_spec);
|
||||
line2 += out_tile->linesize;
|
||||
}
|
||||
|
||||
/* if height % 4 != 0, copy last line to align */
|
||||
if(s->dxt_height != out_tile->height) {
|
||||
int y;
|
||||
line1 = s->decoded + out_tile->linesize * (out_tile->height - 1);
|
||||
for (y = out_tile->height; y < s->dxt_height; ++y)
|
||||
{
|
||||
memcpy(line2, line1, out_tile->linesize);
|
||||
line2 += out_tile->linesize;
|
||||
}
|
||||
line2 += out_tile->linesize;
|
||||
}
|
||||
|
||||
if(s->interlaced_input)
|
||||
vc_deinterlace((unsigned char *) s->decoded, out_tile->linesize,
|
||||
s->dxt_height);
|
||||
|
||||
dxt_encoder_compress(s->encoder,
|
||||
(unsigned char *) s->decoded,
|
||||
(unsigned char *) out_tile->data);
|
||||
}
|
||||
|
||||
return s->out;
|
||||
|
||||
@@ -94,12 +94,13 @@ struct video_compress {
|
||||
pthread_mutex_t lock;
|
||||
volatile int thread_count;
|
||||
pthread_t thread_ids[MAX_THREADS];
|
||||
int tx_aux;
|
||||
codec_t tx_color_spec;
|
||||
sem_t thread_compress[MAX_THREADS];
|
||||
sem_t thread_done[MAX_THREADS];
|
||||
|
||||
int dxt_height;
|
||||
enum interlacing_t interlacing_source;
|
||||
int rgb:1;
|
||||
|
||||
decoder_t decoder;
|
||||
|
||||
@@ -108,55 +109,55 @@ struct video_compress {
|
||||
};
|
||||
|
||||
static void compress_thread(void *args);
|
||||
void reconfigure_compress(struct video_compress *compress, int width, int height, codec_t codec, int aux, double fps);
|
||||
void reconfigure_compress(struct video_compress *compress, int width, int height, codec_t codec, enum interlacing_t, double fps);
|
||||
|
||||
void reconfigure_compress(struct video_compress *compress, int width, int height, codec_t codec, int aux, double fps)
|
||||
void reconfigure_compress(struct video_compress *compress, int width, int height, codec_t codec, enum interlacing_t interlacing, double fps)
|
||||
{
|
||||
int x;
|
||||
|
||||
fprintf(stderr, "Compression reinitialized for %ux%u video.\n",
|
||||
width, height);
|
||||
/* Store original attributes to allow format change detection */
|
||||
compress->tx_aux = aux;
|
||||
compress->tx_color_spec = codec;
|
||||
compress->interlacing_source = interlacing;
|
||||
|
||||
compress->tile->width = width;
|
||||
compress->tile->height = height;
|
||||
compress->dxt_height = (compress->tile->height + 3) / 4 * 4;
|
||||
compress->frame->color_spec = codec;
|
||||
compress->frame->aux = aux;
|
||||
compress->frame->interlacing = PROGRESSIVE;
|
||||
compress->frame->fps = fps;
|
||||
|
||||
switch (codec) {
|
||||
case RGB:
|
||||
compress->decoder = (decoder_t) vc_copylineRGBtoRGBA;
|
||||
compress->frame->aux |= AUX_RGB;
|
||||
compress->rgb = TRUE;
|
||||
break;
|
||||
case RGBA:
|
||||
compress->decoder = (decoder_t) memcpy;
|
||||
compress->frame->aux |= AUX_RGB;
|
||||
compress->rgb = TRUE;
|
||||
break;
|
||||
case R10k:
|
||||
compress->decoder = (decoder_t) vc_copyliner10k;
|
||||
compress->frame->aux |= AUX_RGB;
|
||||
compress->rgb = TRUE;
|
||||
break;
|
||||
case UYVY:
|
||||
case Vuy2:
|
||||
case DVS8:
|
||||
compress->decoder = (decoder_t) memcpy;
|
||||
compress->frame->aux |= AUX_YUV;
|
||||
compress->rgb = FALSE;
|
||||
break;
|
||||
case v210:
|
||||
compress->decoder = (decoder_t) vc_copylinev210;
|
||||
compress->frame->aux |= AUX_YUV;
|
||||
compress->rgb = FALSE;
|
||||
break;
|
||||
case DVS10:
|
||||
compress->decoder = (decoder_t) vc_copylineDVS10;
|
||||
compress->frame->aux |= AUX_YUV;
|
||||
compress->rgb = FALSE;
|
||||
break;
|
||||
case DPX10:
|
||||
compress->decoder = (decoder_t) vc_copylineDPX10toRGBA;
|
||||
compress->frame->aux |= AUX_RGB;
|
||||
compress->rgb = FALSE;
|
||||
break;
|
||||
default:
|
||||
error_with_code_msg(128, "Unknown codec %d!", codec);
|
||||
@@ -170,18 +171,15 @@ void reconfigure_compress(struct video_compress *compress, int width, int height
|
||||
}
|
||||
}
|
||||
assert(h_align != 0);
|
||||
compress->tile->linesize = tile_get(compress->frame, 0, 0)->width *
|
||||
(compress->frame->aux & AUX_RGB ? 4 /*RGBA*/: 2/*YUV 422*/);
|
||||
compress->tile->linesize = vf_get_tile(compress->frame, 0)->width *
|
||||
(compress->rgb ? 4 /*RGBA*/: 2/*YUV 422*/);
|
||||
|
||||
if(compress->frame->aux & AUX_RGB) {
|
||||
if(compress->rgb) {
|
||||
compress->frame->color_spec = DXT1;
|
||||
} else {
|
||||
compress->frame->color_spec = DXT1_YUV;
|
||||
}
|
||||
|
||||
/* We will deinterlace the output frame */
|
||||
compress->frame->aux &= ~AUX_INTERLACED;
|
||||
|
||||
for (x = 0; x < compress->num_threads; x++) {
|
||||
int my_height = (compress->dxt_height / compress->num_threads) / 4 * 4;
|
||||
if(x == compress->num_threads - 1) {
|
||||
@@ -232,8 +230,8 @@ void *fastdxt_init(const char *num_threads_str)
|
||||
compress->num_threads = atoi(num_threads_str);
|
||||
assert (compress->num_threads >= 1 && compress->num_threads <= MAX_THREADS);
|
||||
|
||||
compress->frame = vf_alloc(1, 1);
|
||||
compress->tile = tile_get(compress->frame, 0, 0);
|
||||
compress->frame = vf_alloc(1);
|
||||
compress->tile = vf_get_tile(compress->frame, 0);
|
||||
|
||||
compress->tile->width = 0;
|
||||
compress->tile->height = 0;
|
||||
@@ -275,17 +273,17 @@ struct video_frame * fastdxt_compress(void *args, struct video_frame *tx)
|
||||
unsigned int x;
|
||||
unsigned char *line1, *line2;
|
||||
|
||||
assert(tx->grid_height == 1 && tx->grid_width == 1);
|
||||
assert(tile_get(tx, 0, 0)->width % 4 == 0);
|
||||
assert(tx->tile_count == 1);
|
||||
assert(vf_get_tile(tx, 0)->width % 4 == 0);
|
||||
|
||||
pthread_mutex_lock(&(compress->lock));
|
||||
|
||||
if(tile_get(tx, 0, 0)->width != compress->tile->width ||
|
||||
tile_get(tx, 0, 0)->height != compress->tile->height ||
|
||||
tx->aux != compress->tx_aux ||
|
||||
if(vf_get_tile(tx, 0)->width != compress->tile->width ||
|
||||
vf_get_tile(tx, 0)->height != compress->tile->height ||
|
||||
tx->interlacing != compress->interlacing_source ||
|
||||
tx->color_spec != compress->tx_color_spec)
|
||||
{
|
||||
reconfigure_compress(compress, tile_get(tx, 0, 0)->width, tile_get(tx, 0, 0)->height, tx->color_spec, tx->aux, tx->fps);
|
||||
reconfigure_compress(compress, vf_get_tile(tx, 0)->width, vf_get_tile(tx, 0)->height, tx->color_spec, tx->interlacing, tx->fps);
|
||||
}
|
||||
|
||||
line1 = (unsigned char *)tx->tiles[0].data;
|
||||
@@ -299,9 +297,15 @@ struct video_frame * fastdxt_compress(void *args, struct video_frame *tx)
|
||||
line2 += compress->tile->linesize;
|
||||
}
|
||||
|
||||
if(tx->aux & AUX_INTERLACED)
|
||||
if(tx->interlacing != INTERLACED_MERGED && tx->interlacing != PROGRESSIVE) {
|
||||
fprintf(stderr, "Unsupported interlacing format.\n");
|
||||
exit_uv(1);
|
||||
}
|
||||
|
||||
if(tx->interlacing == INTERLACED_MERGED) {
|
||||
vc_deinterlace(compress->output_data, compress->tile->linesize,
|
||||
compress->tile->height);
|
||||
}
|
||||
|
||||
|
||||
for (x = 0; x < compress->num_threads; x++) {
|
||||
@@ -345,7 +349,7 @@ static void compress_thread(void *args)
|
||||
}
|
||||
my_range = my_height * compress->tile->width;
|
||||
|
||||
if(compress->frame->aux & AUX_YUV)
|
||||
if(!compress->rgb)
|
||||
{
|
||||
unsigned char *input;
|
||||
input = (compress->output_data) + myId
|
||||
|
||||
@@ -78,21 +78,19 @@ static void configure_with(struct compress_jpeg_state *s, struct video_frame *fr
|
||||
int x, y;
|
||||
int h_align = 0;
|
||||
|
||||
assert(tile_get(frame, 0, 0)->width % 4 == 0);
|
||||
s->out = vf_alloc(frame->grid_width, frame->grid_height);
|
||||
assert(vf_get_tile(frame, 0)->width % 4 == 0);
|
||||
s->out = vf_alloc(frame->tile_count);
|
||||
|
||||
for (x = 0; x < frame->grid_width; ++x) {
|
||||
for (y = 0; y < frame->grid_height; ++y) {
|
||||
if (tile_get(frame, x, y)->width != tile_get(frame, 0, 0)->width ||
|
||||
tile_get(frame, x, y)->width != tile_get(frame, 0, 0)->width)
|
||||
error_with_code_msg(128,"[JPEG] Requested to compress tiles of different size!");
|
||||
|
||||
tile_get(s->out, x, y)->width = tile_get(frame, 0, 0)->width;
|
||||
tile_get(s->out, x, y)->height = tile_get(frame, 0, 0)->height;
|
||||
}
|
||||
for (x = 0; x < frame->tile_count; ++x) {
|
||||
if (vf_get_tile(frame, x)->width != vf_get_tile(frame, 0)->width ||
|
||||
vf_get_tile(frame, x)->width != vf_get_tile(frame, 0)->width)
|
||||
error_with_code_msg(128,"[JPEG] Requested to compress tiles of different size!");
|
||||
|
||||
vf_get_tile(s->out, x)->width = vf_get_tile(frame, 0)->width;
|
||||
vf_get_tile(s->out, x)->height = vf_get_tile(frame, 0)->height;
|
||||
}
|
||||
|
||||
s->out->aux = frame->aux;
|
||||
s->out->interlacing = PROGRESSIVE;
|
||||
s->out->fps = frame->fps;
|
||||
s->out->color_spec = s->color_spec;
|
||||
|
||||
@@ -133,11 +131,16 @@ static void configure_with(struct compress_jpeg_state *s, struct video_frame *fr
|
||||
}
|
||||
|
||||
/* We will deinterlace the output frame */
|
||||
if(s->out->aux & AUX_INTERLACED)
|
||||
if(frame->interlacing == INTERLACED_MERGED)
|
||||
s->interlaced_input = TRUE;
|
||||
else
|
||||
else if(frame->interlacing == PROGRESSIVE)
|
||||
s->interlaced_input = FALSE;
|
||||
s->out->aux &= ~AUX_INTERLACED;
|
||||
else {
|
||||
fprintf(stderr, "Unsupported interlacing option: %s.\n", get_interlacing_description(frame->interlacing));
|
||||
free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
s->out->color_spec = JPEG;
|
||||
struct jpeg_image_parameters param_image;
|
||||
@@ -155,11 +158,8 @@ static void configure_with(struct compress_jpeg_state *s, struct video_frame *fr
|
||||
|
||||
s->encoder = jpeg_encoder_create(¶m_image, &s->encoder_param);
|
||||
|
||||
for (x = 0; x < frame->grid_width; ++x) {
|
||||
for (y = 0; y < frame->grid_height; ++y) {
|
||||
tile_get(s->out, x, y)->data = (char *) malloc(s->out->tiles[0].width * s->jpeg_height * 3);
|
||||
tile_get(s->out, x, y)->linesize = s->out->tiles[0].width * (param_image.color_space == JPEG_RGB ? 3 : 2);
|
||||
}
|
||||
for (x = 0; x < frame->tile_count; ++x) {
|
||||
vf_get_tile(s->out, x)->data = (char *) malloc(s->out->tiles[0].width * s->jpeg_height * 3);
|
||||
}
|
||||
|
||||
if(!s->encoder) {
|
||||
@@ -242,42 +242,40 @@ struct video_frame * jpeg_compress(void *arg, struct video_frame * tx)
|
||||
if(!s->encoder)
|
||||
configure_with(s, tx);
|
||||
|
||||
for (x = 0; x < tx->grid_width; ++x) {
|
||||
for (y = 0; y < tx->grid_height; ++y) {
|
||||
struct tile *in_tile = tile_get(tx, x, y);
|
||||
struct tile *out_tile = tile_get(s->out, x, y);
|
||||
|
||||
line1 = (unsigned char *) in_tile->data;
|
||||
line2 = (unsigned char *) s->decoded;
|
||||
|
||||
for (i = 0; i < (int) in_tile->height; ++i) {
|
||||
s->decoder(line2, line1, out_tile->linesize,
|
||||
0, 8, 16);
|
||||
line1 += vc_get_linesize(in_tile->width, tx->color_spec);
|
||||
line2 += out_tile->linesize;
|
||||
}
|
||||
|
||||
line1 = out_tile->data + (in_tile->height - 1) * out_tile->linesize;
|
||||
for( ; i < s->jpeg_height; ++i) {
|
||||
memcpy(line2, line1, out_tile->linesize);
|
||||
line2 += out_tile->linesize;
|
||||
}
|
||||
|
||||
if(s->interlaced_input)
|
||||
vc_deinterlace((unsigned char *) s->decoded, out_tile->linesize,
|
||||
s->jpeg_height);
|
||||
|
||||
uint8_t *compressed;
|
||||
int size;
|
||||
int ret;
|
||||
ret = jpeg_encoder_encode(s->encoder, s->decoded, &compressed, &size);
|
||||
|
||||
if(ret != 0)
|
||||
return NULL;
|
||||
|
||||
out_tile->data_len = size;
|
||||
memcpy(out_tile->data, compressed, size);
|
||||
for (x = 0; x < tx->tile_count; ++x) {
|
||||
struct tile *in_tile = vf_get_tile(tx, x);
|
||||
struct tile *out_tile = vf_get_tile(s->out, x);
|
||||
|
||||
line1 = (unsigned char *) in_tile->data;
|
||||
line2 = (unsigned char *) s->decoded;
|
||||
|
||||
for (i = 0; i < (int) in_tile->height; ++i) {
|
||||
s->decoder(line2, line1, out_tile->linesize,
|
||||
0, 8, 16);
|
||||
line1 += vc_get_linesize(in_tile->width, tx->color_spec);
|
||||
line2 += out_tile->linesize;
|
||||
}
|
||||
|
||||
line1 = out_tile->data + (in_tile->height - 1) * out_tile->linesize;
|
||||
for( ; i < s->jpeg_height; ++i) {
|
||||
memcpy(line2, line1, out_tile->linesize);
|
||||
line2 += out_tile->linesize;
|
||||
}
|
||||
|
||||
if(s->interlaced_input)
|
||||
vc_deinterlace((unsigned char *) s->decoded, out_tile->linesize,
|
||||
s->jpeg_height);
|
||||
|
||||
uint8_t *compressed;
|
||||
int size;
|
||||
int ret;
|
||||
ret = jpeg_encoder_encode(s->encoder, s->decoded, &compressed, &size);
|
||||
|
||||
if(ret != 0)
|
||||
return NULL;
|
||||
|
||||
out_tile->data_len = size;
|
||||
memcpy(out_tile->data, compressed, size);
|
||||
}
|
||||
|
||||
return s->out;
|
||||
|
||||
@@ -79,7 +79,7 @@ typedef struct {
|
||||
struct video_frame *(*func_getf) (void *state);
|
||||
int (*func_putf) (void *state, char *frame);
|
||||
void (*func_reconfigure)(void *state, struct video_desc desc);
|
||||
int (*func_get_property)(void *state, int property, void *val, int *len);
|
||||
int (*func_get_property)(void *state, int property, void *val, size_t *len);
|
||||
|
||||
struct audio_frame *(*func_get_audio_frame) (void *state);
|
||||
void (*func_put_audio_frame) (void *state, const struct audio_frame *frame);
|
||||
@@ -325,7 +325,7 @@ void display_reconfigure(struct display *d, struct video_desc desc)
|
||||
display_device_table[d->index].func_reconfigure(d->state, desc);
|
||||
}
|
||||
|
||||
int display_get_property(struct display *d, int property, void *val, int *len)
|
||||
int display_get_property(struct display *d, int property, void *val, size_t *len)
|
||||
{
|
||||
assert(d->magic == DISPLAY_MAGIC);
|
||||
return display_device_table[d->index].func_get_property(d->state, property, val, len);
|
||||
|
||||
@@ -79,8 +79,11 @@ typedef struct {
|
||||
#define DISPLAY_PROPERTY_GSHIFT 2 /* int */
|
||||
#define DISPLAY_PROPERTY_BSHIFT 3 /* int */
|
||||
#define DISPLAY_PROPERTY_BUF_PITCH 4 /* int */
|
||||
#define DISPLAY_PROPERTY_VIDEO_MODE 5 /* int */
|
||||
|
||||
#define PITCH_DEFAULT -1 /* default to linesize */
|
||||
#define DISPLAY_PROPERTY_VIDEO_MERGED 0
|
||||
#define DISPLAY_PROPERTY_VIDEO_SEPARATE_TILES 1
|
||||
|
||||
int display_init_devices(void);
|
||||
void display_free_devices(void);
|
||||
@@ -106,7 +109,7 @@ void display_reconfigure(struct display *d, struct video_desc desc);
|
||||
struct audio_frame * display_get_audio_frame(struct display *d);
|
||||
void display_put_audio_frame(struct display *d, const struct audio_frame *frame);
|
||||
|
||||
int display_get_property(struct display *d, int property, void *val, int *len);
|
||||
int display_get_property(struct display *d, int property, void *val, size_t *len);
|
||||
|
||||
/*
|
||||
* Additional interface allowing querying properties and monitoring changes
|
||||
|
||||
@@ -354,7 +354,7 @@ static BMDDisplayMode get_mode(IDeckLinkOutput *deckLinkOutput, struct video_des
|
||||
deckLinkDisplayMode->GetFrameRate(frameRateDuration,
|
||||
frameRateScale);
|
||||
displayFPS = (double) *frameRateScale / *frameRateDuration;
|
||||
if(fabs(desc.fps - displayFPS) < 0.01// && (aux & AUX_INTERLACED && interlaced || !interlaced)
|
||||
if(fabs(desc.fps - displayFPS) < 0.01 && (desc.interlacing == INTERLACED_MERGED && interlaced || !interlaced)
|
||||
)
|
||||
{
|
||||
printf("Device %d - selected mode: %s\n", index, modeNameCString);
|
||||
@@ -383,7 +383,7 @@ display_decklink_reconfigure(void *state, struct video_desc desc)
|
||||
assert(s->magic == DECKLINK_MAGIC);
|
||||
|
||||
s->frame->color_spec = desc.color_spec;
|
||||
s->frame->aux = desc.aux;
|
||||
s->frame->interlacing = desc.interlacing;
|
||||
s->frame->fps = desc.fps;
|
||||
|
||||
switch (desc.color_spec) {
|
||||
@@ -403,7 +403,7 @@ display_decklink_reconfigure(void *state, struct video_desc desc)
|
||||
if(s->stereo) {
|
||||
desc.width /= 2; // half of with for each channel
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
struct tile *tile = tile_get(s->frame, i, 0);
|
||||
struct tile *tile = vf_get_tile(s->frame, i);
|
||||
tile->width = desc.width;
|
||||
tile->height = desc.height;
|
||||
tile->linesize = vc_get_linesize(tile->width, s->frame->color_spec);
|
||||
@@ -420,7 +420,7 @@ display_decklink_reconfigure(void *state, struct video_desc desc)
|
||||
exit(128);
|
||||
}
|
||||
|
||||
s->state[0].deckLinkFrame = DeckLink3DFrame::Create(desc.width, desc.height, tile_get(s->frame, 0, 0)->linesize, pixelFormat);
|
||||
s->state[0].deckLinkFrame = DeckLink3DFrame::Create(desc.width, desc.height, vf_get_tile(s->frame, 0)->linesize, pixelFormat);
|
||||
|
||||
s->state[0].deckLinkOutput->EnableVideoOutput(displayMode, bmdVideoOutputDualStream3D);
|
||||
s->state[0].deckLinkFrame->GetBytes((void **) &s->frame->tiles[0].data);
|
||||
@@ -433,10 +433,16 @@ display_decklink_reconfigure(void *state, struct video_desc desc)
|
||||
for(int i = 0; i < s->devices_cnt; ++i) {
|
||||
struct video_desc desc_dev;
|
||||
/* compute position */
|
||||
int x_count = s->frame->grid_width;
|
||||
int y_count = s->frame->grid_height;
|
||||
struct tile *tile = tile_get(s->frame, i % x_count,
|
||||
i / x_count);
|
||||
int x_count;
|
||||
int y_count;
|
||||
if(s->devices_cnt == 2) { /* stereo */
|
||||
x_count = 2;
|
||||
y_count = 1;
|
||||
} else if (s->devices_cnt == 4) { /* tiled 4K */
|
||||
x_count = y_count = 2;
|
||||
}
|
||||
|
||||
struct tile *tile = vf_get_tile(s->frame, i);
|
||||
|
||||
desc_dev = desc;
|
||||
|
||||
@@ -575,17 +581,11 @@ void *display_decklink_init(char *fmt, unsigned int flags)
|
||||
s->play_audio = FALSE;
|
||||
}
|
||||
|
||||
double x_cnt = sqrt(s->devices_cnt);
|
||||
int x_count = x_cnt - round(x_cnt) == 0.0 ? x_cnt : s->devices_cnt;
|
||||
int y_count = s->devices_cnt / x_count;
|
||||
if(s->stereo) {
|
||||
s->frame = vf_alloc(2, 1);
|
||||
s->frame = vf_alloc(2);
|
||||
} else {
|
||||
s->frame = vf_alloc(x_count, y_count);
|
||||
s->frame = vf_alloc(s->devices_cnt);
|
||||
}
|
||||
if(s->devices_cnt > 1) {
|
||||
s->frame->aux = AUX_TILED;
|
||||
}
|
||||
|
||||
for(int i = 0; i < s->devices_cnt; ++i) {
|
||||
// Obtain the audio/video output interface (IDeckLinkOutput)
|
||||
@@ -634,8 +634,9 @@ display_type_t *display_decklink_probe(void)
|
||||
return dtype;
|
||||
}
|
||||
|
||||
int display_decklink_get_property(void *state, int property, void *val, int *len)
|
||||
int display_decklink_get_property(void *state, int property, void *val, size_t *len)
|
||||
{
|
||||
struct state_decklink *s = (struct state_decklink *)state;
|
||||
codec_t codecs[] = {v210, UYVY, RGBA};
|
||||
|
||||
switch (property) {
|
||||
@@ -664,6 +665,12 @@ int display_decklink_get_property(void *state, int property, void *val, int *len
|
||||
*(int *) val = PITCH_DEFAULT;
|
||||
*len = sizeof(int);
|
||||
break;
|
||||
case DISPLAY_PROPERTY_VIDEO_MODE:
|
||||
if(s->devices_cnt == 1)
|
||||
*(int *) val = DISPLAY_PROPERTY_VIDEO_MERGED;
|
||||
else
|
||||
*(int *) val = DISPLAY_PROPERTY_VIDEO_SEPARATE_TILES;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ struct video_frame *display_decklink_getf(void *state);
|
||||
int display_decklink_putf(void *state, char *frame);
|
||||
void display_decklink_reconfigure(void *state,
|
||||
struct video_desc desc);
|
||||
int display_decklink_get_property(void *state, int property, void *val, int *len);
|
||||
int display_decklink_get_property(void *state, int property, void *val, size_t *len);
|
||||
|
||||
struct audio_frame * display_decklink_get_audio_frame(void *state);
|
||||
void display_decklink_put_audio_frame(void *state, struct audio_frame *frame);
|
||||
|
||||
@@ -79,7 +79,7 @@ typedef struct audio_frame * (*display_dvs_get_audio_frame_t)(void *state);
|
||||
typedef void (*display_dvs_put_audio_frame_t)(void *state, struct audio_frame *frame);
|
||||
typedef void (*display_dvs_reconfigure_t)(void *state,
|
||||
struct video_desc desc);
|
||||
typedef int (*display_dvs_get_property_t)(void *state, int property, void *val, int *len);
|
||||
typedef int (*display_dvs_get_property_t)(void *state, int property, void *val, size_t *len);
|
||||
|
||||
static display_dvs_init_t display_dvs_init_func = NULL;
|
||||
static display_dvs_run_t display_dvs_run_func = NULL;
|
||||
@@ -261,7 +261,7 @@ void display_dvs_reconfigure(void *state,
|
||||
display_dvs_reconfigure_func(state, desc);
|
||||
}
|
||||
|
||||
int display_dvs_get_property(void *state, int property, void *val, int *len)
|
||||
int display_dvs_get_property(void *state, int property, void *val, size_t *len)
|
||||
{
|
||||
pthread_once(&DVSLibraryLoad, loadLibrary);
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ struct video_frame *display_dvs_getf(void *state);
|
||||
int display_dvs_putf(void *state, char *frame);
|
||||
void display_dvs_reconfigure(void *state,
|
||||
struct video_desc desc);
|
||||
int display_dvs_get_property(void *state, int property, void *val, int *len);
|
||||
int display_dvs_get_property(void *state, int property, void *val, size_t *len);
|
||||
|
||||
struct audio_frame * display_dvs_get_audio_frame(void *state);
|
||||
void display_dvs_put_audio_frame(void *state, struct audio_frame *frame);
|
||||
|
||||
@@ -502,7 +502,7 @@ void display_dvs_reconfigure_impl(void *state,
|
||||
|
||||
s->frame->color_spec = desc.color_spec;
|
||||
s->frame->fps = desc.fps;
|
||||
s->frame->aux = desc.aux;
|
||||
s->frame->interlacing = desc.interlacing;
|
||||
s->tile->width = desc.width;
|
||||
s->tile->height = desc.height;
|
||||
|
||||
@@ -512,17 +512,21 @@ void display_dvs_reconfigure_impl(void *state,
|
||||
for(i=0; hdsp_mode_table[i].width != 0; i++) {
|
||||
if(hdsp_mode_table[i].width == desc.width &&
|
||||
hdsp_mode_table[i].height == desc.height &&
|
||||
(desc.aux == 0 || (desc.aux & hdsp_mode_table[i].aux)) &&
|
||||
fabs(desc.fps - hdsp_mode_table[i].fps) < 0.01 ) {
|
||||
s->mode = &hdsp_mode_table[i];
|
||||
break;
|
||||
if ((desc.interlacing == INTERLACED_MERGED && hdsp_mode_table[i].aux == AUX_INTERLACED ) ||
|
||||
(desc.interlacing == PROGRESSIVE && hdsp_mode_table[i].aux == AUX_PROGRESSIVE) ||
|
||||
(desc.interlacing == SEGMENTED_FRAME && hdsp_mode_table[i].aux == AUX_SF)) {
|
||||
s->mode = &hdsp_mode_table[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(s->mode == NULL) {
|
||||
fprintf(stderr, "Reconfigure failed. Expect troubles pretty soon..\n"
|
||||
"\tRequested: %dx%d, color space %d, fps %f, aux: %d\n",
|
||||
desc.width, desc.height, desc.color_spec, desc.fps, desc.aux);
|
||||
"\tRequested: %dx%d, color space %d, fps %f,%s\n",
|
||||
desc.width, desc.height, desc.color_spec, desc.fps,
|
||||
get_interlacing_description(desc.interlacing));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -608,8 +612,8 @@ void *display_dvs_init_impl(char *fmt, unsigned int flags)
|
||||
|
||||
s->mode_set_manually = FALSE;
|
||||
|
||||
s->frame = vf_alloc(1, 1);
|
||||
s->tile = tile_get(s->frame, 0, 0);
|
||||
s->frame = vf_alloc(1);
|
||||
s->tile = vf_get_tile(s->frame, 0);
|
||||
|
||||
if (fmt != NULL) {
|
||||
if (strcmp(fmt, "help") == 0) {
|
||||
@@ -681,7 +685,23 @@ void *display_dvs_init_impl(char *fmt, unsigned int flags)
|
||||
s->first_run = TRUE;
|
||||
|
||||
if(s->mode) {
|
||||
struct video_desc desc = {s->mode->width, s->mode->height, s->frame->color_spec, s->mode->aux, s->mode->fps};
|
||||
struct video_desc desc;
|
||||
desc.width = s->mode->width;
|
||||
desc.height = s->mode->height;
|
||||
desc.color_spec = s->frame->color_spec;
|
||||
switch(s->mode->aux) {
|
||||
case AUX_INTERLACED:
|
||||
desc.interlacing = INTERLACED_MERGED;
|
||||
break;
|
||||
case AUX_PROGRESSIVE:
|
||||
desc.interlacing = PROGRESSIVE;
|
||||
break;
|
||||
case AUX_SF:
|
||||
desc.interlacing = SEGMENTED_FRAME;
|
||||
break;
|
||||
}
|
||||
desc.fps = s->mode->fps;
|
||||
|
||||
display_dvs_reconfigure_impl(s,
|
||||
desc);
|
||||
s->mode_set_manually = TRUE;
|
||||
@@ -721,7 +741,7 @@ void display_dvs_done_impl(void *state)
|
||||
free(s);
|
||||
}
|
||||
|
||||
int display_dvs_get_property_impl(void *state, int property, void *val, int *len)
|
||||
int display_dvs_get_property_impl(void *state, int property, void *val, size_t *len)
|
||||
{
|
||||
codec_t codecs[] = {DVS10, UYVY, RGBA, RGB};
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ struct video_frame *display_dvs_getf_impl(void *state);
|
||||
int display_dvs_putf_impl(void *state, char *frame);
|
||||
void display_dvs_reconfigure_impl(void *state,
|
||||
struct video_desc desc);
|
||||
int display_dvs_get_property_impl(void *state, int property, void *val, int *len);
|
||||
int display_dvs_get_property_impl(void *state, int property, void *val, size_t *len);
|
||||
|
||||
struct audio_frame * display_dvs_get_audio_frame_impl(void *state);
|
||||
void display_dvs_put_audio_frame_impl(void *state, struct audio_frame *frame);
|
||||
|
||||
@@ -322,8 +322,8 @@ void * display_gl_init(char *fmt, unsigned int flags) {
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
s->frame = vf_alloc(1, 1);
|
||||
s->tile = tile_get(s->frame, 0, 0);
|
||||
s->frame = vf_alloc(1);
|
||||
s->tile = vf_get_tile(s->frame, 0);
|
||||
s->tile->data = NULL;
|
||||
|
||||
s->frames = 0ul;
|
||||
@@ -482,7 +482,7 @@ void display_gl_reconfigure(void *state, struct video_desc desc)
|
||||
s->tile->width = desc.width;
|
||||
s->tile->height = desc.height;
|
||||
s->frame->fps = desc.fps;
|
||||
s->frame->aux = desc.aux;
|
||||
s->frame->interlacing = desc.interlacing;
|
||||
s->frame->color_spec = desc.color_spec;
|
||||
|
||||
pthread_mutex_lock(&s->lock);
|
||||
@@ -914,7 +914,7 @@ display_type_t *display_gl_probe(void)
|
||||
return dt;
|
||||
}
|
||||
|
||||
int display_gl_get_property(void *state, int property, void *val, int *len)
|
||||
int display_gl_get_property(void *state, int property, void *val, size_t *len)
|
||||
{
|
||||
UNUSED(state);
|
||||
codec_t codecs[] = {UYVY, RGBA, RGB, DXT1, DXT1_YUV, DXT5};
|
||||
|
||||
@@ -59,6 +59,6 @@ void display_gl_done(void *state);
|
||||
struct video_frame *display_gl_getf(void *state);
|
||||
int display_gl_putf(void *state, char *frame);
|
||||
void display_gl_reconfigure(void *state, struct video_desc desc);
|
||||
int display_gl_get_property(void *state, int property, void *val, int *len);
|
||||
int display_gl_get_property(void *state, int property, void *val, size_t *len);
|
||||
|
||||
int display_gl_handle_events(void *arg);
|
||||
|
||||
@@ -109,7 +109,7 @@ display_type_t *display_null_probe(void)
|
||||
return dt;
|
||||
}
|
||||
|
||||
int display_null_get_property(void *state, int property, void *val, int *len)
|
||||
int display_null_get_property(void *state, int property, void *val, size_t *len)
|
||||
{
|
||||
UNUSED(state);
|
||||
UNUSED(property);
|
||||
|
||||
@@ -53,4 +53,4 @@ void display_null_done(void *state);
|
||||
char *display_null_getf(void *state);
|
||||
int display_null_putf(void *state, char *frame);
|
||||
void display_null_reconfigure(void *state, struct video_desc desc);
|
||||
int display_null_get_property(void *state, int property, void *val, int *len);
|
||||
int display_null_get_property(void *state, int property, void *val, size_t *len);
|
||||
|
||||
@@ -212,7 +212,7 @@ struct state_quicktime {
|
||||
/* Prototyping */
|
||||
char *four_char_decode(int format);
|
||||
static int find_mode(ComponentInstance *ci, int width, int height,
|
||||
const char * codec_name, double fps, int aux);
|
||||
const char * codec_name, double fps);
|
||||
void display_quicktime_audio_init(struct state_quicktime *s);
|
||||
void display_quicktime_reconfigure_audio(void *state, int quant_samples, int channels,
|
||||
int sample_rate);
|
||||
@@ -258,8 +258,7 @@ static void reconf_common(struct state_quicktime *s)
|
||||
|
||||
for (i = 0; i < s->devices_cnt; ++i)
|
||||
{
|
||||
struct tile *tile = tile_get(s->frame, i % s->frame->grid_width,
|
||||
i / s->frame->grid_width);
|
||||
struct tile *tile = vf_get_tile(s->frame, i);
|
||||
ImageDescriptionHandle imageDesc;
|
||||
OSErr ret;
|
||||
|
||||
@@ -316,8 +315,7 @@ void display_quicktime_run(void *arg)
|
||||
platform_sem_wait(&s->semaphore);
|
||||
|
||||
for (i = 0; i < s->devices_cnt; ++i) {
|
||||
struct tile *tile = tile_get(s->frame, i % s->frame->grid_width,
|
||||
i / s->frame->grid_width);
|
||||
struct tile *tile = vf_get_tile(s->frame, i);
|
||||
/* TODO: Running DecompressSequenceFrameWhen asynchronously
|
||||
* in this way introduces a possible race condition!
|
||||
*/
|
||||
@@ -594,11 +592,7 @@ void *display_quicktime_init(char *fmt, unsigned int flags)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
double x_cnt = sqrt(s->devices_cnt);
|
||||
int x_count = x_cnt - round(x_cnt) == 0.0 ? x_cnt : s->devices_cnt;
|
||||
int y_count = s->devices_cnt / x_count;
|
||||
|
||||
s->frame = vf_alloc(x_count, y_count);
|
||||
s->frame = vf_alloc(s->devices_cnt);
|
||||
|
||||
for (i = 0; i < s->devices_cnt; ++i) {
|
||||
s->videoDisplayComponentInstance[i] = 0;
|
||||
@@ -616,12 +610,9 @@ void *display_quicktime_init(char *fmt, unsigned int flags)
|
||||
}
|
||||
free(codec_name);
|
||||
s->frame->color_spec = s->cinfo->codec;
|
||||
s->frame->aux = 0;
|
||||
|
||||
for (i = 0; i < s->devices_cnt; ++i) {
|
||||
int pos_x = i % x_count;
|
||||
int pos_y = i / y_count;
|
||||
struct tile *tile = tile_get(s->frame, pos_x, pos_y);
|
||||
struct tile *tile = vf_get_tile(i);
|
||||
/* Open device */
|
||||
s->videoDisplayComponentInstance[i] = OpenComponent((Component) s->device[i]);
|
||||
|
||||
@@ -819,7 +810,7 @@ display_type_t *display_quicktime_probe(void)
|
||||
return dtype;
|
||||
}
|
||||
|
||||
int display_quicktime_get_property(void *state, int property, void *val, int *len)
|
||||
int display_quicktime_get_property(void *state, int property, void *val, size_t *len)
|
||||
{
|
||||
UNUSED(state);
|
||||
codec_t codecs[] = {v210, UYVY, RGBA};
|
||||
@@ -850,6 +841,12 @@ int display_quicktime_get_property(void *state, int property, void *val, int *le
|
||||
*(int *) val = PITCH_DEFAULT;
|
||||
*len = sizeof(int);
|
||||
break;
|
||||
case DISPLAY_PROPERTY_VIDEO_MODE:
|
||||
if(s->devices_cnt == 1)
|
||||
*(int *) val = DISPLAY_PROPERTY_VIDEO_MERGED;
|
||||
else
|
||||
*(int *) val = DISPLAY_PROPERTY_VIDEO_SEPARATE_TILES;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
@@ -880,14 +877,23 @@ void display_quicktime_reconfigure(void *state, struct video_desc desc)
|
||||
desc.height, s->cinfo->bpp);
|
||||
s->frame->color_spec = desc.color_spec;
|
||||
s->frame->fps = desc.fps;
|
||||
s->frame->aux = desc.aux;
|
||||
s->frame->interlacing = desc.interlacing;
|
||||
|
||||
for(i = 0; i < s->devices_cnt; ++i) {
|
||||
int tile_width = desc.width / s->frame->grid_width;
|
||||
int tile_height = desc.height / s->frame->grid_height;
|
||||
int pos_x = i % s->frame->grid_width;
|
||||
int pos_y = i / s->frame->grid_width;
|
||||
struct tile * tile = tile_get(s->frame, pos_x, pos_y);
|
||||
|
||||
int tile_width;
|
||||
int tile_height;
|
||||
|
||||
if(s->devices_cnt == 2) { /* stereo */
|
||||
tile_width = desc.width / 2;
|
||||
tile_height = desc.height;
|
||||
}
|
||||
if(s->devices_cnt = 4) { /*tiled 4K */
|
||||
tile_width = desc.width / 2;
|
||||
tile_height = desc.height / 2;
|
||||
}
|
||||
|
||||
struct tile * tile = vf_get_tile(s->frame, i);
|
||||
|
||||
tile->width = tile_width;
|
||||
tile->height = tile_height;
|
||||
@@ -904,7 +910,7 @@ void display_quicktime_reconfigure(void *state, struct video_desc desc)
|
||||
|
||||
if(!s->mode_set_manually)
|
||||
s->mode = find_mode(&s->videoDisplayComponentInstance[i],
|
||||
tile_width, tile_height, codec_name, desc.fps, desc.aux);
|
||||
tile_width, tile_height, codec_name, desc.fps);
|
||||
/* Set the display mode */
|
||||
ret =
|
||||
QTVideoOutputSetDisplayMode(s->videoDisplayComponentInstance[i],
|
||||
@@ -952,9 +958,8 @@ void display_quicktime_reconfigure(void *state, struct video_desc desc)
|
||||
}
|
||||
|
||||
static int find_mode(ComponentInstance *ci, int width, int height,
|
||||
const char * codec_name, double fps, int aux)
|
||||
const char * codec_name, double fps)
|
||||
{
|
||||
UNUSED(aux);
|
||||
|
||||
QTAtom atomDisplay = 0, nextAtomDisplay = 0;
|
||||
QTAtomType type;
|
||||
|
||||
@@ -69,7 +69,7 @@ void display_quicktime_done(void *state);
|
||||
struct video_frame *display_quicktime_getf(void *state);
|
||||
int display_quicktime_putf(void *state, char *frame);
|
||||
void display_quicktime_reconfigure(void *state, struct video_desc desc);
|
||||
int display_quicktime_get_property(void *state, int property, void *val, int *len);
|
||||
int display_quicktime_get_property(void *state, int property, void *val, size_t *len);
|
||||
|
||||
struct audio_frame *display_quicktime_get_audio_frame(void *state);
|
||||
void display_quicktime_put_audio_frame(void *state, const struct audio_frame *frame);
|
||||
|
||||
@@ -131,8 +131,8 @@ void *display_sage_init(char *fmt, unsigned int flags)
|
||||
s = (struct state_sage *)malloc(sizeof(struct state_sage));
|
||||
s->magic = MAGIC_SAGE;
|
||||
|
||||
s->frame = vf_alloc(1, 1);
|
||||
s->tile = tile_get(s->frame, 0, 0);
|
||||
s->frame = vf_alloc(1);
|
||||
s->tile = vf_get_tile(s->frame, 0);
|
||||
|
||||
/* sage init */
|
||||
//FIXME sem se musi propasovat ty spravne parametry argc argv
|
||||
@@ -220,7 +220,7 @@ void display_sage_reconfigure(void *state, struct video_desc desc)
|
||||
s->tile->width = desc.width;
|
||||
s->tile->height = desc.height;
|
||||
s->frame->fps = desc.fps;
|
||||
s->frame->aux = desc.aux;
|
||||
s->frame->interlacing = desc.interlacing;
|
||||
s->frame->color_spec = desc.color_spec;
|
||||
|
||||
if(s->sage_state) {
|
||||
@@ -246,7 +246,7 @@ display_type_t *display_sage_probe(void)
|
||||
return dt;
|
||||
}
|
||||
|
||||
int display_sage_get_property(void *state, int property, void *val, int *len)
|
||||
int display_sage_get_property(void *state, int property, void *val, size_t *len)
|
||||
{
|
||||
UNUSED(state);
|
||||
codec_t codecs[] = {UYVY, RGBA, RGB, DXT1};
|
||||
|
||||
@@ -57,7 +57,7 @@ void display_sage_done(void *state);
|
||||
struct video_frame *display_sage_getf(void *state);
|
||||
int display_sage_putf(void *state, char *frame);
|
||||
void display_sage_reconfigure(void *state, struct video_desc desc);
|
||||
int display_sage_get_property(void *state, int property, void *val, int *len);
|
||||
int display_sage_get_property(void *state, int property, void *val, size_t *len);
|
||||
|
||||
int display_sage_handle_events(void);
|
||||
|
||||
|
||||
@@ -50,7 +50,9 @@
|
||||
#include "sage_wrapper.h"
|
||||
#include <sail.h>
|
||||
#include <misc.h>
|
||||
extern "C" {
|
||||
#include "host.h"
|
||||
}
|
||||
|
||||
void *initSage(int appID, int nodeID, int width, int height, codec_t codec)
|
||||
{
|
||||
|
||||
@@ -158,7 +158,7 @@ static void loadSplashscreen(struct state_sdl *s) {
|
||||
x_res_x = video_info->current_w;
|
||||
x_res_y = video_info->current_h;
|
||||
|
||||
if(splash_height > tile_get(s->frame, 0, 0)->height || splash_width > tile_get(s->frame, 0, 0)->width)
|
||||
if(splash_height > vf_get_tile(s->frame, 0)->height || splash_width > vf_get_tile(s->frame, 0)->width)
|
||||
return;
|
||||
|
||||
// create a temporary SDL_Surface with the settings of displaying surface
|
||||
@@ -435,7 +435,7 @@ void display_sdl_reconfigure(void *state, struct video_desc desc)
|
||||
s->tile->height = desc.height;
|
||||
|
||||
s->frame->fps = desc.fps;
|
||||
s->frame->aux = desc.aux;
|
||||
s->frame->interlacing = desc.interlacing;
|
||||
s->frame->color_spec = desc.color_spec;
|
||||
|
||||
fprintf(stdout, "Reconfigure to size %dx%d\n", desc.width,
|
||||
@@ -614,8 +614,8 @@ void *display_sdl_init(char *fmt, unsigned int flags)
|
||||
s->buffer_writable_lock = SDL_CreateMutex();
|
||||
s->buffer_writable_cond = SDL_CreateCond();
|
||||
|
||||
s->frame = vf_alloc(1, 1);
|
||||
s->tile = tile_get(s->frame, 0, 0);
|
||||
s->frame = vf_alloc(1);
|
||||
s->tile = vf_get_tile(s->frame, 0);
|
||||
|
||||
video_info = SDL_GetVideoInfo();
|
||||
s->screen_w = video_info->current_w;
|
||||
@@ -714,7 +714,7 @@ display_type_t *display_sdl_probe(void)
|
||||
return dt;
|
||||
}
|
||||
|
||||
int display_sdl_get_property(void *state, int property, void *val, int *len)
|
||||
int display_sdl_get_property(void *state, int property, void *val, size_t *len)
|
||||
{
|
||||
struct state_sdl *s = (struct state_sdl *) state;
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ struct video_frame *display_sdl_getf (void *state);
|
||||
int display_sdl_putf (void *state, char *frame);
|
||||
|
||||
void display_sdl_reconfigure(void *state, struct video_desc desc);
|
||||
int display_sdl_get_property(void *state, int property, void *val, int *len);
|
||||
int display_sdl_get_property(void *state, int property, void *val, size_t *len);
|
||||
|
||||
struct audio_frame * display_sdl_get_audio_frame(void *state);
|
||||
void display_sdl_put_audio_frame(void *state, const struct audio_frame *frame);
|
||||
|
||||
@@ -125,10 +125,10 @@ struct vo_postprocess_state *vo_postprocess_init(char *config_string)
|
||||
}
|
||||
|
||||
struct video_frame * vo_postprocess_reconfigure(struct vo_postprocess_state *s,
|
||||
struct video_desc desc, struct tile_info ti)
|
||||
struct video_desc desc)
|
||||
{
|
||||
if(s) {
|
||||
return s->handle->reconfigure(s->state, desc, ti);
|
||||
return s->handle->reconfigure(s->state, desc);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
@@ -146,8 +146,8 @@ void vo_postprocess_done(struct vo_postprocess_state *s)
|
||||
if(s) s->handle->done(s->state);
|
||||
}
|
||||
|
||||
void vo_postprocess_get_out_desc(struct vo_postprocess_state *s, struct video_desc_ti *out)
|
||||
void vo_postprocess_get_out_desc(struct vo_postprocess_state *s, struct video_desc *out, int *display_mode)
|
||||
{
|
||||
if(s) s->handle->get_out_desc(s->state, out);
|
||||
if(s) s->handle->get_out_desc(s->state, out, display_mode);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,8 +59,8 @@ typedef void *(*vo_postprocess_init_t)(char *cfg);
|
||||
*
|
||||
* @return frame to be written to
|
||||
*/
|
||||
typedef struct video_frame * (*vo_postprocess_reconfigure_t)(void *state, struct video_desc desc, struct tile_info);
|
||||
typedef void (*vo_postprocess_get_out_desc_t)(struct vo_postprocess_state *, struct video_desc_ti *out);
|
||||
typedef struct video_frame * (*vo_postprocess_reconfigure_t)(void *state, struct video_desc desc);
|
||||
typedef void (*vo_postprocess_get_out_desc_t)(struct vo_postprocess_state *, struct video_desc *out, int *display_mode);
|
||||
|
||||
/**
|
||||
* Postprocesses video frame
|
||||
@@ -77,10 +77,10 @@ typedef void (*vo_postprocess_t)(void *state, struct video_frame *in, struct vi
|
||||
typedef void (*vo_postprocess_done_t)(void *);
|
||||
|
||||
struct vo_postprocess_state *vo_postprocess_init(char *config_string);
|
||||
struct video_frame * vo_postprocess_reconfigure(struct vo_postprocess_state *, struct video_desc, struct tile_info);
|
||||
void vo_postprocess_get_out_desc(struct vo_postprocess_state *, struct video_desc_ti *out);
|
||||
struct video_frame * vo_postprocess_reconfigure(struct vo_postprocess_state *, struct video_desc);
|
||||
void vo_postprocess_get_out_desc(struct vo_postprocess_state *, struct video_desc *out, int *display_mode);
|
||||
void vo_postprocess(struct vo_postprocess_state *, struct video_frame*, struct video_frame*, int req_pitch);
|
||||
void compress_done(struct vo_postprocess_state *);
|
||||
void vo_postprocess_done(struct vo_postprocess_state *s);
|
||||
|
||||
void show_vo_postprocess_help(void);
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "debug.h"
|
||||
|
||||
#include "video_codec.h"
|
||||
#include "video_display.h" /* DISPLAY_PROPERTY_VIDEO_SEPARATE_FILES */
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include "vo_postprocess/3d-interleaved.h"
|
||||
@@ -64,31 +65,31 @@ void * interleaved_3d_init(char *config) {
|
||||
|
||||
s = (struct state_interleaved_3d *)
|
||||
malloc(sizeof(struct state_interleaved_3d));
|
||||
s->in = vf_alloc(2, 1);
|
||||
s->in = vf_alloc(2);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
struct video_frame * interleaved_3d_postprocess_reconfigure(void *state, struct video_desc desc, struct tile_info ti)
|
||||
struct video_frame * interleaved_3d_postprocess_reconfigure(void *state, struct video_desc desc)
|
||||
{
|
||||
struct state_interleaved_3d *s = (struct state_interleaved_3d *) state;
|
||||
|
||||
UNUSED(ti);
|
||||
assert(ti.x_count == 2 && ti.y_count == 1);
|
||||
assert(desc.video_mode == VIDEO_STEREO);
|
||||
|
||||
s->in->color_spec = desc.color_spec;
|
||||
s->in->fps = desc.fps;
|
||||
s->in->aux = desc.aux;
|
||||
tile_get(s->in, 0, 0)->width =
|
||||
tile_get(s->in, 1, 0)->width = desc.width / 2;
|
||||
tile_get(s->in, 0, 0)->height =
|
||||
tile_get(s->in, 1, 0)->height = desc.height;
|
||||
s->in->interlacing = desc.interlacing;
|
||||
vf_get_tile(s->in, 0)->width =
|
||||
vf_get_tile(s->in, 1)->width = desc.width / 2;
|
||||
vf_get_tile(s->in, 0)->height =
|
||||
vf_get_tile(s->in, 1)->height = desc.height;
|
||||
|
||||
tile_get(s->in, 0, 0)->data_len =
|
||||
tile_get(s->in, 1, 0)->data_len = vc_get_linesize(desc.width / 2, desc.color_spec)
|
||||
vf_get_tile(s->in, 0)->data_len =
|
||||
vf_get_tile(s->in, 1)->data_len = vc_get_linesize(desc.width / 2, desc.color_spec)
|
||||
* desc.height;
|
||||
tile_get(s->in, 0, 0)->data = malloc(tile_get(s->in, 0, 0)->data_len);
|
||||
tile_get(s->in, 1, 0)->data = malloc(tile_get(s->in, 1, 0)->data_len);
|
||||
vf_get_tile(s->in, 0)->data = malloc(vf_get_tile(s->in, 0)->data_len);
|
||||
vf_get_tile(s->in, 1)->data = malloc(vf_get_tile(s->in, 1)->data_len);
|
||||
fprintf(stderr, "xxxxxxxxxxx%d", vf_get_tile(s->in, 0)->data_len);
|
||||
|
||||
return s->in;
|
||||
}
|
||||
@@ -97,16 +98,16 @@ void interleaved_3d_postprocess(void *state, struct video_frame *in, struct vide
|
||||
{
|
||||
int x;
|
||||
|
||||
char *out_data = tile_get(out, 0, 0)->data;
|
||||
int linesize = vc_get_linesize(tile_get(out, 0, 0)->width, out->color_spec);
|
||||
char *out_data = vf_get_tile(out, 0)->data;
|
||||
int linesize = vc_get_linesize(vf_get_tile(out, 0)->width, out->color_spec);
|
||||
|
||||
/* we compute avg from line k/2*2 and k/2*2+1 for left eye and put
|
||||
* to (k/2*2)th line. Than we compute avg of same lines number
|
||||
* and put it to the following line, which creates interleaved stereo */
|
||||
for (x = 0; x < tile_get(out, 0, 0)->height; ++x) {
|
||||
for (x = 0; x < vf_get_tile(out, 0)->height; ++x) {
|
||||
int linepos;
|
||||
char *line1 = tile_get(in, x % 2, 0)->data + (x / 2) * 2 * linesize;
|
||||
char *line2 = tile_get(in, x % 2, 0)->data + ((x / 2) * 2 + 1) * linesize;
|
||||
char *line1 = vf_get_tile(in, x % 2)->data + (x / 2) * 2 * linesize;
|
||||
char *line2 = vf_get_tile(in, x % 2)->data + ((x / 2) * 2 + 1) * linesize;
|
||||
|
||||
for(linepos = 0; linepos < linesize; linepos += 16) {
|
||||
asm volatile ("movdqu (%0), %%xmm0\n"
|
||||
@@ -127,22 +128,22 @@ void interleaved_3d_done(void *state)
|
||||
{
|
||||
struct state_interleaved_3d *s = (struct state_interleaved_3d *) state;
|
||||
|
||||
free(tile_get(s->in, 0, 0)->data);
|
||||
free(tile_get(s->in, 1, 0)->data);
|
||||
free(vf_get_tile(s->in, 0)->data);
|
||||
free(vf_get_tile(s->in, 1)->data);
|
||||
vf_free(s->in);
|
||||
free(state);
|
||||
}
|
||||
|
||||
void interleaved_3d_get_out_desc(void *state, struct video_desc_ti *out)
|
||||
void interleaved_3d_get_out_desc(void *state, struct video_desc *out, int *display_mode)
|
||||
{
|
||||
struct state_interleaved_3d *s = (struct state_interleaved_3d *) state;
|
||||
|
||||
out->desc.width = tile_get(s->in, 0, 0)->width; /* not *2 !!!!!!*/
|
||||
out->desc.height = tile_get(s->in, 0, 0)->height;
|
||||
out->desc.color_spec = s->in->color_spec;
|
||||
out->desc.aux = s->in->aux;
|
||||
out->desc.fps = s->in->fps;
|
||||
|
||||
out->ti.x_count = s->in->grid_width;
|
||||
out->ti.y_count = s->in->grid_height;
|
||||
out->width = vf_get_tile(s->in, 0)->width; /* not *2 !!!!!!*/
|
||||
out->height = vf_get_tile(s->in, 0)->height;
|
||||
out->color_spec = s->in->color_spec;
|
||||
out->interlacing = s->in->interlacing;
|
||||
out->fps = s->in->fps;
|
||||
out->video_mode = VIDEO_NORMAL;
|
||||
|
||||
*display_mode = DISPLAY_PROPERTY_VIDEO_SEPARATE_TILES;
|
||||
}
|
||||
|
||||
@@ -48,8 +48,8 @@
|
||||
#include "video_codec.h"
|
||||
|
||||
void * interleaved_3d_init(char *config);
|
||||
struct video_frame * interleaved_3d_postprocess_reconfigure(void *state, struct video_desc desc, struct tile_info tile);
|
||||
void interleaved_3d_get_out_desc(void *state, struct video_desc_ti *out);
|
||||
struct video_frame * interleaved_3d_postprocess_reconfigure(void *state, struct video_desc desc);
|
||||
void interleaved_3d_get_out_desc(void *state, struct video_desc *out, int *display_mode);
|
||||
void interleaved_3d_postprocess(void *state, struct video_frame *in, struct video_frame *out, int req_pitch);
|
||||
void interleaved_3d_done(void *state);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user