Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
(연관된 글이 1개 있습니다.)
(시리즈 글이 10개 있습니다.)
VC++: 121. DXGI를 이용한 윈도우 화면 캡처 소스 코드(Visual C++)
; https://www.sysnet.pe.kr/2/0/11385

.NET Framework: 705. C# - SharpDX + DXGI를 이용한 윈도우 화면 캡처 소스 코드
; https://www.sysnet.pe.kr/2/0/11400

.NET Framework: 706. C# - SharpDX + DXGI를 이용한 윈도우 화면 캡처 소스 코드 + Direct2D 출력
; https://www.sysnet.pe.kr/2/0/11401

.NET Framework: 712. C# - SharpDX + DXGI를 이용한 윈도우 화면 캡처 소스 코드 + Direct2D 출력 + OpenCV
; https://www.sysnet.pe.kr/2/0/11407

.NET Framework: 713. C# - SharpDX + DXGI를 이용한 윈도우 화면 캡처 소스 코드 + Direct2D 출력 + OpenCV (2)
; https://www.sysnet.pe.kr/2/0/11408

.NET Framework: 913. C# - SharpDX + DXGI를 이용한 윈도우 화면 캡처 라이브러리
; https://www.sysnet.pe.kr/2/0/12238

.NET Framework: 1123. C# - (SharpDX + DXGI) 화면 캡처한 이미지를 빠르게 JPG로 변환하는 방법
; https://www.sysnet.pe.kr/2/0/12889

.NET Framework: 1126. C# - snagit처럼 화면 캡처를 연속으로 수행해 동영상 제작
; https://www.sysnet.pe.kr/2/0/12895

.NET Framework: 1128. C# - 화면 캡처한 이미지를 ffmpeg(FFmpeg.AutoGen)로 동영상 처리
; https://www.sysnet.pe.kr/2/0/12897

.NET Framework: 1152. C# - 화면 캡처한 이미지를 ffmpeg(FFmpeg.AutoGen)로 동영상 처리 (저해상도 현상 해결)
; https://www.sysnet.pe.kr/2/0/12963




C# - 화면 캡처한 이미지를 ffmpeg(FFmpeg.AutoGen)로 동영상 처리

지난 글에서는,

C# - snagit처럼 화면 캡처를 연속으로 수행해 동영상 제작
; https://www.sysnet.pe.kr/2/0/12895

동영상 처리를 OpenCvSharp.VideoWriter를 이용해 처리했는데요, 그 부분만 ffmpeg로 바꿔볼까요? ^^

자, 그럼 일단 지난 예제 코드 파일의 프로젝트를 로드하고 FFmpeg.AutoGen 패키지를 참조 추가한 후,

// Install-Package FFmpeg.AutoGen -Version 4.4.1.1

Install-Package FFmpeg.AutoGen

네이티브 DLL을 "FFmpeg" 디렉터리를 만들어 /bin/x64 디렉터리에 복사한 후 "Copy if newer" 빌드 설정을 합니다. 그다음, ffmpeg.RootPath를 /FFmpeg/bin/x64로 설정하면 이제 다음의 코드를 넣어 잘 동작할 수 있는 환경이 완료됩니다.

public Form1()
{
    // ...[생략]...

    FFmpegBinariesHelper.RegisterFFmpegBinaries();
}

이제부터는, 실제적인 ffmpeg 관련 코딩을 해야 하는데요, 바닥부터 하기보다는 FFmpeg.AutoGen의 예제에서 제공하던 H264VideoStreamEncoder.cs 파일을 그대로 복사해, 기존의 VideoWriter를 사용했던 코드를 최대한 그대로 재사용하기 위해 FFmpegVideoWriter를 만들어 H264VideoStreamEncoder에 연결하는 코드를 다음과 같이 작성했습니다.

public class FFmpegVideoWriter : IDisposable
{
    double _fps;
    public double Fps => _fps;

    OpenCvSharp.Size _frameSize;
    public OpenCvSharp.Size FrameSize => _frameSize;

    FileStream _outputStream;
    H264VideoStreamEncoder _streamEncoder;
    VideoFrameConverter _vfc;

    int _frameNumber = 0;

    public FFmpegVideoWriter(string filePath, FourCC type, double fps,
            OpenCvSharp.Size frameSize, bool color)
    {
        _frameSize = frameSize;
        _fps = fps;

        System.Drawing.Size imageSize = new System.Drawing.Size(frameSize.Width, frameSize.Height);
        AVPixelFormat sourcePixelFormat = AVPixelFormat.AV_PIX_FMT_BGR24;
        AVPixelFormat destinationPixelFormat = AVPixelFormat.AV_PIX_FMT_YUV420P;

        _outputStream = File.Open(filePath, FileMode.Create);
        _streamEncoder = new H264VideoStreamEncoder(_outputStream, AVCodecID.AV_CODEC_ID_H264, destinationPixelFormat, (int)fps, imageSize);

        _vfc = new VideoFrameConverter(imageSize, sourcePixelFormat, imageSize, destinationPixelFormat);
    }

