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

[WIP] add avfilter#180

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
cchampet merged 16 commits intoavTranscoder:developfromcchampet:dev_addAvFilter
Jan 22, 2016
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
16 commits
Select commitHold shift + click to select a range
44b24cd
CMake: added avfilter when build the project
Nov 20, 2015
3d4b67f
Library: added avfilter license
Nov 20, 2015
4b7dc83
Added FilterGraph
Nov 20, 2015
ec6b1de
common: load filters when preloadCodecsAndFormats
Nov 20, 2015
c613802
Merge branch 'develop' of https://github.com/avTranscoder/avTranscode…
Jan 20, 2016
11b72e8
Frame: added isVideo/AudioFrame methods
Jan 21, 2016
bb02458
AudioFrame: added getChannelLayout method
Jan 21, 2016
d441d25
filter: added Filter class
Jan 21, 2016
bec1155
FilterGraph: used Filter class to manage a graph of video/audio filters
Jan 21, 2016
b2b5d0a
StreamTranscoder: added a FilterGraph attribute
Jan 21, 2016
e25fef4
StreamTranscoder: process filtering at each frame when transcode
Jan 21, 2016
00007c9
StreamTranscoder: added getFilterGraph method
Jan 21, 2016
612ac4e
StreamTranscoder: updated doc
Jan 21, 2016
35d273c
filter: added classes to SWIG interface
Jan 21, 2016
1dc1f09
FilterGraph: fixed channel layout value of abuffer
Jan 22, 2016
6371c40
pyTest: added testFilter to check filter classes
Jan 22, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletionssrc/AvTranscoder/Library.cpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,12 +5,14 @@ extern "C" {
#include <libavcodec/version.h>
#include <libswscale/version.h>
#include <libswscale/swscale.h>
#include <libavfilter/version.h>
#ifdef AVTRANSCODER_LIBAV_DEPENDENCY
#include <libavresample/version.h>
#else
#include <libswresample/version.h>
#endif
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
}

#include <cstring>
Expand DownExpand Up@@ -94,6 +96,8 @@ Libraries getLibraries()
#endif
libs.push_back(
Library("swscale", swscale_license(), LIBSWSCALE_VERSION_MAJOR, LIBSWSCALE_VERSION_MINOR, LIBSWSCALE_VERSION_MICRO));
libs.push_back(Library("avfilter", avfilter_license(), LIBAVFILTER_VERSION_MAJOR, LIBAVFILTER_VERSION_MINOR,
LIBAVFILTER_VERSION_MICRO));

return libs;
}
Expand Down
1 change: 1 addition & 0 deletionssrc/AvTranscoder/avTranscoder.i
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -38,5 +38,6 @@
%include "AvTranscoder/transform/transform.i"
%include "AvTranscoder/file/file.i"
%include "AvTranscoder/stat/stat.i"
%include "AvTranscoder/filter/filter.i"
%include "AvTranscoder/transcoder/transcoder.i"
%include "AvTranscoder/reader/reader.i"
2 changes: 2 additions & 0 deletionssrc/AvTranscoder/common.cpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,7 @@

extern "C" {
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
#include <libavutil/error.h>
}

Expand All@@ -15,6 +16,7 @@ namespace avtranscoder
void preloadCodecsAndFormats()
{
av_register_all();
avfilter_register_all();
}

std::string getDescriptionFromErrorCode(const int code)
Expand Down
1 change: 1 addition & 0 deletionssrc/AvTranscoder/data/decoded/AudioFrame.hpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,6 +44,7 @@ class AvExport AudioFrame : public Frame

size_t getSampleRate() const { return av_frame_get_sample_rate(_frame); }
size_t getNbChannels() const { return av_frame_get_channels(_frame); }
size_t getChannelLayout() const { return av_frame_get_channel_layout(_frame); }
AVSampleFormat getSampleFormat() const { return static_cast<AVSampleFormat>(_frame->format); }
size_t getNbSamplesPerChannel() const { return _frame->nb_samples; }
AudioFrameDesc desc() const { return AudioFrameDesc(getSampleRate(), getNbChannels(), getSampleFormat()); }
Expand Down
14 changes: 14 additions & 0 deletionssrc/AvTranscoder/data/decoded/Frame.cpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -80,4 +80,18 @@ void Frame::allocateAVFrame()
throw std::runtime_error("Unable to allocate an empty Frame.");
}
}

bool Frame::isAudioFrame() const
{
if(_frame->sample_rate && _frame->channels && _frame->channel_layout && _frame->format != -1)
return true;
return false;
}

