Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일

(시리즈 글이 24개 있습니다.)
.NET Framework: 1129. C# - ffmpeg(FFmpeg.AutoGen)를 이용한 비디오 인코딩 예제(encode_video.c)
; https://www.sysnet.pe.kr/2/0/12898

.NET Framework: 1134. C# - ffmpeg(FFmpeg.AutoGen)를 이용한 비디오 디코딩 예제(decode_video.c)
; https://www.sysnet.pe.kr/2/0/12924

.NET Framework: 1135. C# - ffmpeg(FFmpeg.AutoGen)로 하드웨어 가속기를 이용한 비디오 디코딩 예제(hw_decode.c)
; https://www.sysnet.pe.kr/2/0/12932

.NET Framework: 1136. C# - ffmpeg(FFmpeg.AutoGen)를 이용해 MP2 오디오 파일 디코딩 예제(decode_audio.c)
; https://www.sysnet.pe.kr/2/0/12933

.NET Framework: 1137. ffmpeg의 파일 해시 예제(ffhash.c)를 C#으로 포팅
; https://www.sysnet.pe.kr/2/0/12935

.NET Framework: 1138. C# - ffmpeg(FFmpeg.AutoGen)를 이용해 멀티미디어 파일의 메타데이터를 보여주는 예제(metadata.c)
; https://www.sysnet.pe.kr/2/0/12936

.NET Framework: 1139. C# - ffmpeg(FFmpeg.AutoGen)를 이용해 오디오(mp2) 인코딩하는 예제(encode_audio.c)
; https://www.sysnet.pe.kr/2/0/12937

.NET Framework: 1147. C# - ffmpeg(FFmpeg.AutoGen)를 이용한 오디오 필터링 예제(filtering_audio.c)
; https://www.sysnet.pe.kr/2/0/12951

.NET Framework: 1148. C# - ffmpeg(FFmpeg.AutoGen)를 이용한 오디오 필터 예제(filter_audio.c)
; https://www.sysnet.pe.kr/2/0/12952

.NET Framework: 1150. C# - ffmpeg(FFmpeg.AutoGen)를 이용한 비디오 디코딩 예제(decode_video.c) - 두 번째 이야기
; https://www.sysnet.pe.kr/2/0/12959

개발 환경 구성: 637. ffmpeg(FFmpeg.AutoGen)를 이용한 비디오 디코딩 예제(decode_video.c) - 세 번째 이야기
; https://www.sysnet.pe.kr/2/0/12960

.NET Framework: 1151. C# - ffmpeg(FFmpeg.AutoGen)를 이용한 비디오 프레임의 크기 및 포맷 변경 예제(scaling_video.c)
; https://www.sysnet.pe.kr/2/0/12961

.NET Framework: 1153. C# - ffmpeg(FFmpeg.AutoGen)를 이용한 avio_reading.c 예제 포팅
; https://www.sysnet.pe.kr/2/0/12964

.NET Framework: 1157. C# - ffmpeg(FFmpeg.AutoGen)를 이용한 muxing.c 예제 포팅
; https://www.sysnet.pe.kr/2/0/12971

.NET Framework: 1159. C# - ffmpeg(FFmpeg.AutoGen)를 이용한 qsvdec.c 예제 포팅
; https://www.sysnet.pe.kr/2/0/12975

.NET Framework: 1161. C# - ffmpeg(FFmpeg.AutoGen)를 이용한 resampling_audio.c 예제 포팅
; https://www.sysnet.pe.kr/2/0/12978

.NET Framework: 1166. C# - ffmpeg(FFmpeg.AutoGen)를 이용한 filtering_video.c 예제 포팅
; https://www.sysnet.pe.kr/2/0/12984

.NET Framework: 1169. C# - ffmpeg(FFmpeg.AutoGen)를 이용한 demuxing_decoding.c 예제 포팅
; https://www.sysnet.pe.kr/2/0/12987

.NET Framework: 1170. C# - ffmpeg(FFmpeg.AutoGen)를 이용한 transcode_aac.c 예제 포팅
; https://www.sysnet.pe.kr/2/0/12991

.NET Framework: 1178. C# - ffmpeg(FFmpeg.AutoGen)를 이용한 http_multiclient.c 예제 포팅
; https://www.sysnet.pe.kr/2/0/13002

.NET Framework: 1180. C# - ffmpeg(FFmpeg.AutoGen)를 이용한 remuxing.c 예제 포팅
; https://www.sysnet.pe.kr/2/0/13006

.NET Framework: 1188. C# - ffmpeg(FFmpeg.AutoGen)를 이용한 transcoding.c 예제 포팅
; https://www.sysnet.pe.kr/2/0/13023

.NET Framework: 1190. C# - ffmpeg(FFmpeg.AutoGen)를 이용한 vaapi_encode.c, vaapi_transcode.c 예제 포팅
; https://www.sysnet.pe.kr/2/0/13025

.NET Framework: 1191. C 언어로 작성된 FFmpeg Examples의 C# 포팅 전체 소스 코드
; https://www.sysnet.pe.kr/2/0/13026




