Skip to content
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audio buffer support in filter graph #389

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
fee765a
Respect detected include paths in feature detection function
egao1980 Sep 23, 2018
d9d340f
Add audio buffer support
egao1980 Sep 23, 2018
9a96a4a
Fix feature detection
egao1980 Sep 23, 2018
324a0be
Add channels option
egao1980 Sep 23, 2018
7e82484
Set channels to nb_channels to respect Frame contract
egao1980 Sep 23, 2018
bb9600f
Add all known formats for ndarray conversion
egao1980 Sep 23, 2018
f2b29bd
Fix continuation style
egao1980 Sep 29, 2018
d40b975
Sort imports
egao1980 Sep 29, 2018
cbda6a4
Merge branch 'develop' into audio-filters
egao1980 Oct 29, 2018
5c7a8df
Merge with the recent AudioFrame changes
egao1980 Oct 29, 2018
2f240eb
Fix abuffer configuration:
egao1980 Oct 29, 2018
ed96cc9
Reorganize imports
egao1980 Oct 29, 2018
f40c068
Add / fix documentation
egao1980 Dec 5, 2018
44abf1f
Add / fix documentation
egao1980 Dec 5, 2018
0b5809c
Push either AudioFrame or VideoFrame, fix error message for unknown f…
egao1980 Dec 5, 2018
8f0e8f7
Make example compatible with 2.7
egao1980 Dec 5, 2018
0dfaf50
Merge branch 'develop' of https://github.com/mikeboers/PyAV into audi…
egao1980 Jun 1, 2019
3fa7abe
Sort imports
egao1980 Jun 1, 2019
6e13ad4
Fix pep8 warning
egao1980 Jun 1, 2019
3e9645c
Fix isort test
egao1980 Jun 1, 2019
26cd084
Run example with the default duration of 1 sec
egao1980 Jun 11, 2019
14781c8
Merge remote-tracking branch 'origin/audio-filters' into audio-filter…
egao1980 Jun 11, 2019
2e0306b
Merge branch 'develop' of github.com:mikeboers/PyAV into audio-filters
egao1980 Jul 23, 2019
8b55ac7
Correct error codes handling for pulling frames through graph
egao1980 Jul 23, 2019
9517bfc
Fix indentation
egao1980 Jul 23, 2019
f723fad
Fix imports formatting
egao1980 Jul 23, 2019
5e2b50e
Add unit tests for abuffer and audio filters
egao1980 Jul 24, 2019
38d4b64
Fix isort issue
egao1980 Jul 24, 2019
f1294cf
Fix isort issue, mk II
egao1980 Jul 24, 2019
f3ac206
Create venv on MacOS X to fix the build
egao1980 Jul 27, 2019
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
9 changes: 9 additions & 0 deletions av/audio/frame.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ cdef class AudioFrame(Frame):
self.layout = get_audio_layout(0, self.ptr.channel_layout)
self.format = get_audio_format(<lib.AVSampleFormat>self.ptr.format)
self.nb_channels = lib.av_get_channel_layout_nb_channels(self.ptr.channel_layout)
self.ptr.channels = self.nb_channels
egao1980 marked this conversation as resolved.
Show resolved Hide resolved
self.nb_planes = self.nb_channels if lib.av_sample_fmt_is_planar(<lib.AVSampleFormat>self.ptr.format) else 1
self._init_planes(AudioPlane)

Expand Down Expand Up @@ -130,8 +131,16 @@ cdef class AudioFrame(Frame):
# map avcodec type to numpy type
try:
dtype = np.dtype({
'u8' : 'u1',
'u8p' : 'u1',
's16' :'<i2',
's16p':'<i2',
's32' :'<i4',
's32p':'<i4',
'flt' :'<f4',
'fltp':'<f4',
'dbl' :'<f8',
egao1980 marked this conversation as resolved.
Show resolved Hide resolved
'dblp':'<f8'
}[self.format.name])
except:
raise AssertionError("Don't know how to convert data type.", self.format.name)
Expand Down
38 changes: 38 additions & 0 deletions av/filter/graph.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ from av.filter.filter cimport Filter, wrap_filter
from av.utils cimport err_check
from av.video.frame cimport VideoFrame, alloc_video_frame
from av.video.format cimport VideoFormat
from av.audio.frame cimport AudioFrame, alloc_audio_frame
egao1980 marked this conversation as resolved.
Show resolved Hide resolved
from av.audio.format cimport AudioFormat