bool Frame::isVideoFrame() const
{
if(_frame->width && _frame->height && _frame->format != -1)
return true;
return false;
}
}
12 changes: 12 additions & 0 deletionssrc/AvTranscoder/data/decoded/Frame.hpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -63,6 +63,18 @@ class AvExport Frame
*/
void clear();

/**
* @return If it corresponds to a valid audio frame.
* @see AudioFrame
*/
bool isAudioFrame() const;

/**
* @return If it corresponds to a valid video frame.
* @see VideoFrame
*/
bool isVideoFrame() const;

#ifndef SWIG
AVFrame& getAVFrame() { return *_frame; }
const AVFrame& getAVFrame() const { return *_frame; }
Expand Down
4 changes: 2 additions & 2 deletionssrc/AvTranscoder/decoder/AudioGenerator.hpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,8 +22,8 @@ class AvExport AudioGenerator : public IDecoder
void setNextFrame(Frame& inputFrame);

private:
Frame* _inputFrame;///< Has link (no ownership)
AudioFrame* _silent;///< The generated silent (has ownership)
Frame* _inputFrame; ///< Has link (no ownership)
AudioFrame* _silent; ///< The generated silent (has ownership)
};
}

Expand Down
37 changes: 37 additions & 0 deletionssrc/AvTranscoder/filter/Filter.cpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
#include "Filter.hpp"

extern "C" {
#include <libavfilter/avfilter.h>
}

#include <stdexcept>

namespace avtranscoder
{

Filter::Filter(const std::string& name, const std::string& options, const std::string& instanceName)
: _filter(NULL)
, _context(NULL)
, _options(options)
, _instanceName(instanceName.empty() ? name : instanceName)
{
_filter = avfilter_get_by_name(name.c_str());
if(!_filter)
{
std::string msg("Cannot find filter ");
msg += name;
msg += ". It will not be added to the filter graph.";
throw std::runtime_error(msg);
}
}

Filter::~Filter()
{
avfilter_free(_context);
}

std::string Filter::getName() const
{
return _filter->name ? std::string(_filter->name) : "";
}
}
40 changes: 40 additions & 0 deletionssrc/AvTranscoder/filter/Filter.hpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
#ifndef _AV_TRANSCODER_FILTER_FILTER_HPP_
#define _AV_TRANSCODER_FILTER_FILTER_HPP_

#include <AvTranscoder/common.hpp>

struct AVFilter;
struct AVFilterContext;

namespace avtranscoder
{

/**
* @brief Describe a filter and its options.
**/
class AvExport Filter
{
public:
Filter(const std::string& name, const std::string& options = "", const std::string& instanceName = "");
~Filter();

std::string getName() const;
std::string getOptions() const { return _options; }
std::string getInstanceName() const { return _instanceName; }

#ifndef SWIG
AVFilter& getAVFilter() { return *_filter; }
AVFilterContext* getAVFilterContext() { return _context; }

void setAVFilterContext(AVFilterContext* newContext) { _context = newContext; }
#endif

private:
AVFilter* _filter;
AVFilterContext* _context;
std::string _options;
std::string _instanceName;
};
}

#endif
184 changes: 184 additions & 0 deletionssrc/AvTranscoder/filter/FilterGraph.cpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
#include "FilterGraph.hpp"

#include <AvTranscoder/util.hpp>
#include <AvTranscoder/data/decoded/AudioFrame.hpp>
#include <AvTranscoder/data/decoded/VideoFrame.hpp>

extern "C" {
#include <libavfilter/avfilter.h>
#include <libavfilter/buffersrc.h>
#include <libavfilter/buffersink.h>
}

#include <stdexcept>
#include <sstream>

