Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4c480ce

Browse files
committed
Merge pull request#180 from cchampet/dev_addAvFilter
Manage filters
2 parents8a895ac +6371c40 commit4c480ce

File tree

16 files changed

+558
-6
lines changed

16 files changed

+558
-6
lines changed

‎src/AvTranscoder/Library.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ extern "C" {
55
#include<libavcodec/version.h>
66
#include<libswscale/version.h>
77
#include<libswscale/swscale.h>
8+
#include<libavfilter/version.h>
89
#ifdef AVTRANSCODER_LIBAV_DEPENDENCY
910
#include<libavresample/version.h>
1011
#else
1112
#include<libswresample/version.h>
1213
#endif
1314
#include<libavformat/avformat.h>
15+
#include<libavfilter/avfilter.h>
1416
}
1517

1618
#include<cstring>
@@ -94,6 +96,8 @@ Libraries getLibraries()
9496
#endif
9597
libs.push_back(
9698
Library("swscale",swscale_license(), LIBSWSCALE_VERSION_MAJOR, LIBSWSCALE_VERSION_MINOR, LIBSWSCALE_VERSION_MICRO));
99+
libs.push_back(Library("avfilter",avfilter_license(), LIBAVFILTER_VERSION_MAJOR, LIBAVFILTER_VERSION_MINOR,
100+
LIBAVFILTER_VERSION_MICRO));
97101

98102
return libs;
99103
}

‎src/AvTranscoder/avTranscoder.i

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,6 @@
3838
%include"AvTranscoder/transform/transform.i"
3939
%include"AvTranscoder/file/file.i"
4040
%include"AvTranscoder/stat/stat.i"
41+
%include"AvTranscoder/filter/filter.i"
4142
%include"AvTranscoder/transcoder/transcoder.i"
4243
%include"AvTranscoder/reader/reader.i"

‎src/AvTranscoder/common.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
extern"C" {
44
#include<libavformat/avformat.h>
5+
#include<libavfilter/avfilter.h>
56
#include<libavutil/error.h>
67
}
78

@@ -15,6 +16,7 @@ namespace avtranscoder
1516
voidpreloadCodecsAndFormats()
1617
{
1718
av_register_all();
19+
avfilter_register_all();
1820
}
1921

2022
std::stringgetDescriptionFromErrorCode(constint code)

‎src/AvTranscoder/data/decoded/AudioFrame.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class AvExport AudioFrame : public Frame
4444

4545
size_tgetSampleRate()const {returnav_frame_get_sample_rate(_frame); }
4646
size_tgetNbChannels()const {returnav_frame_get_channels(_frame); }
47+
size_tgetChannelLayout()const {returnav_frame_get_channel_layout(_frame); }
4748
AVSampleFormatgetSampleFormat()const {returnstatic_cast<AVSampleFormat>(_frame->format); }
4849
size_tgetNbSamplesPerChannel()const {return _frame->nb_samples; }
4950
AudioFrameDescdesc()const {returnAudioFrameDesc(getSampleRate(),getNbChannels(),getSampleFormat()); }

‎src/AvTranscoder/data/decoded/Frame.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,18 @@ void Frame::allocateAVFrame()
8080
throwstd::runtime_error("Unable to allocate an empty Frame.");
8181
}
8282
}
83+
84+
boolFrame::isAudioFrame()const
85+
{
86+
if(_frame->sample_rate && _frame->channels && _frame->channel_layout && _frame->format != -1)
87+
returntrue;
88+
returnfalse;
89+
}
90+
91+
boolFrame::isVideoFrame()const
92+
{
93+
if(_frame->width && _frame->height && _frame->format != -1)
94+
returntrue;
95+
returnfalse;
96+
}
8397
}

‎src/AvTranscoder/data/decoded/Frame.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,18 @@ class AvExport Frame
6363
*/
6464
voidclear();
6565

66+
/**
67+
* @return If it corresponds to a valid audio frame.
68+
* @see AudioFrame
69+
*/
70+
boolisAudioFrame()const;
71+
72+
/**
73+
* @return If it corresponds to a valid video frame.
74+
* @see VideoFrame
75+
*/
76+
boolisVideoFrame()const;
77+
6678
#ifndef SWIG
6779
AVFrame&getAVFrame() {return *_frame; }
6880
const AVFrame&getAVFrame()const {return *_frame; }

‎src/AvTranscoder/decoder/AudioGenerator.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ class AvExport AudioGenerator : public IDecoder
2222
voidsetNextFrame(Frame& inputFrame);
2323

2424
private:
25-
Frame* _inputFrame;///< Has link (no ownership)
26-
AudioFrame* _silent;///< The generated silent (has ownership)
25+
Frame* _inputFrame;///< Has link (no ownership)
26+
AudioFrame* _silent;///< The generated silent (has ownership)
2727
};
2828
}
2929

