AvTranscoder  0.9.4
C++APIforLibav/FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
FilterGraph.cpp
Go to the documentation of this file.
1 #include "FilterGraph.hpp"
2 
3 #include <AvTranscoder/util.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 namespace avtranscoder
17 {
18 
20  : _graph(avfilter_graph_alloc())
21  , _filters()
22  , _codec(codec)
23  , _isInit(false)
24 {
25  if(!_graph)
26  throw std::runtime_error("Unable to create filter graph: out of memory.");
27 }
28 
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 
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  throw std::runtime_error("Error when adding a frame to the source buffer used to start to process filters: " +
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  throw std::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 = new Filter(filterName, filterOptions, instanceName);
76  _filters.push_back(filter);
77  return *_filters.back();
78 }
79 
80 void FilterGraph::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  const int err =
95  avfilter_link(_filters.at(index)->getAVFilterContext(), 0, _filters.at(index + 1)->getAVFilterContext(), 0);
96  if(err < 0)
97  {
98  throw std::runtime_error("Error when connecting filters.");
99  }
100  }
101 
102  // configuring the graph
103  LOG_INFO("Configuring filter graph.")
104  const int err = avfilter_graph_config(_graph, NULL);
105  if(err < 0)
106  {
107  throw std::runtime_error("Error configuring the filter graph: " + getDescriptionFromErrorCode(err));
108  }
109 
110  _isInit = true;
111 }
112 
114 {
115  AVFilterContext* context = NULL;
116  const int 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::string msg("Cannot add filter ");
122  msg += filter.getName();
123  msg += " (instance=";
124  msg += filter.getInstanceName();
125  msg += ") to the graph: ";
126  msg += getDescriptionFromErrorCode(err);
127  throw std::runtime_error(msg);
128  }
129 }
130 
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  else if(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  throw std::runtime_error("Cannot create input buffer of filter graph: the given frame is invalid.");
161 
162  // add in buffer
163  Filter* in = new Filter(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 
170 {
171  std::string filterName;
172 
173  if(frame.isAudioFrame())
174  filterName = "abuffersink";
175  else if(frame.isVideoFrame())
176  filterName = "buffersink";
177  else
178  throw std::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 }
size_t getChannelLayout() const
Definition: AudioFrame.hpp:47
Describe a filter and its options.
Definition: Filter.hpp:15
bool _isInit
Is the FilterGraph initialized.
Definition: FilterGraph.hpp:86
void pushOutBuffer(const Frame &frame)
bool isVideoFrame() const
Definition: Frame.cpp:96
This class describes decoded video data.
Definition: VideoFrame.hpp:43
FilterGraph(const FilterGraph &otherFilterGraph)
void setAVFilterContext(AVFilterContext *newContext)
Definition: Filter.hpp:29
AVSampleFormat getSampleFormat() const
Definition: AudioFrame.hpp:48
AVFilter & getAVFilter()
Definition: Filter.hpp:26
std::string getInstanceName() const
Definition: Filter.hpp:23
std::string getDescriptionFromErrorCode(const int code)
Get the string description corresponding to the error code provided by ffmpeg/libav.
Definition: common.cpp:22
bool isAudioFrame() const
Definition: Frame.cpp:89
#define LOG_INFO(...)
Definition: log.hpp:23
std::string getPixelFormatName(const AVPixelFormat pixelFormat)
Definition: util.cpp:100
AVPixelFormat getPixelFormat() const
Definition: VideoFrame.hpp:51
std::string getOptions() const
Definition: Filter.hpp:22
void init(const Frame &frame)
Initialize the graph of filters to process.
Definition: FilterGraph.cpp:80
Filter & addFilter(const std::string &filterName, const std::string &filterOptions="", const std::string &instanceName="")
Add a filter.
Definition: FilterGraph.cpp:71
void pushInBuffer(const Frame &frame)
Push the input and output buffer at the beginning and the end of the graph.
size_t getHeight() const
Definition: VideoFrame.hpp:50
std::vector< Filter * > _filters
List of filters to process.
Definition: FilterGraph.hpp:79
size_t getSampleRate() const
Definition: AudioFrame.hpp:45
This class describes decoded audio data.
Definition: AudioFrame.hpp:36
This class describes decoded (raw) audio or video data.
Definition: Frame.hpp:16
std::string getName() const
Definition: Filter.cpp:33
void process(Frame &frame)
Pull filtered data from the filter graph, and put result to the given frame.
Definition: FilterGraph.cpp:38
AVCodecContext & getAVCodecContext()
Definition: ICodec.hpp:53
#define LOG_DEBUG(...)
Definition: log.hpp:17
size_t getWidth() const
Definition: VideoFrame.hpp:49
void pushFilter(Filter &filter)
Push the given Filter to the graph.
const ICodec & _codec
Codec of the stream on which the filters will be applied.
Definition: FilterGraph.hpp:80
std::string getSampleFormatName(const AVSampleFormat sampleFormat)
Definition: util.cpp:106
AVFrame & getAVFrame()
Definition: Frame.hpp:88
AVFilterGraph * _graph
The graph which holds the filters.
Definition: FilterGraph.hpp:78
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy