예제 #1
0
        private FFmpegFrame ensureFramePixelFormat(FFmpegFrame frame, AVPixelFormat targetPixelFormat)
        {
            if (frame.PixelFormat == targetPixelFormat)
            {
                return(frame);
            }

            int width  = frame.Pointer->width;
            int height = frame.Pointer->height;

            swsContext = ffmpeg.sws_getCachedContext(
                swsContext,
                width, height, frame.PixelFormat,
                width, height, targetPixelFormat,
                1, null, null, null);

            if (!scalerFrames.TryDequeue(out var scalerFrame))
            {
                scalerFrame = new FFmpegFrame(ffmpeg, returnScalerFrame);
            }

            // (re)initialize the scaler frame if needed.
            if (scalerFrame.PixelFormat != targetPixelFormat || scalerFrame.Pointer->width != width || scalerFrame.Pointer->height != height)
            {
                ffmpeg.av_frame_unref(scalerFrame.Pointer);

                // Note: this field determines the scaler's output pix format.
                scalerFrame.PixelFormat     = targetPixelFormat;
                scalerFrame.Pointer->width  = width;
                scalerFrame.Pointer->height = height;

                int getBufferResult = ffmpeg.av_frame_get_buffer(scalerFrame.Pointer, 0);

                if (getBufferResult < 0)
                {
                    Logger.Log($"Failed to allocate SWS frame buffer: {getErrorMessage(getBufferResult)}");

                    scalerFrame.Dispose();
                    frame.Return();
                    return(null);
                }
            }

            int scalerResult = ffmpeg.sws_scale(
                swsContext,
                frame.Pointer->data, frame.Pointer->linesize, 0, height,
                scalerFrame.Pointer->data, scalerFrame.Pointer->linesize);

            // return the original frame regardless of the scaler result.
            frame.Return();

            if (scalerResult < 0)
            {
                Logger.Log($"Failed to scale frame: {getErrorMessage(scalerResult)}");

                scalerFrame.Dispose();
                return(null);
            }

            return(scalerFrame);
        }