X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=nageru%2Fmixer.cpp;h=c25b22dc711fa528c2720493504f9bebcfe12f3b;hb=647810a468e01fab5d7f0fcd122565ab000a2e73;hp=2f6a8ebafc1018ddbc90ce7db9368b5594070f15;hpb=131a051c4cd3719a9be415386fdf0f4e15da7c66;p=nageru diff --git a/nageru/mixer.cpp b/nageru/mixer.cpp index 2f6a8eb..c25b22d 100644 --- a/nageru/mixer.cpp +++ b/nageru/mixer.cpp @@ -37,21 +37,23 @@ #include "cef_capture.h" #endif #include "chroma_subsampler.h" -#include "context.h" +#include "shared/context.h" #include "decklink_capture.h" #include "decklink_output.h" #include "defs.h" -#include "disk_space_estimator.h" +#include "shared/disk_space_estimator.h" #include "ffmpeg_capture.h" #include "flags.h" #include "input_mapping.h" #include "shared/metrics.h" +#include "mjpeg_encoder.h" #include "pbo_frame_allocator.h" #include "shared/ref_counted_gl_sync.h" #include "resampling_queue.h" #include "shared/timebase.h" #include "timecode_renderer.h" #include "v210_converter.h" +#include "va_display_with_cleanup.h" #include "video_encoder.h" #undef Status @@ -356,6 +358,9 @@ Mixer::Mixer(const QSurfaceFormat &format, unsigned num_cards) display_chain->finalize(); video_encoder.reset(new VideoEncoder(resource_pool.get(), h264_encoder_surface, global_flags.va_display, global_flags.width, global_flags.height, &httpd, global_disk_space_estimator)); + if (!global_flags.card_to_mjpeg_stream_export.empty()) { + mjpeg_encoder.reset(new MJPEGEncoder(&httpd, global_flags.va_display)); + } // Must be instantiated after VideoEncoder has initialized global_flags.use_zerocopy. theme.reset(new Theme(global_flags.theme_filename, global_flags.theme_dirs, resource_pool.get(), num_cards)); @@ -499,6 +504,9 @@ Mixer::Mixer(const QSurfaceFormat &format, unsigned num_cards) Mixer::~Mixer() { + if (mjpeg_encoder != nullptr) { + mjpeg_encoder->stop(); + } httpd.stop(); BMUSBCapture::stop_bm_thread(); @@ -790,7 +798,7 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode, size_t cbcr_width, cbcr_height, cbcr_offset, y_offset; size_t expected_length = video_format.stride * (video_format.height + video_format.extra_lines_top + video_format.extra_lines_bottom); - if (userdata != nullptr && userdata->pixel_format == PixelFormat_8BitYCbCrPlanar) { + if (userdata->pixel_format == PixelFormat_8BitYCbCrPlanar) { // The calculation above is wrong for planar Y'CbCr, so just override it. assert(card->type == CardType::FFMPEG_INPUT); assert(video_offset == 0); @@ -954,6 +962,9 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode, new_frame.upload_func = upload_func; new_frame.dropped_frames = dropped_frames; new_frame.received_timestamp = video_frame.received_timestamp; // Ignore the audio timestamp. + new_frame.video_format = video_format; + new_frame.y_offset = y_offset; + new_frame.cbcr_offset = cbcr_offset; card->new_frames.push_back(move(new_frame)); card->jitter_history.frame_arrived(video_frame.received_timestamp, frame_length, dropped_frames); card->may_have_dropped_last_frame = false; @@ -1063,6 +1074,15 @@ void Mixer::thread_func() new_frame->upload_func(); new_frame->upload_func = nullptr; } + + // Only bother doing MJPEG encoding if there are any connected clients + // that want the stream. + if (httpd.get_num_connected_multicam_clients() > 0) { + auto stream_it = global_flags.card_to_mjpeg_stream_export.find(card_index); + if (stream_it != global_flags.card_to_mjpeg_stream_export.end()) { + mjpeg_encoder->upload_frame(pts_int, stream_it->second, new_frame->frame, new_frame->video_format, new_frame->y_offset, new_frame->cbcr_offset); + } + } } int64_t frame_duration = output_frame_info.frame_duration;