    public unsafe void Write(Mat matFrame)
    {
        // ...[생략]...
    }

    public void Dispose()
    {
        _streamEncoder.Dispose();
        _outputStream.Dispose();
        _vfc.Dispose();
    }
}

이렇게 바꾸고 실행했더니, 일단 동작은 잘 하는데 AV_PIX_FMT_BGR24 포맷에서 AV_PIX_FMT_YUV420P 포맷으로 바뀌는 과정에 꽤나 데이터 손실이 발생해 이미지가 많이 뭉개집니다. (대신, 출력 파일의 크기는 예전에 비해 확실히 용량이 작아집니다.)

(2022-02-11 업데이트: bit_rate의 값을 높였더니 이미지가 뭉개지는 현상은 없어졌습니다.)





그나저나, ffmpeg에 대해 거의 모르니 저 데이터 손실을 없앨 방법을 모르겠군요. ^^; "AVPixelFormat destinationPixelFormat = AVPixelFormat.AV_PIX_FMT_YUV420P"의 값을 AV_PIX_FMT_YUYV422로 바꿨더니 "ffmpeg.avcodec_open2(_pCodecContext, _pCodec, null).ThrowExceptionIfError();" 호출에서 "System.ApplicationException: 'Invalid argument'" 오류가 발생합니다.

H264 코덱이 좀 더 해상도가 높은 인코딩 방식을 지원하지 않는다는 것은 말이 안 되는 듯한데... 아마도 제가 모르는 다른 인자가 있겠지요. ^^ (혹시 이에 대해서 아시는 분은 덧글 부탁드립니다.)

암튼, 기초는 끝냈으니... 조금씩 예제 코드를 확장해 보겠습니다. ^^

(첨부 파일은 이 글의 예제 코드를 포함합니다. 단지, 압축 파일 크기를 줄이기 위해 ./FFmpeg/bin/x64 하위의 DLL은 제거했습니다.)




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 2/11/2022]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2022-01-03 10시54분
[이승준] AV_PIX_FMT_YUYV422 이것의 변경에서 에러가 나는것은 두가지 경우를 생각해 볼 수 있습니다.

1. 인코더가 해당 컬러포맷을 지원하지 않는 경우.
2. 컬러포맷 컨버터를 지원하지 않도록 만든 경우.

1번의 경우는 인코더마다 지원하는 컬러포맷이 다릅니다.
문제는 위의 코드로는 어떤 코덱이 선택되었는지 조차도 알수가 없고,
에러처리를 코덱 선택 부분에서 실제 지원 컬러포맷을 확인해서 처리했는지?
아니면 그냥 범용적으로 사용되는 컬러포맷이 아닐 경우 전부 오류 처리를 했는지 알수가 없다는거죠.

2번의 경우는 가능성이 거의 없습니다.
ffmpeg 포맷 컨버터는 특수한 컬러포맷이 아니면 거의 변환을 합니다.
당연히 YUYV422은 문제가 없죠.
[guest]
2022-01-03 11시03분
@이승준 덧글 감사합니다. 1번의 경우를 언급하면서 본문의 코드에서 어떤 코덱이 선택되었는지 알 수가 없다고 했는데, 그렇다면 "AVCodecID.AV_CODEC_ID_H264"라는 식별자도 H264를 지원하는 것들의 다양한 코덱 종류에 대한 대표값에 불과하다는 거죠?
정성태
2022-01-03 12시54분
[이승준] 정성태님 맞습니다.
다만 보통 기본 인코더가 선택이 되는데. 이게 라이브러리 빌드에 따라서 달라집니다.
ffmpeg.org에서 다운로드 받는것 중 gpl3기준일 경우 libx264가 올라오고요.
lgpl일 경우 아주 기본적인 소프트웨어 인코더가 올라오거나 아니면 gpu에 따라 gpu인코더가 올라오기도 합니다.
vcpkg 로 직접 빌드할 경우에는 딱 기본적인 라이브러리만 추가되서 빌드될겁니다.