C# - ffmpeg(FFmpeg.AutoGen)를 이용한 avio_reading.c 예제 포팅

지난 예제에 이어,

C# - ffmpeg(FFmpeg.AutoGen)를 이용한 비디오 프레임의 크기 및 포맷 변경 예제(scaling_video.c)
; https://www.sysnet.pe.kr/2/0/12961

이번에는 ffmpeg 예제 중 "avio_reading.c" 파일을 FFmpeg.AutoGen으로 포팅하겠습니다.

using FFmpeg.AutoGen;
using FFmpeg.AutoGen.Example;
using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography;

namespace FFmpegApp1
{
    internal unsafe class Program
    {
        [DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)]
        static extern void MoveMemory(IntPtr dest, IntPtr src, int size);

        static unsafe int Main(string[] args)
        {
            FFmpegBinariesHelper.RegisterFFmpegBinaries();

#if DEBUG
            Console.WriteLine("Current directory: " + Environment.CurrentDirectory);
            Console.WriteLine("Running in {0}-bit mode.", Environment.Is64BitProcess ? "64" : "32");
            Console.WriteLine($"FFmpeg version info: {ffmpeg.av_version_info()}");
#endif
            Console.WriteLine();

            AVFormatContext* fmt_ctx = null;
            AVIOContext* avio_ctx = null;

            byte* buffer = null;
            byte* avio_ctx_buffer = null;
            ulong buffer_size;
            ulong avio_ctx_buffer_size = 4096;
            
            int ret = 0;
            buffer_data bd = new buffer_data();

            string input_filename = @"D:\media_sample\test.mkv";
            ret = ffmpeg.av_file_map(input_filename, &buffer, &buffer_size, 0, null);
            if (ret < 0)
            {
                return ret;
            }

            bd.ptr = buffer;
            bd.size = (int)buffer_size;

            do
            {
                fmt_ctx = ffmpeg.avformat_alloc_context();
                if (fmt_ctx == null)
                {
                    ret = ffmpeg.AVERROR(ffmpeg.ENOMEM);
                    break;
                }

                avio_ctx_buffer = (byte*)ffmpeg.av_malloc(avio_ctx_buffer_size);
                if (avio_ctx_buffer == null)
                {
                    ret = ffmpeg.AVERROR(ffmpeg.ENOMEM);
                    break;
                }

                avio_ctx = ffmpeg.avio_alloc_context(avio_ctx_buffer, (int)avio_ctx_buffer_size, 0, &bd, 
                    (avio_alloc_context_read_packet_func)read_packet, null, null);
                if (avio_ctx == null)
                {
                    ret = ffmpeg.AVERROR(ffmpeg.ENOMEM);
                    break;
                }

                fmt_ctx->pb = avio_ctx;

                ret = ffmpeg.avformat_open_input(&fmt_ctx, null, null, null);
                if (ret < 0)
                {
                    Console.WriteLine("Could not open input");
                    break;
                }

                ret = ffmpeg.avformat_find_stream_info(fmt_ctx, null);
                if (ret < 0)
                {
                    Console.WriteLine("Could not find stream information");
                    break;
                }

                ffmpeg.av_dump_format(fmt_ctx, 0, input_filename, 0);

            } while (false);

            if (fmt_ctx != null)
            {
                ffmpeg.avformat_close_input(&fmt_ctx);
            }

            if (avio_ctx != null)
            {
                ffmpeg.av_freep(&avio_ctx->buffer);
                ffmpeg.avio_context_free(&avio_ctx);
            }

            ffmpeg.av_file_unmap(buffer, buffer_size);

            return ret;
        }

        static unsafe int read_packet(void *opaque, byte* buf, int buf_size)
        {
            buffer_data* bd = (buffer_data*)opaque;
            buf_size = (int)Math.Min(buf_size, bd->size);

            if (buf_size == 0)
            {
                return ffmpeg.AVERROR_EOF;
            }

            Console.WriteLine($"ptr:{new IntPtr(bd->ptr):x} size:{bd->size}");

            MoveMemory(new IntPtr(buf), new IntPtr(bd->ptr), buf_size);
            bd->ptr += buf_size;
            bd->size -= buf_size;

            return buf_size;
        }
    }

    public unsafe struct buffer_data
    {
        public byte* ptr;
        public int size;
    }
}

이런 식의 제어가 언제 필요한지는 모르겠지만, 일단 실행하면 avformat_find_stream_info 등의 함수를 실행하는 중에 read_packet 메서드가 콜백이 되어 다음과 같은 출력이 나옵니다.

ptr:1b27a880000 size:75337278
ptr:1b27a881000 size:75333182
ptr:1b27a88acff size:75292991
ptr:1b27a88bcff size:75288895
ptr:1b27a8907bb size:75269763
ptr:1b27a8917bb size:75265667

그리고 av_dump_format의 호출에 대한 출력은 예제의 특성과는 별 상관이 없습니다.

