Ffmpeg 좌우 반전 - Ffmpeg jwau banjeon

뮤텍스 소스

< VideoFilter.h >

#ifndef __VIDEO_FILTER_H__ #define __VIDEO_FILTER_H__ extern "C" { #include "libavfilter/avfiltergraph.h" #include "libavfilter/buffersink.h" #include "libavfilter/buffersrc.h" } #include "Mutex.h" struct VideoFilterParam { int width; int height; AVPixelFormat pix_fmt; AVRational time_base; AVRational sample_aspect_ratio; }; class VideoFilter { public: VideoFilter(); virtual ~VideoFilter(); int initFilter(struct VideoFilterParam &param, int vflip, int hflip, int rotate); void freeFilter(); int processFilter(AVFrame *newFrame, AVFrame *frame); int checkFilter(struct VideoFilterParam &param); protected: static void initFilter(); protected: AVFilterGraph* m_pFilterGraph; AVFilterContext* m_pBufferSinkCtx; AVFilterContext* m_pBufferSrcCtx; AVFrame* m_pFrame; int m_nWidth; int m_nHeight; AVPixelFormat m_nPixelFormat; AVRational m_timeBase; AVRational m_sampleAspectRatio; static MUTEX m_hMutex; static bool m_bInit; }; #endif

< VideoFilter.cpp >

#include "VideoFilter.h" #include "GlobalEnv.h" #include "CommonType.h" bool VideoFilter::m_bInit = false; MUTEX VideoFilter::m_hMutex = PTHREAD_MUTEX_INITIALIZER; VideoFilter::VideoFilter() : m_pFilterGraph(NULL), m_pBufferSrcCtx(NULL), m_pBufferSinkCtx(NULL), m_pFrame(NULL) { initFilter(); m_nWidth = m_nHeight = 0; m_nPixelFormat = AV_PIX_FMT_NONE; m_timeBase.den = m_timeBase.num = 0; m_sampleAspectRatio.den = m_sampleAspectRatio.num = 0; } VideoFilter::~VideoFilter() { freeFilter(); } void VideoFilter::initFilter() { MUTEX_LOCK(&m_hMutex); if (!m_bInit) { avfilter_register_all(); m_bInit = true; } MUTEX_UNLOCK(&m_hMutex); } int VideoFilter::initFilter(struct VideoFilterParam &param, int vflip, int hflip, int rotate) { freeFilter(); char args[128]; snprintf(args, sizeof(args), "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d", param.width, param.height, param.pix_fmt, param.time_base.num, param.time_base.den, param.sample_aspect_ratio.num, param.sample_aspect_ratio.den); m_pFrame = av_frame_alloc(); m_pFilterGraph = avfilter_graph_alloc(); char errbuf[128]; int err = avfilter_graph_create_filter(&m_pBufferSrcCtx, avfilter_get_by_name("buffer"), "buffer1", args, NULL, m_pFilterGraph); if (err < 0) { av_strerror(err, errbuf, sizeof(errbuf)); DXPRINTF("avfilter_graph_create_filter failed, err : %s\n", errbuf); return -1; } err = avfilter_graph_create_filter(&m_pBufferSinkCtx, avfilter_get_by_name("buffersink"), "buffersink1", NULL, NULL, m_pFilterGraph); if (err < 0) { av_strerror(err, errbuf, sizeof(errbuf)); DXPRINTF("avfilter_graph_create_filter failed, err : %s\n", errbuf); return -1; } AVFilterContext *vflipCtx = NULL; AVFilterContext *hflipCtx = NULL; AVFilterContext *rotateCtx = NULL; AVFilterContext *prevCtx = m_pBufferSrcCtx; if (vflip > 0) { err = avfilter_graph_create_filter(&vflipCtx, avfilter_get_by_name("vflip"), "vflip1", NULL, NULL, m_pFilterGraph); if (err < 0) { av_strerror(err, errbuf, sizeof(errbuf)); DXPRINTF("avfilter_graph_create_filter failed, err : %s\n", errbuf); return -1; } err = avfilter_link(prevCtx, 0, vflipCtx, 0); if (err < 0) { av_strerror(err, errbuf, sizeof(errbuf)); DXPRINTF("avfilter_link failed, err : %s\n", errbuf); return -1; } prevCtx = vflipCtx; } if (hflip > 0) { err = avfilter_graph_create_filter(&hflipCtx, avfilter_get_by_name("hflip"), "hflip1", NULL, NULL, m_pFilterGraph); if (err < 0) { av_strerror(err, errbuf, sizeof(errbuf)); DXPRINTF("avfilter_graph_create_filter failed, err : %s\n", errbuf); return -1; } err = avfilter_link(prevCtx, 0, hflipCtx, 0); if (err < 0) { av_strerror(err, errbuf, sizeof(errbuf)); DXPRINTF("avfilter_link failed, err : %s\n", errbuf); return -1; } prevCtx = hflipCtx; } if (rotate) { snprintf(args, sizeof(args), "PI*2/360*%d", rotate); err = avfilter_graph_create_filter(&rotateCtx, avfilter_get_by_name("rotate"), "rotate1", args, NULL, m_pFilterGraph); if (err < 0) { av_strerror(err, errbuf, sizeof(errbuf)); DXPRINTF("avfilter_graph_create_filter failed, err : %s\n", errbuf); return -1; } err = avfilter_link(prevCtx, 0, rotateCtx, 0); if (err < 0) { av_strerror(err, errbuf, sizeof(errbuf)); DXPRINTF("avfilter_link failed, err : %s\n", errbuf); return -1; } prevCtx = rotateCtx; } err = avfilter_link(prevCtx, 0, m_pBufferSinkCtx, 0); if (err < 0) { av_strerror(err, errbuf, sizeof(errbuf)); DXPRINTF("avfilter_link failed, err : %s\n", errbuf); return -1; } err = avfilter_graph_config(m_pFilterGraph, NULL); if (err < 0) { av_strerror(err, errbuf, sizeof(errbuf)); DXPRINTF("avfilter_graph_config failed, err : %s\n", errbuf); return -1; } m_nWidth = param.width; m_nHeight = param.height; m_nPixelFormat = param.pix_fmt; m_timeBase.den = param.time_base.den; m_timeBase.num = param.time_base.num; m_sampleAspectRatio.den = param.sample_aspect_ratio.den; m_sampleAspectRatio.num = param.sample_aspect_ratio.num; return 0; } void VideoFilter::freeFilter() { avfilter_graph_free(&m_pFilterGraph); av_frame_free(&m_pFrame); m_nWidth = m_nHeight = 0; m_nPixelFormat = AV_PIX_FMT_NONE; m_timeBase.den = m_timeBase.num = 0; m_sampleAspectRatio.den = m_sampleAspectRatio.num = 0; } AVFrame* copyFrame(AVFrame *frame) { AVFrame *new_frame = avcodec_alloc_frame(); if (new_frame) { if (av_image_alloc(new_frame->data, new_frame->linesize, frame->width, frame->height, (AVPixelFormat)frame->format, 1) > 0) { av_image_copy(new_frame->data, new_frame->linesize, (const uint8_t **)frame->data, frame->linesize, (AVPixelFormat)frame->format, frame->width, frame->height); new_frame->width = frame->width; new_frame->height = frame->height; new_frame->pict_type = frame->pict_type; new_frame->format = frame->format; return new_frame; } else { av_free(new_frame->data[0]); av_free(new_frame); } } return NULL; } int VideoFilter::processFilter(AVFrame *newFrame, AVFrame *frame) { if (!m_pFilterGraph) return -1; int ret = av_buffersrc_add_frame_flags(m_pBufferSrcCtx, frame, AV_BUFFERSRC_FLAG_KEEP_REF); if (ret >= 0) { while (1) { ret = av_buffersink_get_frame(m_pBufferSinkCtx, m_pFrame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) break; if (ret < 0) break; newFrame = copyFrame(m_pFrame); av_frame_unref(m_pFrame); } } return 0; } int VideoFilter::checkFilter(struct VideoFilterParam &param) { if (m_nWidth != param.width || m_nHeight != param.height || m_nPixelFormat != param.pix_fmt || m_timeBase.den != param.time_base.den || m_timeBase.num != param.time_base.num || m_sampleAspectRatio.den != param.sample_aspect_ratio.den || m_sampleAspectRatio.num != param.sample_aspect_ratio.num) { return -1; } return 0; }

