성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] 그냥 RSS Reader 기능과 약간의 UI 편의성 때문에 사용...
[이종효] 오래된 소프트웨어는 보안 위협이 되기도 합니다. 혹시 어떤 기능...
[정성태] @Keystroke IEEE의 문서를 소개해 주시다니... +_...
[손민수 (Keystroke)] 괜히 듀얼채널 구성할 때 한번에 같은 제품 사라고 하는 것이 아...
[정성태] 전각(Full-width)/반각(Half-width) 기능을 토...
[정성태] Vector에 대한 내용은 없습니다. Vector가 닷넷 BCL...
[orion] 글 읽고 찾아보니 디자인 타임에는 InitializeCompon...
[orion] 연휴 전에 재현 프로젝트 올리자 생각해 놓고 여의치 않아서 못 ...
[정성태] 아래의 글에 정리했으니 참고하세요. C# - Typed D...
[정성태] 간단한 재현 프로젝트라도 있을까요? 저런 식으로 설명만 해...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>C# - ffmpeg(FFmpeg.AutoGen)를 이용한 resampling_audio.c 예제 포팅</h1> <p> 지난 예제에 이어,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C# - ffmpeg(FFmpeg.AutoGen)를 이용한 qsvdec.c 예제 포팅 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12975'>https://www.sysnet.pe.kr/2/0/12975</a> </pre> <br /> 이번에는 <a target='tab' href='https://ffmpeg.org/doxygen/trunk/examples.html'>ffmpeg 예제</a> 중 "<a target='tab' href='https://ffmpeg.org/doxygen/trunk/resampling_audio_8c-example.html'>resampling_audio.c</a>" 파일을 FFmpeg.AutoGen으로 포팅하겠습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using FFmpeg.AutoGen; using FFmpeg.AutoGen.Example; namespace resampling_audio { internal unsafe class Program { static int Main(string[] args) { FFmpegBinariesHelper.RegisterFFmpegBinaries(); long src_ch_layout = ffmpeg.AV_CH_LAYOUT_STEREO; long dst_ch_layout = ffmpeg.AV_CH_LAYOUT_SURROUND; int src_rate = 48000, dst_rate = 44100; byte** src_data = null; byte** dst_data = null; int src_nb_channels = 0, dst_nb_channels = 0; int src_linesize, dst_linesize; int src_nb_samples = 1024, dst_nb_samples, max_dst_nb_samples; AVSampleFormat src_sample_fmt = AVSampleFormat.AV_SAMPLE_FMT_DBL, dst_sample_fmt = AVSampleFormat.AV_SAMPLE_FMT_S16; int dst_bufsize; string fmt = ""; SwrContext* swr_ctx; double t; int ret; string dirPath = Path.GetDirectoryName(typeof(Program).Assembly.Location) ?? ""; string dst_filename = Path.Combine(dirPath, "test.dat"); using FileStream dst_file = File.OpenWrite(dst_filename); swr_ctx = ffmpeg.swr_alloc(); if (swr_ctx == null) { Console.WriteLine("Could not allocate resampler context"); ret = ffmpeg.AVERROR(ffmpeg.ENOMEM); goto end; } ffmpeg.av_opt_set_int(swr_ctx, "in_channel_layout", src_ch_layout, 0); ffmpeg.av_opt_set_int(swr_ctx, "in_sample_rate", src_rate, 0); ffmpeg.av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", src_sample_fmt, 0); ffmpeg.av_opt_set_int(swr_ctx, "out_channel_layout", dst_ch_layout, 0); ffmpeg.av_opt_set_int(swr_ctx, "out_sample_rate", dst_rate, 0); ffmpeg.av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", dst_sample_fmt, 0); if ((ret = ffmpeg.swr_init(swr_ctx)) < 0) { Console.WriteLine("Failed to initialize the resampling context"); goto end; } src_nb_channels = ffmpeg.av_get_channel_layout_nb_channels((ulong)src_ch_layout); ret = ffmpeg.av_samples_alloc_array_and_samples(&src_data, &src_linesize, src_nb_channels, src_nb_samples, src_sample_fmt, 0); if (ret < 0) { Console.WriteLine("Could not allocate source samples"); goto end; } max_dst_nb_samples = dst_nb_samples = (int)ffmpeg.av_rescale_rnd(src_nb_samples, dst_rate, src_rate, AVRounding.AV_ROUND_UP); dst_nb_channels = ffmpeg.av_get_channel_layout_nb_channels((ulong)dst_ch_layout); ret = ffmpeg.av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels, dst_nb_samples, dst_sample_fmt, 0); if (ret < 0) { Console.WriteLine("Could not allocate destination samples"); goto end; } t = 0; do { fill_samples((double*)src_data[0], src_nb_samples, src_nb_channels, src_rate, &t); dst_nb_samples = (int)ffmpeg.av_rescale_rnd(ffmpeg.swr_get_delay(swr_ctx, src_rate) + src_nb_samples, dst_rate, src_rate, AVRounding.AV_ROUND_UP); if (dst_nb_samples > max_dst_nb_samples) { ffmpeg.av_freep(&dst_data[0]); ret = ffmpeg.av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels, dst_nb_samples, dst_sample_fmt, 1); if (ret < 0) { break; } max_dst_nb_samples = dst_nb_samples; } ret = ffmpeg.swr_convert(swr_ctx, dst_data, dst_nb_samples, src_data, src_nb_samples); if (ret < 0) { Console.WriteLine("Error while converting"); goto end; } dst_bufsize = ffmpeg.av_samples_get_buffer_size(&dst_linesize, dst_nb_channels, ret, dst_sample_fmt, 1); if (dst_bufsize < 0) { Console.WriteLine("Could not get sample buffer size"); goto end; } Console.WriteLine($"t:{t} in:{src_nb_samples} out:{ret}"); dst_file.Write(new ReadOnlySpan<byte>(dst_data[0], dst_bufsize)); } while (t < 10); if ((ret = get_format_from_sample_fmt(out fmt, dst_sample_fmt)) < 0) { goto end; } Console.WriteLine($"Resampling succeeded. Play the output file with the command:\n ffplay -autoexit -f {fmt} -channel_layout {dst_ch_layout} -channels {dst_nb_channels} -ar {dst_rate} {dst_filename}"); end: if (src_data != null) { ffmpeg.av_freep(&src_data[0]); } ffmpeg.av_freep(&src_data); if (dst_data != null) { ffmpeg.av_freep(&dst_data[0]); } ffmpeg.av_freep(&dst_data); ffmpeg.swr_free(&swr_ctx); return 0; } static void fill_samples(double* dst, int nb_samples, int nb_channels, int sample_rate, double* t) { int i, j; double tincr = 1.0 / sample_rate; double* dstp = dst; const double c = 2 * Math.PI * 440.0; for (i = 0; i < nb_samples; i++) { *dstp = Math.Sin(c * *t); for (j = 1; j < nb_channels; j++) { dstp[j] = dstp[0]; } dstp += nb_channels; *t += tincr; } } static int get_format_from_sample_fmt(out string fmt, AVSampleFormat sample_fmt) { fmt = ""; foreach (var item in sample_fmt_entry.entries) { if (item.sample_fmt == sample_fmt) { fmt = (BitConverter.IsLittleEndian) ? item.fmt_le : item.fmt_be; return 0; } } return ffmpeg.AVERROR(ffmpeg.EINVAL); } } public class sample_fmt_entry { public AVSampleFormat sample_fmt; public string fmt_be = ""; public string fmt_le = ""; public static sample_fmt_entry[] entries = new sample_fmt_entry[] { new sample_fmt_entry { sample_fmt = AVSampleFormat.AV_SAMPLE_FMT_U8, fmt_be = "u8", fmt_le = "u8" }, new sample_fmt_entry { sample_fmt = AVSampleFormat.AV_SAMPLE_FMT_S16, fmt_be = "s16be", fmt_le = "s16le" }, new sample_fmt_entry { sample_fmt = AVSampleFormat.AV_SAMPLE_FMT_S32, fmt_be = "s32be", fmt_le = "s32le" }, new sample_fmt_entry { sample_fmt = AVSampleFormat.AV_SAMPLE_FMT_FLT, fmt_be = "f32be", fmt_le = "f32le" }, new sample_fmt_entry { sample_fmt = AVSampleFormat.AV_SAMPLE_FMT_DBL, fmt_be = "f64be", fmt_le = "f64le" }, }; } } </pre> <br /> 실행하면, 실행 파일 위치에 test.dat 파일이 생성되고, ffplay를 이용한 재생 방법이 출력됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > t:0.021333333333333492 in:1024 out:925 t:0.042666666666666124 in:1024 out:941 t:0.06399999999999711 in:1024 out:940 ...[생략]... t:9.941333333343279 in:1024 out:941 t:9.96266666667732 in:1024 out:941 t:9.984000000011362 in:1024 out:940 t:10.005333333345403 in:1024 out:941 Resampling succeeded. Play the output file with the command: ffplay -autoexit -f s16le -channel_layout 7 -channels 3 -ar 44100 E:\...[생략]...\test.dat </pre> <br /> 예제 코드가 아주 간결해서 더 설명할 것이 없군요. ^^<br /> <br /> (<a target='tab' href='https://github.com/stjeong/ffmpeg_autogen_cs/tree/master/resampling_audio'>이 글의 소스 코드는 github에 올려</a>져 있습니다.)<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1821
(왼쪽의 숫자를 입력해야 합니다.)