namespace avtranscoder
{

FilterGraph::FilterGraph(const ICodec& codec)
: _graph(avfilter_graph_alloc())
, _filters()
, _codec(codec)
, _isInit(false)
{
if(!_graph)
throw std::runtime_error("Unable to create filter graph: out of memory.");
}

FilterGraph::~FilterGraph()
{
for(std::vector<Filter*>::iterator it = _filters.begin(); it < _filters.end(); ++it)
{
it = _filters.erase(it);
}
avfilter_graph_free(&_graph);
}

void FilterGraph::process(Frame& frame)
{
if(!hasFilters())
{
LOG_DEBUG("No filter to process.")
return;
}

// init filter graph
if(!_isInit)
init(frame);

// setup source frame
int ret = av_buffersrc_write_frame(_filters.at(0)->getAVFilterContext(), &frame.getAVFrame());
if(ret < 0)
{
throw std::runtime_error("Error when adding a frame to the source buffer used to start to process filters: " +
getDescriptionFromErrorCode(ret));
}

// pull filtered data from the filter graph
for(;;)
{
ret = av_buffersink_get_frame(_filters.at(_filters.size() - 1)->getAVFilterContext(), &frame.getAVFrame());
if(ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
break;
if(ret < 0)
{
throw std::runtime_error("Error reading buffer from buffersink: " + getDescriptionFromErrorCode(ret));
}
}
}

Filter& FilterGraph::addFilter(const std::string& filterName, const std::string& filterOptions,
const std::string& instanceName)
{
LOG_INFO("Add filter " << filterName << " to the graph.")
Filter* filter = new Filter(filterName, filterOptions, instanceName);
_filters.push_back(filter);
return *_filters.back();
}

void FilterGraph::init(const Frame& frame)
{
// push filters to the graph
pushInBuffer(frame);
for(size_t i = 1; i < _filters.size(); ++i)
{
pushFilter(*_filters.at(i));
}
pushOutBuffer(frame);

// connect filters
for(size_t index = 0; index < _filters.size() - 1; ++index)
{
LOG_INFO("Connect filter " << _filters.at(index)->getName() << " to filter " << _filters.at(index + 1)->getName())
const int err =
avfilter_link(_filters.at(index)->getAVFilterContext(), 0, _filters.at(index + 1)->getAVFilterContext(), 0);
if(err < 0)
{
throw std::runtime_error("Error when connecting filters.");
}
}

// configuring the graph
LOG_INFO("Configuring filter graph.")
const int err = avfilter_graph_config(_graph, NULL);
if(err < 0)
{
throw std::runtime_error("Error configuring the filter graph: " + getDescriptionFromErrorCode(err));
}

_isInit = true;
}

void FilterGraph::pushFilter(Filter& filter)
{
AVFilterContext* context = NULL;
const int err = avfilter_graph_create_filter(&context, &filter.getAVFilter(), filter.getInstanceName().c_str(),
filter.getOptions().c_str(), NULL, _graph);
filter.setAVFilterContext(context);
if(err < 0)
{
std::string msg("Cannot add filter ");
msg += filter.getName();
msg += " (instance=";
msg += filter.getInstanceName();
msg += ") to the graph: ";
msg += getDescriptionFromErrorCode(err);
throw std::runtime_error(msg);
}
}

void FilterGraph::pushInBuffer(const Frame& frame)
{
std::string filterName;
std::stringstream filterOptions;
// audio frame
if(frame.isAudioFrame())
{
filterName = "abuffer";
const AudioFrame& audioFrame = dynamic_cast<const AudioFrame&>(frame);
filterOptions << "time_base=" << _codec.getAVCodecContext().time_base.num << "/"
<< _codec.getAVCodecContext().time_base.den << ":";
filterOptions << "sample_rate=" << audioFrame.getSampleRate() << ":";
filterOptions << "sample_fmt=" << getSampleFormatName(audioFrame.getSampleFormat()) << ":";
filterOptions << "channel_layout=0x" << std::hex << audioFrame.getChannelLayout();
}
// video frame
else if(frame.isVideoFrame())
{
filterName = "buffer";
const VideoFrame& videoFrame = dynamic_cast<const VideoFrame&>(frame);
filterOptions << "video_size=" << videoFrame.getWidth() << "x" << videoFrame.getHeight() << ":";
filterOptions << "pix_fmt=" << getPixelFormatName(videoFrame.getPixelFormat()) << ":";
filterOptions << "time_base=" << _codec.getAVCodecContext().time_base.num << "/"
<< _codec.getAVCodecContext().time_base.den << ":";
filterOptions << "pixel_aspect=" << _codec.getAVCodecContext().sample_aspect_ratio.num << "/"
<< _codec.getAVCodecContext().sample_aspect_ratio.den;
}
// invalid frame
else
throw std::runtime_error("Cannot create input buffer of filter graph: the given frame is invalid.");

// add in buffer
Filter* in = new Filter(filterName, filterOptions.str(), "in");
LOG_INFO("Add filter '" << filterName << "' at the beginning of the graph.")
_filters.insert(_filters.begin(), in);
pushFilter(*in);
}

void FilterGraph::pushOutBuffer(const Frame& frame)
{
std::string filterName;

if(frame.isAudioFrame())
filterName = "abuffersink";
else if(frame.isVideoFrame())
filterName = "buffersink";
else
throw std::runtime_error("Cannot create output buffer of filter graph: the given frame is invalid.");

// add out buffer
Filter& out = addFilter(filterName, "", "out");
pushFilter(out);
}
}
Loading

[8]ページ先頭

©2009-2025 Movatter.jp