https://github.com/m-ab-s/media-autobuild_suite
요건 윈도우즈에서 최신버전의 ffmpeg을 본인 입맛대로 빌드할 수 있는 스크립트가 제공되는 깃허브 입니다.
단점은 간헐적으로 버그가 발생하면 빌드가 안되는 경우도 있습니다. 그리고 ffmpeg을 그때그때 다운로드 받기 때문에 소스 수정은 불가능 합니다.
스크립트 자체를 수정하면 물론 가능하고요.
[guest]
2022-01-03 01시48분
@이승준 답변 정말 감사드립니다. ^^ 생각했던 것보다 이쪽 분야가 엄청 복잡다단하군요. ^^; 말씀해 주신 링크도 참고해서 다양한 빌드 버전을 얻어 테스트를 좀 더 해보겠습니다. (알려주시지 않았다면 그런게 있었는지 평생 몰랐을 듯싶군요. ^^)
정성태

... 181  182  183  [184]  185  186  187  188  189  190  191  192  193  194  195  ...
NoWriterDateCnt.TitleFile(s)
410정성태12/16/200621987오류 유형: 20. TFS SP1 설치 관련 오류 (1) - KB919156 패치
408정성태12/10/200624321Windows: 7. USB 드라이브 내용 암호화
407정성태12/10/200621723오류 유형: 19. Vista 에서의 VS.NET 2005 로 개발한 어셈블리에 대한 서명 확인 오류
406정성태12/10/200626561Windows: 6. IE 7 검색 공급자 - 영한 사전
403정성태12/6/200633716Windows: 5. Vista 와 웹 인증 등록 서비스의 문제 [5]
402정성태12/11/200624700Windows: 4. Vista 설치 후기 [1]
409정성태12/11/200628696    답변글 Windows: 4.1. Vista 설치 후기 - 두 번째 이야기 [3]
396정성태2/13/200731242오류 유형: 18. "Automatic Updates" 서비스 CPU 100% 점유 현상
393정성태11/8/200620846오류 유형: 17. Unable to start debugging - The binding handle is invalid.
371정성태10/23/200620109오류 유형: 16. STS Communication failed.
370정성태11/12/200623946.NET Framework: 75. Windows CardSpace 이야기 (이 글의 내용은 재작성되어질 예정입니다.)
375정성태10/25/200625829    답변글 .NET Framework: 75.1. 개인 발행 카드에 대한 Microsoft 예제 실습(이 글의 내용은 재작성되어질 예정입니다.)
376정성태10/27/200625546    답변글 .NET Framework: 75.2. "Windows CardSpace"와 "인증서 서비스"의 만남(이 글의 내용은 재작성되어질 예정입니다.)
377정성태10/26/200625404    답변글 .NET Framework: 75.3. Managed Card 발행에 대한 Microsoft 예제 실습 (1) - CardWriter (이 글의 내용은 재작성되어질 예정입니다.)
385정성태11/6/200627806    답변글 .NET Framework: 75.4. Managed Card 발행에 대한 Microsoft 예제 실습 (2) - STS 구현 (이 글의 내용은 재작성되어질 예정입니다.) [7]
387정성태11/2/200628655    답변글 .NET Framework: 75.5. Windows CardSpace와 SYSNET 사이트의 만남 (이 글의 내용은 재작성되어질 예정입니다.) [1]
397정성태11/11/200626229    답변글 .NET Framework: 75.6. CardWriter.csproj와 함께 알아보는 인증서 식별 방법(이 글의 내용은 재작성되어질 예정입니다.)
398정성태11/12/200624679    답변글 .NET Framework: 75.7. 카드에 암호 거는 방법(이 글의 내용은 재작성되어질 예정입니다.)
399정성태11/12/200626869    답변글 .NET Framework: 75.8. 인증서/스마트 카드에 기반한 Managed Card - STS 구현(이 글의 내용은 재작성되어질 예정입니다.) [5]
369정성태10/22/200622299오류 유형: 15. 자동 업데이트 실패
367정성태10/22/200638197Windows: 3. IIS 7.0 다중 바인딩 설정하는 방법 [1]
365정성태10/21/200621634Windows: 2. 서버(build 5600)에 IIS 7.0 서비스와 .NET 3.0 설치 방법
359정성태10/17/200617860오류 유형: 14. VS.NET 빌드 오류 - FxCopCmd.exe returned error code 65.
358정성태10/17/200623155오류 유형: 13. WSE 3.0 서비스 관련 WSE101 오류 / Destination Unreachable
357정성태12/1/200625405.NET Framework: 74. WCF 이야기 [4]
378정성태10/28/200630270    답변글 .NET Framework: 74.1. WCF와 WSE 3.0의 활용 [4]파일 다운로드1
... 181  182  183  [184]  185  186  187  188  189  190  191  192  193  194  195  ...