‎src/AvTranscoder/filter/Filter.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include"Filter.hpp"
2+
3+
extern"C" {
4+
#include<libavfilter/avfilter.h>
5+
}
6+
7+
#include<stdexcept>
8+
9+
namespaceavtranscoder
10+
{
11+
12+
Filter::Filter(const std::string& name,const std::string& options,const std::string& instanceName)
13+
: _filter(NULL)
14+
, _context(NULL)
15+
, _options(options)
16+
, _instanceName(instanceName.empty() ? name : instanceName)
17+
{
18+
_filter =avfilter_get_by_name(name.c_str());
19+
if(!_filter)
20+
{
21+
std::stringmsg("Cannot find filter");
22+
msg += name;
23+
msg +=". It will not be added to the filter graph.";
24+
throwstd::runtime_error(msg);
25+
}
26+
}
27+
28+
Filter::~Filter()
29+
{
30+
avfilter_free(_context);
31+
}
32+
33+
std::stringFilter::getName()const
34+
{
35+
return _filter->name ?std::string(_filter->name) :"";
36+
}
37+
}

‎src/AvTranscoder/filter/Filter.hpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#ifndef _AV_TRANSCODER_FILTER_FILTER_HPP_
2+
#define_AV_TRANSCODER_FILTER_FILTER_HPP_
3+
4+
#include<AvTranscoder/common.hpp>
5+
6+
structAVFilter;
7+
structAVFilterContext;
8+
9+
namespaceavtranscoder
10+
{
11+
12+
/**
13+
* @brief Describe a filter and its options.
14+
**/
15+
classAvExport Filter
16+
{
17+
public:
18+
Filter(const std::string& name,const std::string& options ="",const std::string& instanceName ="");
19+
~Filter();
20+
21+
std::stringgetName()const;
22+
std::stringgetOptions()const {return _options; }
23+
std::stringgetInstanceName()const {return _instanceName; }
24+
25+
#ifndef SWIG
26+
AVFilter&getAVFilter() {return *_filter; }
27+
AVFilterContext*getAVFilterContext() {return _context; }
28+
29+
voidsetAVFilterContext(AVFilterContext* newContext) { _context = newContext; }
30+
#endif
31+
32+
private:
33+
AVFilter* _filter;
34+
AVFilterContext* _context;
35+
std::string _options;
36+
std::string _instanceName;
37+
};
38+
}
39+
40+
#endif
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
#include"FilterGraph.hpp"
2+
3+
#include<AvTranscoder/util.hpp>
4+
#include<AvTranscoder/data/decoded/AudioFrame.hpp>
5+
#include<AvTranscoder/data/decoded/VideoFrame.hpp>
6+
7+
extern"C" {
8+
#include<libavfilter/avfilter.h>
9+
#include<libavfilter/buffersrc.h>
10+
#include<libavfilter/buffersink.h>
11+
}
12+
13+
#include<stdexcept>
14+
#include<sstream>
15+
16+
namespaceavtranscoder
17+
{
18+
19+
FilterGraph::FilterGraph(const ICodec& codec)
20+
: _graph(avfilter_graph_alloc())
21+
, _filters()
22+
, _codec(codec)
23+
, _isInit(false)
24+
{
25+
if(!_graph)
26+
throwstd::runtime_error("Unable to create filter graph: out of memory.");
27+
}
28+
29+
FilterGraph::~FilterGraph()
30+
{
31+
for(std::vector<Filter*>::iterator it = _filters.begin(); it < _filters.end(); ++it)
32+
{
33+
it = _filters.erase(it);
34+
}
35+
avfilter_graph_free(&_graph);
36+
}
37+
38+
voidFilterGraph::process(Frame& frame)
39+
{
40+
if(!hasFilters())
41+
{
42+
LOG_DEBUG("No filter to process.")
43+
return;
44+
}
45+
46+
// init filter graph
47+
if(!_isInit)
48+
init(frame);
49+
50+
// setup source frame
51+
int ret =av_buffersrc_write_frame(_filters.at(0)->getAVFilterContext(), &frame.getAVFrame());
52+
if(ret <0)
53+
{
54+
throwstd::runtime_error("Error when adding a frame to the source buffer used to start to process filters:" +
55+
getDescriptionFromErrorCode(ret));
56+
}
57+
58+
// pull filtered data from the filter graph
59+
for(;;)
60+
{
61+
ret =av_buffersink_get_frame(_filters.at(_filters.size() -1)->getAVFilterContext(), &frame.getAVFrame());
62+
if(ret == AVERROR_EOF || ret ==AVERROR(EAGAIN))
63+
break;
64+
if(ret <0)
65+
{
66+
throwstd::runtime_error("Error reading buffer from buffersink:" +getDescriptionFromErrorCode(ret));
67+
}
68+
}
69+
}
70+
71+
Filter&FilterGraph::addFilter(const std::string& filterName,const std::string& filterOptions,
72+
const std::string& instanceName)
73+
{
74+
LOG_INFO("Add filter" << filterName <<" to the graph.")
75+
Filter* filter =newFilter(filterName, filterOptions, instanceName);
76+
_filters.push_back(filter);
77+
return *_filters.back();
78+
}
79+
80+
voidFilterGraph::init(const Frame& frame)
81+
{
82+
// push filters to the graph
83+
pushInBuffer(frame);
84+
for(size_t i =1; i < _filters.size(); ++i)
85+
{
86+
pushFilter(*_filters.at(i));
87+
}
88+
pushOutBuffer(frame);
89+
90+
// connect filters
91+
for(size_t index =0; index < _filters.size() -1; ++index)
92+
{
93+
LOG_INFO("Connect filter" << _filters.at(index)->getName() <<" to filter" << _filters.at(index +1)->getName())
94+
constint err =
95+
avfilter_link(_filters.at(index)->getAVFilterContext(),0, _filters.at(index +1)->getAVFilterContext(),0);
96+
if(err <0)
97+
{
98+
throwstd::runtime_error("Error when connecting filters.");
99+
}
100+
}
101+
102+
// configuring the graph
103+
LOG_INFO("Configuring filter graph.")
104+
constint err =avfilter_graph_config(_graph,NULL);
105+
if(err <0)
106+
{
107+
throwstd::runtime_error("Error configuring the filter graph:" +getDescriptionFromErrorCode(err));
108+
}
109+
110+
_isInit =true;
111+
}
112+
113+
voidFilterGraph::pushFilter(Filter& filter)
114+
{
115+
AVFilterContext* context =NULL;
116+
constint err =avfilter_graph_create_filter(&context, &filter.getAVFilter(), filter.getInstanceName().c_str(),
117+
filter.getOptions().c_str(),NULL, _graph);
118+
filter.setAVFilterContext(context);
119+
if(err <0)
120+
{
121+
std::stringmsg("Cannot add filter");
122+
msg += filter.getName();
123+
msg +=" (instance=";
124+
msg += filter.getInstanceName();
125+
msg +=") to the graph:";
126+
msg +=getDescriptionFromErrorCode(err);
127+
throwstd::runtime_error(msg);
128+
}
129+
}
130+
131+
voidFilterGraph::pushInBuffer(const Frame& frame)
132+
{
133+
std::string filterName;
134+
std::stringstream filterOptions;
135+
// audio frame
136+
if(frame.isAudioFrame())
137+
{
138+
filterName ="abuffer";
139+
const AudioFrame& audioFrame =dynamic_cast<const AudioFrame&>(frame);
140+
filterOptions <<"time_base=" << _codec.getAVCodecContext().time_base.num <<"/"
141+
<< _codec.getAVCodecContext().time_base.den <<":";
142+
filterOptions <<"sample_rate=" << audioFrame.getSampleRate() <<":";
143+
filterOptions <<"sample_fmt=" <<getSampleFormatName(audioFrame.getSampleFormat()) <<":";
144+
filterOptions <<"channel_layout=0x" << std::hex << audioFrame.getChannelLayout();
145+
}
146+
// video frame
147+
elseif(frame.isVideoFrame())
148+
{
149+
filterName ="buffer";
150+
const VideoFrame& videoFrame =dynamic_cast<const VideoFrame&>(frame);
151+
filterOptions <<"video_size=" << videoFrame.getWidth() <<"x" << videoFrame.getHeight() <<":";
152+
filterOptions <<"pix_fmt=" <<getPixelFormatName(videoFrame.getPixelFormat()) <<":";
153+
filterOptions <<"time_base=" << _codec.getAVCodecContext().time_base.num <<"/"
154+
<< _codec.getAVCodecContext().time_base.den <<":";
155+
filterOptions <<"pixel_aspect=" << _codec.getAVCodecContext().sample_aspect_ratio.num <<"/"
156+
<< _codec.getAVCodecContext().sample_aspect_ratio.den;
157+
}
158+
// invalid frame
159+
else
160+
throwstd::runtime_error("Cannot create input buffer of filter graph: the given frame is invalid.");
161+
162+
// add in buffer
163+
Filter* in =newFilter(filterName, filterOptions.str(),"in");
164+
LOG_INFO("Add filter '" << filterName <<"' at the beginning of the graph.")
165+
_filters.insert(_filters.begin(), in);
166+
pushFilter(*in);
167+
}
168+
169+
voidFilterGraph::pushOutBuffer(const Frame& frame)
170+
{
171+
std::string filterName;
172+
173+
if(frame.isAudioFrame())
174+
filterName ="abuffersink";
175+
elseif(frame.isVideoFrame())
176+
filterName ="buffersink";
177+
else
178+
throwstd::runtime_error("Cannot create output buffer of filter graph: the given frame is invalid.");
179+
180+
// add out buffer
181+
Filter& out =addFilter(filterName,"","out");
182+
pushFilter(out);
183+
}
184+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp