]> git.sesse.net Git - nageru/blobdiff - nageru/ffmpeg_capture.cpp
Fix a warning wording in FFmpegCapture.
[nageru] / nageru / ffmpeg_capture.cpp
index 863f4fba4feaecc40b14d07b4662a04740c1894c..79fba7b9ab4ebf4135e8e9f34c145e78a676e7b4 100644 (file)
@@ -44,8 +44,6 @@ extern "C" {
 #include <srt/srt.h>
 #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;
 
@@ -479,6 +477,11 @@ AVPixelFormat get_hw_format(AVCodecContext *ctx, const AVPixelFormat *fmt)
                        if (config->pix_fmt == *fmt_ptr) {
                                fprintf(stderr, "Initialized '%s' hardware decoding for codec '%s'.\n",
                                        av_hwdevice_get_type_name(type), ctx->codec->name);
+                               if (ctx->profile == FF_PROFILE_H264_BASELINE) {
+                                       fprintf(stderr, "WARNING: Stream claims to be H.264 Baseline, which is generally poorly supported in hardware decoders.\n");
+                                       fprintf(stderr, "         Consider encoding it as Constrained Baseline, Main or High instead.\n");
+                                       fprintf(stderr, "         Decoding might fail and fall back to software.\n");
+                               }
                                return config->pix_fmt;
                        }
                }
@@ -498,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];
 }
 
@@ -646,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;
@@ -1133,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;