X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=nageru%2Fffmpeg_capture.cpp;h=6dbcbd602b79b544c8319ddd9446b9992c66ef10;hb=HEAD;hp=1a9a295cd28d988233821294116ebf9ff2f50abf;hpb=b22b0f8e945c5a0b9e738eb982b61aa70b88ed1d;p=nageru diff --git a/nageru/ffmpeg_capture.cpp b/nageru/ffmpeg_capture.cpp index 1a9a295..14ad91f 100644 --- a/nageru/ffmpeg_capture.cpp +++ b/nageru/ffmpeg_capture.cpp @@ -1,24 +1,49 @@ #include "ffmpeg_capture.h" +#include "defs.h" +#include "shared/shared_defs.h" #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include #include #include #include #include +#include #include -#include +#include +#include extern "C" { #include +#include +#include +#include #include #include +#include +#include +#include +#include #include #include -#include -#include +#include +#include +#include #include -#include +#include +#include +#include +#include #include } @@ -33,6 +58,7 @@ extern "C" { #include #include "bmusb/bmusb.h" +#include "shared/context.h" #include "shared/ffmpeg_raii.h" #include "ffmpeg_util.h" #include "flags.h" @@ -260,8 +286,8 @@ RGBTriplet get_neutral_color(AVDictionary *metadata) } // namespace -FFmpegCapture::FFmpegCapture(const string &filename, unsigned width, unsigned height) - : filename(filename), width(width), height(height), video_timebase{1, 1} +FFmpegCapture::FFmpegCapture(const string &filename, unsigned width, unsigned height, QSurface *surface) + : filename(filename), width(width), height(height), video_timebase{1, 1}, surface(surface) { description = "Video: " + filename; @@ -271,12 +297,13 @@ FFmpegCapture::FFmpegCapture(const string &filename, unsigned width, unsigned he } #ifdef HAVE_SRT -FFmpegCapture::FFmpegCapture(int srt_sock, const string &stream_id) +FFmpegCapture::FFmpegCapture(int srt_sock, const string &stream_id, QSurface *surface) : srt_sock(srt_sock), width(0), // Don't resize; SRT streams typically have stable resolution, and should behave much like regular cards in general. height(0), pixel_format(bmusb::PixelFormat_8BitYCbCrPlanar), - video_timebase{1, 1} + video_timebase{1, 1}, + surface(surface) { if (stream_id.empty()) { description = "SRT stream"; @@ -300,6 +327,7 @@ FFmpegCapture::~FFmpegCapture() srt_close(srt_sock); } #endif + delete surface; } void FFmpegCapture::configure_card() @@ -360,6 +388,21 @@ void FFmpegCapture::producer_thread_func() snprintf(thread_name, sizeof(thread_name), "FFmpeg_C_%d", card_index); pthread_setname_np(pthread_self(), thread_name); + // We need a context in case create_frame() needs to reallocate something. + // (If none is given, we are probably in Kaeru, which uses MallocFrameAllocator + // anyway, which doesn't reallocate currently and definitely doesn't need + // an active OpenGL context to do so.) + QOpenGLContext *context = nullptr; + if (surface != nullptr) { + context = create_context(this->surface); + eglBindAPI(EGL_OPENGL_API); + if (!make_current(context, this->surface)) { + printf("display=%p surface=%p context=%p curr=%p err=%d\n", eglGetCurrentDisplay(), this->surface, context, eglGetCurrentContext(), + eglGetError()); + abort(); + } + } + while (!producer_thread_should_quit.should_quit()) { string filename_copy; { @@ -403,9 +446,11 @@ void FFmpegCapture::producer_thread_func() } if (has_dequeue_callbacks) { - dequeue_cleanup_callback(); + dequeue_cleanup_callback(); has_dequeue_callbacks = false; - } + } + + delete_context(context); } void FFmpegCapture::send_disconnected_frame() @@ -1071,9 +1116,9 @@ void FFmpegCapture::convert_audio(const AVFrame *audio_avframe, FrameAllocator:: int out_samples = swr_convert(resampler, &data, num_samples_room, const_cast(audio_avframe->data), audio_avframe->nb_samples); if (out_samples < 0) { - fprintf(stderr, "Audio conversion failed.\n"); - abort(); - } + fprintf(stderr, "Audio conversion failed.\n"); + abort(); + } audio_frame->len += out_samples * bytes_per_sample; } @@ -1102,7 +1147,7 @@ UniqueFrame FFmpegCapture::make_video_frame(const AVFrame *frame, const string & { *error = false; - UniqueFrame video_frame(video_frame_allocator->alloc_frame()); + UniqueFrame video_frame(video_frame_allocator->create_frame(frame->width, frame->height, frame->width)); if (video_frame->data == nullptr) { return video_frame; } @@ -1167,8 +1212,8 @@ UniqueFrame FFmpegCapture::make_video_frame(const AVFrame *frame, const string & // FIXME: Currently, if the video is too high-res for one of the allocated // frames, we simply refuse to scale it here to avoid crashes. It would be better // if we could somehow signal getting larger frames, especially as 4K is a thing now. - if (video_frame->len > FRAME_SIZE) { - fprintf(stderr, "%s: Decoded frame would be larger than supported FRAME_SIZE (%zu > %u), not decoding.\n", pathname.c_str(), video_frame->len, FRAME_SIZE); + if (video_frame->len > video_frame->size) { + fprintf(stderr, "%s: Decoded frame would be larger than supported frame size (%zu > %zu), not decoding.\n", pathname.c_str(), video_frame->len, video_frame->size); *error = true; return video_frame; }