< VideoFilter 사용 >

AVCodecContext *pCodecCtx;
...
struct VideoFilterParam param;
param.width = pCodecCtx->width;
param.height = pCodecCtx->height;
param.pix_fmt = pCodecCtx->pix_fmt;
param.time_base.den = pCodecCtx->time_base.den;
param.time_base.num = pCodecCtx->time_base.num;
param.sample_aspect_ratio.den = pCodecCtx->sample_aspect_ratio.den;
param.sample_aspect_ratio.num = pCodecCtx->sample_aspect_ratio.num;
...
VideoFilter *filter = new VideoFilter();
...
filter->initFilter(param, 1, 1, 30);    // 상하반전, 좌우반전, 30도 회전
...
if (filter->checkFilter(param) < 0) {
    filter->freeFilter();

      param.width = pCodecCtx->width;
    param.height = pCodecCtx->height;
    param.pix_fmt = pCodecCtx->pix_fmt;
    param.time_base.den = pCodecCtx->time_base.den;
    param.time_base.num = pCodecCtx->time_base.num;
    param.sample_aspect_ratio.den = pCodecCtx->sample_aspect_ratio.den;
    param.sample_aspect_ratio.num = pCodecCtx->sample_aspect_ratio.num;
}  
filter->processFilter(newFrame, frame);   // newFrame은 처리결과, frame은 디코딩된 프레임
...
filter->freeFilter();

Toplist

최신 우편물

태그