성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
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)를 이용한 filtering_video.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)를 이용한 resampling_audio.c 예제 포팅 ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12978'>https://www.sysnet.pe.kr/2/0/12978</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/filtering_video_8c-example.html'>filtering_video.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; using FFmpeg.OSDepends; using System; using System.IO; namespace filtering_video { internal unsafe class Program { const string filter_descr = "scale=78:24,transpose=cclock"; /* other way: scale=78:24 [scl]; [scl] transpose=cclock // assumes "[in]" and "[out]" to be input output pads respectively */ static AVFormatContext* fmt_ctx; static AVCodecContext* dec_ctx; static AVFilterContext* buffersink_ctx; static AVFilterContext* buffersrc_ctx; static AVFilterGraph* filter_graph; static int video_stream_index = -1; static long last_pts = ffmpeg.AV_NOPTS_VALUE; static unsafe int Main(string[] args) { FFmpegBinariesHelper.RegisterFFmpegBinaries(); int ret; AVPacket* packet; AVFrame* frame; AVFrame* filt_frame; frame = ffmpeg.av_frame_alloc(); filt_frame = ffmpeg.av_frame_alloc(); packet = ffmpeg.av_packet_alloc(); if (frame == null || filt_frame == null || packet == null) { Console.WriteLine("Could not allocate frame or packet"); return 1; } string dirPath = Path.GetDirectoryName(typeof(Program).Assembly.Location) ?? ""; // https://file-examples.com/index.php/sample-video-files/sample-mp4-files/ string inputfile = Path.Combine(dirPath, "..", "..", "..", "Samples", "file_example_MP4_1920_18MG.mp4"); if ((ret = open_input_file(inputfile)) < 0) { goto end; } if ((ret = init_filters(filter_descr)) < 0) { goto end; } while (true) { if ((ret = ffmpeg.av_read_frame(fmt_ctx, packet)) < 0) { break; } if (packet->stream_index == video_stream_index) { ret = ffmpeg.avcodec_send_packet(dec_ctx, packet); if (ret < 0) { ffmpeg.av_log(null, ffmpeg.AV_LOG_ERROR, "Error while sending a packet to the decoder"); break; } while (ret >= 0) { ret = ffmpeg.avcodec_receive_frame(dec_ctx, frame); if (ret == ffmpeg.AVERROR(ffmpeg.EAGAIN) || ret == ffmpeg.AVERROR_EOF) { break; } else if (ret < 0) { ffmpeg.av_log(null, ffmpeg.AV_LOG_ERROR, "Error while receiving a frame from the decoder"); goto end; } frame->pts = frame->best_effort_timestamp; if (ffmpeg.av_buffersrc_add_frame_flags(buffersrc_ctx, frame, (int)AV_BUFFERSRC_FLAG.KEEP_REF) < 0) { ffmpeg.av_log(null, ffmpeg.AV_LOG_ERROR, "Error while feeding the filtergraph"); break; } while (true) { ret = ffmpeg.av_buffersink_get_frame(buffersink_ctx, filt_frame); if (ret == ffmpeg.AVERROR(ffmpeg.EAGAIN) || ret == ffmpeg.AVERROR_EOF) { break; } if (ret < 0) { goto end; } display_name(filt_frame, buffersink_ctx->inputs[0]->time_base); ffmpeg.av_frame_unref(filt_frame); } ffmpeg.av_frame_unref(frame); } } ffmpeg.av_packet_unref(packet); } end: fixed (AVFilterGraph** pfilter = &filter_graph) { ffmpeg.avfilter_graph_free(pfilter); } fixed (AVCodecContext** pdec_ctx = &dec_ctx) { ffmpeg.avcodec_free_context(pdec_ctx); } fixed (AVFormatContext** pfmt_ctx = &fmt_ctx) { ffmpeg.avformat_close_input(pfmt_ctx); } ffmpeg.av_frame_free(&frame); ffmpeg.av_frame_free(&filt_frame); ffmpeg.av_packet_free(&packet); if (ret < 0 && ret != ffmpeg.AVERROR_EOF) { Console.WriteLine($"Error occurred: {FFmpegHelper.av_strerror(ret)}"); return 1; } return 0; } static unsafe int open_input_file(string filename) { AVCodec* dec; int ret; fixed (AVFormatContext** pfmt_ctx = &fmt_ctx) { if ((ret = ffmpeg.avformat_open_input(pfmt_ctx, filename, null, null)) < 0) { ffmpeg.av_log(null, ffmpeg.AV_LOG_ERROR, "Cannot open input file"); return ret; } } if ((ret = ffmpeg.avformat_find_stream_info(fmt_ctx, null)) < 0) { ffmpeg.av_log(null, ffmpeg.AV_LOG_ERROR, "Cannot find stream information"); return ret; } ret = ffmpeg.av_find_best_stream(fmt_ctx, AVMediaType.AVMEDIA_TYPE_VIDEO, -1, -1, &dec, 0); if (ret < 0) { ffmpeg.av_log(null, ffmpeg.AV_LOG_ERROR, "Cannot find a video stream in the input file"); return ret; } video_stream_index = ret; dec_ctx = ffmpeg.avcodec_alloc_context3(dec); if (dec_ctx == null) { return ffmpeg.AVERROR(ffmpeg.ENOMEM); } ffmpeg.avcodec_parameters_to_context(dec_ctx, fmt_ctx->streams[video_stream_index]->codecpar); if ((ret = ffmpeg.avcodec_open2(dec_ctx, dec, null)) < 0) { ffmpeg.av_log(null, ffmpeg.AV_LOG_ERROR, "Cannot open video decoder"); return ret; } return ret; } static unsafe int init_filters(string filter_descr) { int ret = 0; AVFilter* buffersrc = ffmpeg.avfilter_get_by_name("buffer"); AVFilter* buffersink = ffmpeg.avfilter_get_by_name("buffersink"); AVFilterInOut* outputs = ffmpeg.avfilter_inout_alloc(); AVFilterInOut* inputs = ffmpeg.avfilter_inout_alloc(); AVRational time_base = fmt_ctx->streams[video_stream_index]->time_base; Span<int> pix_fmts = stackalloc int[] { (int)AVPixelFormat.AV_PIX_FMT_GRAY8, }; filter_graph = ffmpeg.avfilter_graph_alloc(); if (outputs == null || inputs == null || filter_graph == null) { ret = ffmpeg.AVERROR(ffmpeg.ENOMEM); goto end; } string args = $"video_size={dec_ctx->width}x{dec_ctx->height}:pix_fmt={(int)dec_ctx->pix_fmt}:" + $"time_base={time_base.num}/{time_base.den}:pixel_aspect={dec_ctx->sample_aspect_ratio.num}/{dec_ctx->sample_aspect_ratio.den}"; fixed (AVFilterContext** pbuffersrc_ctx = &buffersrc_ctx) { ret = ffmpeg.avfilter_graph_create_filter(pbuffersrc_ctx, buffersrc, "in", args, null, filter_graph); if (ret < 0) { ffmpeg.av_log(null, ffmpeg.AV_LOG_ERROR, "Cannot create buffer source"); goto end; } } fixed (AVFilterContext** pbuffersink_ctx = &buffersink_ctx) { ret = ffmpeg.avfilter_graph_create_filter(pbuffersink_ctx, buffersink, "out", null, null, filter_graph); if (ret < 0) { ffmpeg.av_log(null, ffmpeg.AV_LOG_ERROR, "Cannot create buffer sink"); goto end; } } fixed (int* pfmts = pix_fmts) { ret = ffmpeg.av_opt_set_bin(buffersink_ctx, "pix_fmts", (byte*)pfmts, pix_fmts.Length * sizeof(int), ffmpeg.AV_OPT_SEARCH_CHILDREN); if (ret < 0) { ffmpeg.av_log(null, ffmpeg.AV_LOG_ERROR, "Cannot set output pixel format"); goto end; } } outputs->name = ffmpeg.av_strdup("in"); outputs->filter_ctx = buffersrc_ctx; outputs->pad_idx = 0; outputs->next = null; inputs->name = ffmpeg.av_strdup("out"); inputs->filter_ctx = buffersink_ctx; inputs->pad_idx = 0; inputs->next = null; if ((ret = ffmpeg.avfilter_graph_parse_ptr(filter_graph, filter_descr, &inputs, &outputs, null)) < 0) { goto end; } if ((ret = ffmpeg.avfilter_graph_config(filter_graph, null)) < 0) { goto end; } end: ffmpeg.avfilter_inout_free(&inputs); ffmpeg.avfilter_inout_free(&outputs); return ret; } static unsafe void display_name(AVFrame* frame, AVRational time_base) { int x, y; byte* p0; byte* p; long delay; string drawing = " .-+#"; // <a target='tab' href='https://gamz.tistory.com/16'>https://gamz.tistory.com/16</a> if (frame->pts != ffmpeg.AV_NOPTS_VALUE) { if (last_pts != ffmpeg.AV_NOPTS_VALUE) { delay = ffmpeg.av_rescale_q(frame->pts - last_pts, time_base, FFmpegHelper.AV_TIME_BASE_Q); if (delay > 0 && delay < 1_000_000) { NativeMethods.uSleep(delay); // <a target='tab' href='https://www.sysnet.pe.kr/2/0/12980'>https://www.sysnet.pe.kr/2/0/12980</a> } } last_pts = frame->pts; } p0 = frame->data[0]; Console.Clear(); for (y = 0; y < frame->height; y++) { p = p0; for (x = 0; x < frame->width; x++) { Console.Write(drawing[*(p++) / 52]); } Console.WriteLine(); p0 += frame->linesize[0]; } } } } </pre> <br /> 전체적으로 소스 코드는 오디오 예제와 유사합니다.<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)를 이용한 오디오 필터링 예제(filtering_audio.c) ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12951'>https://www.sysnet.pe.kr/2/0/12951</a> </pre> <br /> 그리고, 예제 동영상을 대상으로 실행시키면 뜻모를 ^^; 화면만 나옵니다.<br /> <br /> <img alt='ffmpeg_filtering_video_1.png' src='/SysWebRes/bbs/ffmpeg_filtering_video_1.png' /><br /> <br /> (<a target='tab' href='https://github.com/stjeong/ffmpeg_autogen_cs/tree/master/filtering_video'>이 글의 소스 코드는 github에 올려</a>져 있습니다.)<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
5054
(왼쪽의 숫자를 입력해야 합니다.)