X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=nageru%2Fffmpeg_capture.cpp;h=79fba7b9ab4ebf4135e8e9f34c145e78a676e7b4;hb=685a74b4a2e928670eb5fb53919bbcffca45c8e3;hp=e099d18a34a5073ba1f8bc1b07158d40f778f720;hpb=ef52ac608e069f76af5e56de585833e8efa93168;p=nageru diff --git a/nageru/ffmpeg_capture.cpp b/nageru/ffmpeg_capture.cpp index e099d18..79fba7b 100644 --- a/nageru/ffmpeg_capture.cpp +++ b/nageru/ffmpeg_capture.cpp @@ -44,8 +44,6 @@ extern "C" { #include #endif -#define FRAME_SIZE (8 << 20) // 8 MB. - using namespace std; using namespace std::chrono; using namespace bmusb; @@ -125,8 +123,8 @@ AVPixelFormat decide_dst_format(AVPixelFormat src_format, bmusb::PixelFormat dst if (desc->comp[0].depth != 8) continue; // Same or better chroma resolution only. - int chroma_w_diff = desc->log2_chroma_w - src_desc->log2_chroma_w; - int chroma_h_diff = desc->log2_chroma_h - src_desc->log2_chroma_h; + int chroma_w_diff = src_desc->log2_chroma_w - desc->log2_chroma_w; + int chroma_h_diff = src_desc->log2_chroma_h - desc->log2_chroma_h; if (chroma_w_diff < 0 || chroma_h_diff < 0) continue; @@ -503,7 +501,15 @@ AVPixelFormat get_hw_format(AVCodecContext *ctx, const AVPixelFormat *fmt) fprintf(stderr, "Decoder '%s' does not support device type '%s'.\n", ctx->codec->name, av_hwdevice_get_type_name(type)); } - // We found no VA-API formats, so take the best software format. + // We found no VA-API formats, so take the first software format. + for (const AVPixelFormat *fmt_ptr = fmt; *fmt_ptr != -1; ++fmt_ptr) { + if ((av_pix_fmt_desc_get(*fmt_ptr)->flags & AV_PIX_FMT_FLAG_HWACCEL) == 0) { + fprintf(stderr, "Falling back to software format %s.\n", av_get_pix_fmt_name(*fmt_ptr)); + return *fmt_ptr; + } + } + + // Fallback: Just return anything. (Should never really happen.) return fmt[0]; } @@ -651,7 +657,7 @@ bool FFmpegCapture::play_video(const string &pathname) pathname, video_stream_index, audio_stream_index, subtitle_stream_index, audio_frame.get(), &audio_format, &audio_pts, &error); if (error) { if (++consecutive_errors >= 100) { - fprintf(stderr, "More than 100 consecutive video frames, aborting playback.\n"); + fprintf(stderr, "More than 100 consecutive error video frames, aborting playback.\n"); return false; } else { continue; @@ -1138,6 +1144,16 @@ UniqueFrame FFmpegCapture::make_video_frame(const AVFrame *frame, const string & current_frame_ycbcr_format = decode_ycbcr_format(desc, frame, is_mjpeg, &last_colorspace, &last_chroma_location); } + + // 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); + *error = true; + return video_frame; + } + sws_scale(sws_ctx.get(), frame->data, frame->linesize, 0, frame->height, pic_data, linesizes); return video_frame;