Repository: opencv/opencv
File: modules/videoio/src/cap_ffmpeg_impl.hpp (C++)

Code before:
#endif
    }
    return ret;
}

/// write a frame with FFMPEG
bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int width, int height, int type, int origin )
{
    if (!encode_video) {
        CV_Assert((type == CV_16UC1 || type == CV_8UC1) && ((width > 0 && height == 1) || (width == 1 && height > 0 && step == 1)));
        const bool set_key_frame = key_frame ? key_frame : idr_period ? frame_idx % idr_period == 0 : 1;
        bool ret = icv_av_encapsulate_video_FFMPEG(oc, video_st, context, (uint8_t*)data, width, frame_idx, pts_index, b_frame_dts_delay, set_key_frame);
        frame_idx++;
        return ret;
    }

    // check parameters and do conversions if needed
    cv::Mat inputMat(height, width, type, (void*)data, step);
    cv::Mat convertedMat;
    switch (input_pix_fmt) {
        case AV_PIX_FMT_BGR24: // expected CV_8UC3
            if (type == CV_8UC3)
                convertedMat = inputMat;
            else {
                if (type == CV_16UC1) // CV_16UC1 -> CV_8UC1
                    inputMat.convertTo(inputMat, CV_8UC1, 1.0 / 256);
                cv::cvtColor(inputMat, convertedMat, cv::COLOR_GRAY2BGR); // CV_8UC1 -> CV_8UC3
            }
            break;
        case AV_PIX_FMT_GRAY8: // expected CV_8UC1
            if (type == CV_8UC1)
                convertedMat = inputMat;
            else if (type == CV_8UC3) // CV_8UC3 -> CV_8UC1
                cv::cvtColor(inputMat, convertedMat, COLOR_BGR2GRAY);
            else // CV_16UC1 -> CV_8UC1
                inputMat.convertTo(convertedMat, CV_8UC1, 1.0 / 256);
            break;
        case AV_PIX_FMT_GRAY16LE: // expected CV_16UC1
            if (type == CV_16UC1)
                convertedMat = inputMat;
            else {
                if (type == CV_8UC3)
                    cv::cvtColor(inputMat, inputMat, COLOR_BGR2GRAY);  // CV_8UC3 -> CV_8UC1
                inputMat.convertTo(convertedMat, CV_16UC1, 256.0);  // CV_8UC1 -> CV_16UC1
            }
            break;

        default:
            CV_LOG_WARNING(NULL, "Unknown pixel format: " << av_get_pix_fmt_name(input_pix_fmt));
            CV_Assert(false);
            break;

Review comment (suggestion):
> inputMat ... inputMat

"In-place" ops should not be used in general (causes extra `.clone()` call).

Code after:
#endif
    }
    return ret;
}

/// write a frame with FFMPEG
bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int width, int height, int cn, int origin )
{
    if (!encode_video) {
        CV_Assert(cn == 1 && ((width > 0 && height == 1) || (width == 1 && height > 0 && step == 1)));
        const bool set_key_frame = key_frame ? key_frame : idr_period ? frame_idx % idr_period == 0 : 1;
        bool ret = icv_av_encapsulate_video_FFMPEG(oc, video_st, context, (uint8_t*)data, width, frame_idx, pts_index, b_frame_dts_delay, set_key_frame);
        frame_idx++;
        return ret;
    }

    // check parameters
    if (input_pix_fmt == AV_PIX_FMT_BGR24) {
        if (cn != 3) {
            CV_LOG_WARNING(NULL, "write frame skipped - expected 3 channels but got " << cn);
            return false;
        }
    }
    else if (input_pix_fmt == AV_PIX_FMT_GRAY8 || input_pix_fmt == AV_PIX_FMT_GRAY16LE) {
        if (cn != 1) {
            CV_LOG_WARNING(NULL, "write frame skipped - expected 1 channel but got " << cn);
            return false;
        }
    }
    else {
        CV_LOG_WARNING(NULL, "Input data does not match selected pixel format: "
                       << av_get_pix_fmt_name(input_pix_fmt)
                       << ", number of channels: " << cn);
        CV_Assert(false);
    }

    if( (width & -2) != frame_width || (height & -2) != frame_height || !data )
        return false;
    width = frame_width;
    height = frame_height;

    // FFmpeg contains SIMD optimizations which can sometimes read data past
    // the supplied input buffer.
    // Related info: https://trac.ffmpeg.org/ticket/6763
    // 1. To ensure that doesn't happen, we pad the step to a multiple of 32
    // (that's the minimal alignment for which Valgrind doesn't raise any warnings).
    // 2. (dataend - SIMD_SIZE) and (dataend + SIMD_SIZE) is from the same 4k page
    const int CV_STEP_ALIGNMENT = 32;
    const size_t CV_SIMD_SIZE = 32;
    const size_t CV_PAGE_MASK = ~(size_t)(4096 - 1);
    const unsigned char* dataend = data + ((size_t)height * step);