cdef class Graph(object):

Expand Down Expand Up @@ -143,10 +145,46 @@ cdef class Graph(object):

return self.add('buffer', args, name=name)

def add_abuffer(self, template=None, sample_rate=None, format=None, layout=None, channels=None, name=None):
egao1980 marked this conversation as resolved.
Show resolved Hide resolved
"""
Convenient method for adding `abuffer <https://ffmpeg.org/ffmpeg-filters.html#abuffer>`_.
egao1980 marked this conversation as resolved.
Show resolved Hide resolved
"""

if template is not None:
if sample_rate is None:
sample_rate = template.sample_rate
if format is None:
format = template.format
if layout is None:
layout = template.layout.name
if channels is None:
channels = template.channels

if sample_rate is None:
raise ValueError('missing sample_rate')
if format is None:
raise ValueError('missing format')
if layout is None:
raise ValueError('missing layout')
if channels is None:
raise ValueError('missing channels')

args = "sample_rate=%d:sample_fmt=%s:channel_layout=%s:channels=%d:time_base=%d/%d" % (
sample_rate, AudioFormat(format).name,
layout,
channels,
1, 1000,
)

return self.add('abuffer', args, name=name)


def push(self, frame):

if isinstance(frame, VideoFrame):
contexts = self._context_by_type.get('buffer', [])
if isinstance(frame, AudioFrame):
egao1980 marked this conversation as resolved.
Show resolved Hide resolved
contexts = self._context_by_type.get('abuffer', [])
else:
raise ValueError('can only push VideoFrame', type(frame))

Expand Down
38 changes: 19 additions & 19 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,10 @@ def compile_check(code, name, includes=None, include_dirs=None, libraries=None,
try:
objects = cc.compile([source_path], include_dirs=include_dirs)
if link:
cc.link_executable(objects, exec_path, libraries=libraries,
library_dirs=library_dirs, runtime_library_dirs=runtime_library_dirs)
egao1980 marked this conversation as resolved.
Show resolved Hide resolved
cc.link_executable(objects, exec_path,
libraries=libraries,
library_dirs=library_dirs,
runtime_library_dirs=runtime_library_dirs)
except (CompileError, LinkError, TypeError):
res = False
else:
Expand Down Expand Up @@ -540,6 +542,17 @@ def run(self):
config['libraries'] += self.libraries
config['library_dirs'] += self.library_dirs

compile_options = dict(
includes=reflection_includes,
libraries=config['libraries'],
library_dirs=config['library_dirs'],
include_dirs=config['include_dirs'],
runtime_library_dirs=config['runtime_library_dirs'],
compiler=self.compiler,
force=self.force,
verbose=self.debug,
)

# Check for some specific functions.
for func_name in (

Expand All @@ -557,13 +570,8 @@ def run(self):
print("looking for %s... " % func_name, end='\n' if self.debug else '')
results[func_name] = compile_check(
name=os.path.join(tmp_dir, func_name),
code='%s()' % func_name,
libraries=config['libraries'],
library_dirs=config['library_dirs'],
runtime_library_dirs=config['runtime_library_dirs'],
compiler=self.compiler,
force=self.force,
verbose=self.debug,
code='typedef void void_f(void); void_f *foo = *%s;' % func_name,
**compile_options
)
print('found' if results[func_name] else 'missing')

Expand All @@ -579,12 +587,8 @@ def run(self):
results[enum_name] = compile_check(
name=os.path.join(tmp_dir, enum_name),
code='int x = %s' % enum_name,
includes=reflection_includes,
include_dirs=config['include_dirs'],
link=False,
compiler=self.compiler,
force=self.force,
verbose=self.debug,
**compile_options
)
print("found" if results[enum_name] else "missing")

Expand All @@ -602,12 +606,8 @@ def run(self):
results[name] = compile_check(
name=os.path.join(tmp_dir, name),
code='struct %s x; x.%s;' % (struct_name, member_name),
includes=reflection_includes,
include_dirs=config['include_dirs'],
link=False,
compiler=self.compiler,
force=self.force,
verbose=self.debug,
**compile_options
)
print('found' if results[name] else 'missing')

Expand Down