From 6e02fed36ff416ca9e2429f95bb1bd60d4530242 Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Thu, 13 Mar 2014 15:04:58 +0100 Subject: [PATCH] Video decoder: run reconfiguration as a future If the reconfiguration lasts for a long time, we at least receive all packets from network. --- configure.ac | 2 +- src/rtp/video_decoders.cpp | 73 +++++++++++++++++++++++++++----------- 2 files changed, 53 insertions(+), 22 deletions(-) diff --git a/configure.ac b/configure.ac index f38aee231..5cbd94d6d 100644 --- a/configure.ac +++ b/configure.ac @@ -47,7 +47,7 @@ AC_CHECK_HEADERS(stropts.h sys/filio.h sys/wait.h) POST_COMPILE_MSG="" CFLAGS="$CFLAGS -I." CPPFLAGS="$CPPFLAGS -I." -CXXLAGS="$CXXLAGS -I." +CXXFLAGS="$CXXFLAGS -I. -D__STRICT_ANSI__ -std=c++0x" LIB_MODULES= AC_SUBST(LIBS) AC_SUBST(OBJS) diff --git a/src/rtp/video_decoders.cpp b/src/rtp/video_decoders.cpp index 7a549920b..ce15b9b46 100644 --- a/src/rtp/video_decoders.cpp +++ b/src/rtp/video_decoders.cpp @@ -92,6 +92,7 @@ #include "video_display.h" #include "vo_postprocess.h" +#include #include #include @@ -298,6 +299,9 @@ struct state_video_decoder message_queue msg_queue; struct openssl_decrypt *decrypt; ///< decrypt state + + std::future reconfiguration_future; + bool reconfiguration_in_progress; }; /** @@ -1354,6 +1358,15 @@ static bool reconfigure_decoder(struct state_video_decoder *decoder, } } + // Pass metadata to receiver thread (it can tweak parameters) + struct msg_receiver *msg = (struct msg_receiver *) + new_message(sizeof(struct msg_receiver)); + msg->type = RECEIVER_MSG_VIDEO_PROP_CHANGED; + msg->new_desc = decoder->received_vid_desc; + struct response *resp = + send_message_to_receiver(decoder->parent, (struct message *) msg); + resp->deleter(resp); + return true; } @@ -1385,8 +1398,6 @@ static bool parse_video_hdr(uint32_t *hdr, struct video_desc *desc) static int reconfigure_if_needed(struct state_video_decoder *decoder, struct video_desc network_desc) { - int ret = FALSE; - if (!video_desc_eq_excl_param(decoder->received_vid_desc, network_desc, PARAM_TILE_COUNT)) { printf("New incoming video format detected: %dx%d @%.2f%s, codec %s\n", network_desc.width, network_desc.height, network_desc.fps, @@ -1394,24 +1405,13 @@ static int reconfigure_if_needed(struct state_video_decoder *decoder, get_codec_name(network_desc.color_spec)); decoder->received_vid_desc = network_desc; - if (reconfigure_decoder(decoder, decoder->received_vid_desc)) { - decoder->frame = display_get_frame(decoder->display); - ret = TRUE; - } else { - decoder->frame = NULL; - ret = FALSE; - } + decoder->reconfiguration_in_progress = true; + decoder->reconfiguration_future = std::async(std::launch::async, + [&decoder](){ return reconfigure_decoder(decoder, decoder->received_vid_desc); }); - // Pass metadata to receiver thread (it can tweak parameters) - struct msg_receiver *msg = (struct msg_receiver *) - new_message(sizeof(struct msg_receiver)); - msg->type = RECEIVER_MSG_VIDEO_PROP_CHANGED; - msg->new_desc = decoder->received_vid_desc; - struct response *resp = - send_message_to_receiver(decoder->parent, (struct message *) msg); - resp->deleter(resp); + return TRUE; } - return ret; + return FALSE; } /** * Checks if network format has changed. @@ -1485,11 +1485,40 @@ int decode_video_frame(struct coded_data *cdata, void *decoder_data) int k = 0, m = 0, c = 0, seed = 0; // LDGM int buffer_number, buffer_length; + // check if we are not in the middle of reconfiguration + if (decoder->reconfiguration_in_progress) { +#if defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 6 + bool status = +#else + std::future_status status = +#endif + decoder->reconfiguration_future.wait_until(std::chrono::system_clock::now()); +#if defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ == 6 + if (status) { +#else + if (status == std::future_status::ready) { +#endif + bool ret = decoder->reconfiguration_future.get(); + if (ret) { + decoder->frame = display_get_frame(decoder->display); + } else { + fprintf(stderr, "Decoder reconfiguration failed!!!\n"); + decoder->frame = NULL; + } + decoder->reconfiguration_in_progress = false; + } else { + // skip the frame if we are not yet reconfigured + return FALSE; + } + } + main_msg *msg; while ((msg = dynamic_cast(decoder->msg_queue.pop(true /* nonblock */)))) { if (dynamic_cast(msg)) { main_msg_reconfigure *msg_reconf = dynamic_cast(msg); - reconfigure_if_needed(decoder, msg_reconf->desc); + if (reconfigure_if_needed(decoder, msg_reconf->desc)) { + return FALSE; + } } delete msg; } @@ -1558,7 +1587,7 @@ int decode_video_frame(struct coded_data *cdata, void *decoder_data) goto cleanup; } - if(substream >= max_substreams) { + if ((int) substream >= max_substreams) { fprintf(stderr, "[decoder] received substream ID %d. Expecting at most %d substreams. Did you set -M option?\n", substream, max_substreams); // the guess is valid - we start with highest substream number (anytime - since it holds a m-bit) @@ -1607,7 +1636,9 @@ int decode_video_frame(struct coded_data *cdata, void *decoder_data) /* Critical section * each thread *MUST* wait here if this condition is true */ - check_for_mode_change(decoder, hdr); + if (check_for_mode_change(decoder, hdr)) { + return FALSE; + } // hereafter, display framebuffer can be used, so we // check if we got it