]> git.sesse.net Git - nageru/commitdiff
Suppress repeated chroma location warnings from FFmpeg.
authorSteinar H. Gunderson <steinar+nageru@gunderson.no>
Mon, 1 Jun 2020 08:25:52 +0000 (10:25 +0200)
committerSteinar H. Gunderson <steinar+nageru@gunderson.no>
Mon, 1 Jun 2020 08:25:52 +0000 (10:25 +0200)
It's no good getting one of these for every frame. This works around
an FFmpeg bug where HEVC doesn't get the right chroma location set.

nageru/ffmpeg_capture.cpp
nageru/ffmpeg_capture.h

index 87d1c007e9142a07e21b2c49820c706709b45c26..c6824069aedc8786954531e3fb1f8f62deb52391 100644 (file)
@@ -143,7 +143,7 @@ AVPixelFormat decide_dst_format(AVPixelFormat src_format, bmusb::PixelFormat dst
        return av_get_pix_fmt(best_format);
 }
 
-YCbCrFormat decode_ycbcr_format(const AVPixFmtDescriptor *desc, const AVFrame *frame, bool is_mjpeg)
+YCbCrFormat decode_ycbcr_format(const AVPixFmtDescriptor *desc, const AVFrame *frame, bool is_mjpeg, AVColorSpace *last_colorspace, AVChromaLocation *last_chroma_location)
 {
        YCbCrFormat format;
        AVColorSpace colorspace = frame->colorspace;
@@ -163,11 +163,14 @@ YCbCrFormat decode_ycbcr_format(const AVPixFmtDescriptor *desc, const AVFrame *f
                format.luma_coefficients = (frame->height >= 720 ? YCBCR_REC_709 : YCBCR_REC_601);
                break;
        default:
-               fprintf(stderr, "Unknown Y'CbCr coefficient enum %d from FFmpeg; choosing Rec. 709.\n",
-                       colorspace);
+               if (colorspace != *last_colorspace) {
+                       fprintf(stderr, "Unknown Y'CbCr coefficient enum %d from FFmpeg; choosing Rec. 709.\n",
+                               colorspace);
+               }
                format.luma_coefficients = YCBCR_REC_709;
                break;
        }
+       *last_colorspace = colorspace;
 
        format.full_range = is_full_range(desc);
        format.num_levels = 1 << desc->comp[0].depth;
@@ -200,12 +203,15 @@ YCbCrFormat decode_ycbcr_format(const AVPixFmtDescriptor *desc, const AVFrame *f
                format.cb_y_position = 1.0;
                break;
        default:
-               fprintf(stderr, "Unknown chroma location coefficient enum %d from FFmpeg; choosing center.\n",
-                       frame->chroma_location);
+               if (frame->chroma_location != *last_chroma_location) {
+                       fprintf(stderr, "Unknown chroma location coefficient enum %d from FFmpeg; choosing center.\n",
+                               frame->chroma_location);
+               }
                format.cb_x_position = 0.5;
                format.cb_y_position = 0.5;
                break;
        }
+       *last_chroma_location = frame->chroma_location;
 
        if (is_mjpeg && !format.full_range) {
                // Limited-range MJPEG is only detected by FFmpeg whenever a special
@@ -459,6 +465,8 @@ bool FFmpegCapture::play_video(const string &pathname)
        } else {
                last_modified = buf.st_mtim;
        }
+       last_colorspace = static_cast<AVColorSpace>(-1);
+       last_chroma_location = static_cast<AVChromaLocation>(-1);
 
        AVFormatContextWithCloser format_ctx;
        if (srt_sock == -1) {
@@ -1002,7 +1010,7 @@ UniqueFrame FFmpegCapture::make_video_frame(const AVFrame *frame, const string &
                video_frame->len = (frame_width(frame) * 2) * frame_height(frame);
 
                const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(sws_dst_format);
-               current_frame_ycbcr_format = decode_ycbcr_format(desc, frame, is_mjpeg);
+               current_frame_ycbcr_format = decode_ycbcr_format(desc, frame, is_mjpeg, &last_colorspace, &last_chroma_location);
        } else {
                assert(pixel_format == bmusb::PixelFormat_8BitYCbCrPlanar);
                const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(sws_dst_format);
@@ -1021,7 +1029,7 @@ UniqueFrame FFmpegCapture::make_video_frame(const AVFrame *frame, const string &
 
                video_frame->len = frame_width(frame) * frame_height(frame) + 2 * chroma_width * chroma_height;
 
-               current_frame_ycbcr_format = decode_ycbcr_format(desc, frame, is_mjpeg);
+               current_frame_ycbcr_format = decode_ycbcr_format(desc, frame, is_mjpeg, &last_colorspace, &last_chroma_location);
        }
        sws_scale(sws_ctx.get(), frame->data, frame->linesize, 0, frame->height, pic_data, linesizes);
 
index 4cddbfddf757bce77a1f49b6c21b52bd7b57675b..1fc8f7128f516d6b4d06431b3049256f7bbdf7f7 100644 (file)
@@ -329,6 +329,11 @@ private:
        std::string last_subtitle;
 
        movit::RGBTriplet last_neutral_color{1.0f, 1.0f, 1.0f};
+
+       // Used for suppressing repeated warnings. Reset when a video starts playing.
+       // -1 is strictly speaking outside the range of the enum, but hopefully, it will be alright.
+       AVColorSpace last_colorspace = static_cast<AVColorSpace>(-1);
+       AVChromaLocation last_chroma_location = static_cast<AVChromaLocation>(-1);
 };
 
 #endif  // !defined(_FFMPEG_CAPTURE_H)