Input #0, matroska,webm, from 'D:\media_sample\test.mkv':
  Metadata:
    COMPATIBLE_BRANDS: iso6avc1mp41
    MAJOR_BRAND     : dash
    MINOR_VERSION   : 0
    ENCODER         : Lavf58.45.100
  Duration: 00:03:07.98, start: -0.007000, bitrate: N/A
  Stream #0:0: Video: h264 (High), yuv420p(tv, bt709, progressive), 1920x1080 [SAR 1:1 DAR 16:9], 29.97 fps, 29.97 tbr, 1k tbn, 59.94 tbc (default)
    Metadata:
      HANDLER_NAME    : ISO Media file produced by Google Inc.
      DURATION        : 00:03:07.954000000
  Stream #0:1(eng): Audio: opus, 48000 Hz, stereo, fltp (default)
    Metadata:
      DURATION        : 00:03:07.981000000

(첨부 파일은 이 글의 예제 코드를 포함합니다.)
(이 글의 소스 코드는 github에 올려져 있습니다.)




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







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

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

비밀번호

댓글 작성자
 




... 31  32  33  34  35  36  37  38  39  40  41  42  43  44  [45]  ...
NoWriterDateCnt.TitleFile(s)
12810정성태8/27/202115485.NET Framework: 1107. .NET Core/5+에서 동적 컴파일한 C# 코드를 (Breakpoint도 활용하며) 디버깅하는 방법 - #line 지시자파일 다운로드1
12809정성태8/26/202115445.NET Framework: 1106. .NET Core/5+에서 C# 코드를 동적으로 컴파일/사용하는 방법 [1]파일 다운로드1
12808정성태8/25/202117089오류 유형: 758. go: ...: missing go.sum entry; to add it: go mod download ...
12807정성태8/25/202117869.NET Framework: 1105. C# 10 - (9) 비동기 메서드가 사용할 AsyncMethodBuilder 선택 가능파일 다운로드1
12806정성태8/24/202114415개발 환경 구성: 601. PyCharm - 다중 프로세스 디버깅 방법
12805정성태8/24/202116124.NET Framework: 1104. C# 10 - (8) 분해 구문에서 기존 변수의 재사용 가능파일 다운로드1
12804정성태8/24/202116291.NET Framework: 1103. C# 10 - (7) Source Generator V2 APIs
12803정성태8/23/202116801개발 환경 구성: 600. pip cache 디렉터리 옮기는 방법
12802정성태8/23/202117220.NET Framework: 1102. .NET Conf Mini 21.08 - WinUI 3 따라해 보기 [1]
12801정성태8/23/202116803.NET Framework: 1101. C# 10 - (6) record class 타입의 ToString 메서드를 sealed 처리 허용파일 다운로드1
12800정성태8/22/202117184개발 환경 구성: 599. PyCharm - (반대로) 원격 프로세스가 PyCharm에 디버그 연결하는 방법
12799정성태8/22/202117464.NET Framework: 1100. C# 10 - (5) 속성 패턴의 개선파일 다운로드1
12798정성태8/21/202118814개발 환경 구성: 598. PyCharm - 원격 프로세스를 디버그하는 방법
12797정성태8/21/202116186Windows: 197. TCP의 MSS(Maximum Segment Size) 크기는 고정된 것일까요?
12796정성태8/21/202117180.NET Framework: 1099. C# 10 - (4) 상수 문자열에 포맷 식 사용 가능파일 다운로드1
12795정성태8/20/202117505.NET Framework: 1098. .NET 6에 포함된 신규 BCL API - 스레드 관련
12794정성태8/20/202116880스크립트: 23. 파이썬 - WSGI를 만족하는 최소한의 구현 코드 및 PyCharm에서의 디버깅 방법 [1]
12793정성태8/20/202117673.NET Framework: 1097. C# 10 - (3) 개선된 변수 초기화 판정파일 다운로드1
12792정성태8/19/202118771.NET Framework: 1096. C# 10 - (2) 전역 네임스페이스 선언파일 다운로드1
12791정성태8/19/202115596.NET Framework: 1095. C# COM 개체를 C++에서 사용하는 예제 [3]파일 다운로드1
12790정성태8/18/202119540.NET Framework: 1094. C# 10 - (1) 구조체를 생성하는 record struct파일 다운로드1
12789정성태8/18/202118199개발 환경 구성: 597. PyCharm - 윈도우 환경에서 WSL을 이용해 파이썬 앱 개발/디버깅하는 방법
12788정성태8/17/202115741.NET Framework: 1093. C# - 인터페이스의 메서드가 다형성을 제공할까요? (virtual일까요?)파일 다운로드1
12787정성태8/17/202116122.NET Framework: 1092. (책 내용 수정) "4.5.1.4 인터페이스"의 "인터페이스와 다형성"
12786정성태8/16/202118055.NET Framework: 1091. C# - Python range 함수 구현 (2) INumber<T>를 이용한 개선 [1]파일 다운로드1
12785정성태8/16/202116514.NET Framework: 1090. .NET 6 Preview 7에 추가된 숫자 형식에 대한 제네릭 연산 지원 [1]파일 다운로드1
... 31  32  33  34  35  36  37  38  39  40  41  42  43  44  [45]  ...