Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
F
ffmpeg
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
ffmpeg
Commits
b6afb2dd
Commit
b6afb2dd
authored
Jan 02, 2013
by
Nicolas George
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavfi: support unknown channel layouts.
parent
fccd8c21
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
184 additions
and
19 deletions
+184
-19
audio.c
libavfilter/audio.c
+1
-1
avcodec.c
libavfilter/avcodec.c
+0
-3
avfiltergraph.c
libavfilter/avfiltergraph.c
+79
-6
formats.c
libavfilter/formats.c
+73
-9
formats.h
libavfilter/formats.h
+31
-0
No files found.
libavfilter/audio.c
View file @
b6afb2dd
...
@@ -44,7 +44,7 @@ AVFilterBufferRef *ff_default_get_audio_buffer(AVFilterLink *link, int perms,
...
@@ -44,7 +44,7 @@ AVFilterBufferRef *ff_default_get_audio_buffer(AVFilterLink *link, int perms,
AVFilterBufferRef
*
samplesref
=
NULL
;
AVFilterBufferRef
*
samplesref
=
NULL
;
uint8_t
**
data
;
uint8_t
**
data
;
int
planar
=
av_sample_fmt_is_planar
(
link
->
format
);
int
planar
=
av_sample_fmt_is_planar
(
link
->
format
);
int
nb_channels
=
av_get_channel_layout_nb_channels
(
link
->
channel_layout
)
;
int
nb_channels
=
link
->
channels
;
int
planes
=
planar
?
nb_channels
:
1
;
int
planes
=
planar
?
nb_channels
:
1
;
int
linesize
;
int
linesize
;
int
full_perms
=
AV_PERM_READ
|
AV_PERM_WRITE
|
AV_PERM_PRESERVE
|
int
full_perms
=
AV_PERM_READ
|
AV_PERM_WRITE
|
AV_PERM_PRESERVE
|
...
...
libavfilter/avcodec.c
View file @
b6afb2dd
...
@@ -96,9 +96,6 @@ AVFilterBufferRef *avfilter_get_audio_buffer_ref_from_frame(const AVFrame *frame
...
@@ -96,9 +96,6 @@ AVFilterBufferRef *avfilter_get_audio_buffer_ref_from_frame(const AVFrame *frame
int
channels
=
av_frame_get_channels
(
frame
);
int
channels
=
av_frame_get_channels
(
frame
);
int64_t
layout
=
av_frame_get_channel_layout
(
frame
);
int64_t
layout
=
av_frame_get_channel_layout
(
frame
);
if
(
av_frame_get_channels
(
frame
)
>
8
)
// libavfilter does not suport more than 8 channels FIXME, remove once libavfilter is fixed
return
NULL
;
if
(
layout
&&
av_get_channel_layout_nb_channels
(
layout
)
!=
av_frame_get_channels
(
frame
))
{
if
(
layout
&&
av_get_channel_layout_nb_channels
(
layout
)
!=
av_frame_get_channels
(
frame
))
{
av_log
(
0
,
AV_LOG_ERROR
,
"Layout indicates a different number of channels than actually present
\n
"
);
av_log
(
0
,
AV_LOG_ERROR
,
"Layout indicates a different number of channels than actually present
\n
"
);
return
NULL
;
return
NULL
;
...
...
libavfilter/avfiltergraph.c
View file @
b6afb2dd
...
@@ -185,9 +185,24 @@ AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name)
...
@@ -185,9 +185,24 @@ AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name)
return
NULL
;
return
NULL
;
}
}
static
void
sanitize_channel_layouts
(
void
*
log
,
AVFilterChannelLayouts
*
l
)
{
if
(
!
l
)
return
;
if
(
l
->
nb_channel_layouts
)
{
if
(
l
->
all_layouts
||
l
->
all_counts
)
av_log
(
log
,
AV_LOG_WARNING
,
"All layouts set on non-empty list
\n
"
);
l
->
all_layouts
=
l
->
all_counts
=
0
;
}
else
{
if
(
l
->
all_counts
&&
!
l
->
all_layouts
)
av_log
(
log
,
AV_LOG_WARNING
,
"All counts without all layouts
\n
"
);
l
->
all_layouts
=
1
;
}
}
static
int
filter_query_formats
(
AVFilterContext
*
ctx
)
static
int
filter_query_formats
(
AVFilterContext
*
ctx
)
{
{
int
ret
;
int
ret
,
i
;
AVFilterFormats
*
formats
;
AVFilterFormats
*
formats
;
AVFilterChannelLayouts
*
chlayouts
;
AVFilterChannelLayouts
*
chlayouts
;
AVFilterFormats
*
samplerates
;
AVFilterFormats
*
samplerates
;
...
@@ -201,6 +216,11 @@ static int filter_query_formats(AVFilterContext *ctx)
...
@@ -201,6 +216,11 @@ static int filter_query_formats(AVFilterContext *ctx)
return
ret
;
return
ret
;
}
}
for
(
i
=
0
;
i
<
ctx
->
nb_inputs
;
i
++
)
sanitize_channel_layouts
(
ctx
,
ctx
->
inputs
[
i
]
->
out_channel_layouts
);
for
(
i
=
0
;
i
<
ctx
->
nb_outputs
;
i
++
)
sanitize_channel_layouts
(
ctx
,
ctx
->
outputs
[
i
]
->
in_channel_layouts
);
formats
=
ff_all_formats
(
type
);
formats
=
ff_all_formats
(
type
);
if
(
!
formats
)
if
(
!
formats
)
return
AVERROR
(
ENOMEM
);
return
AVERROR
(
ENOMEM
);
...
@@ -470,7 +490,7 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref)
...
@@ -470,7 +490,7 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref)
link
->
in_samplerates
->
format_count
=
1
;
link
->
in_samplerates
->
format_count
=
1
;
link
->
sample_rate
=
link
->
in_samplerates
->
formats
[
0
];
link
->
sample_rate
=
link
->
in_samplerates
->
formats
[
0
];
if
(
!
link
->
in_channel_layouts
->
nb_channe
l_layouts
)
{
if
(
link
->
in_channel_layouts
->
al
l_layouts
)
{
av_log
(
link
->
src
,
AV_LOG_ERROR
,
"Cannot select channel layout for"
av_log
(
link
->
src
,
AV_LOG_ERROR
,
"Cannot select channel layout for"
"the link between filters %s and %s.
\n
"
,
link
->
src
->
name
,
"the link between filters %s and %s.
\n
"
,
link
->
src
->
name
,
link
->
dst
->
name
);
link
->
dst
->
name
);
...
@@ -478,7 +498,10 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref)
...
@@ -478,7 +498,10 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref)
}
}
link
->
in_channel_layouts
->
nb_channel_layouts
=
1
;
link
->
in_channel_layouts
->
nb_channel_layouts
=
1
;
link
->
channel_layout
=
link
->
in_channel_layouts
->
channel_layouts
[
0
];
link
->
channel_layout
=
link
->
in_channel_layouts
->
channel_layouts
[
0
];
link
->
channels
=
av_get_channel_layout_nb_channels
(
link
->
channel_layout
);
if
((
link
->
channels
=
FF_LAYOUT2COUNT
(
link
->
channel_layout
)))
link
->
channel_layout
=
0
;
else
link
->
channels
=
av_get_channel_layout_nb_channels
(
link
->
channel_layout
);
}
}
ff_formats_unref
(
&
link
->
in_formats
);
ff_formats_unref
(
&
link
->
in_formats
);
...
@@ -534,8 +557,42 @@ static int reduce_formats_on_filter(AVFilterContext *filter)
...
@@ -534,8 +557,42 @@ static int reduce_formats_on_filter(AVFilterContext *filter)
format_count
,
ff_add_format
);
format_count
,
ff_add_format
);
REDUCE_FORMATS
(
int
,
AVFilterFormats
,
samplerates
,
formats
,
REDUCE_FORMATS
(
int
,
AVFilterFormats
,
samplerates
,
formats
,
format_count
,
ff_add_format
);
format_count
,
ff_add_format
);
REDUCE_FORMATS
(
uint64_t
,
AVFilterChannelLayouts
,
channel_layouts
,
channel_layouts
,
nb_channel_layouts
,
ff_add_channel_layout
);
/* reduce channel layouts */
for
(
i
=
0
;
i
<
filter
->
nb_inputs
;
i
++
)
{
AVFilterLink
*
inlink
=
filter
->
inputs
[
i
];
uint64_t
fmt
;
if
(
!
inlink
->
out_channel_layouts
||
inlink
->
out_channel_layouts
->
nb_channel_layouts
!=
1
)
continue
;
fmt
=
inlink
->
out_channel_layouts
->
channel_layouts
[
0
];
for
(
j
=
0
;
j
<
filter
->
nb_outputs
;
j
++
)
{
AVFilterLink
*
outlink
=
filter
->
outputs
[
j
];
AVFilterChannelLayouts
*
fmts
;
fmts
=
outlink
->
in_channel_layouts
;
if
(
inlink
->
type
!=
outlink
->
type
||
fmts
->
nb_channel_layouts
==
1
)
continue
;
if
(
fmts
->
all_layouts
)
{
/* Turn the infinite list into a singleton */
fmts
->
all_layouts
=
fmts
->
all_counts
=
0
;
ff_add_channel_layout
(
&
outlink
->
in_channel_layouts
,
fmt
);
break
;
}
for
(
k
=
0
;
k
<
outlink
->
in_channel_layouts
->
nb_channel_layouts
;
k
++
)
{
if
(
fmts
->
channel_layouts
[
k
]
==
fmt
)
{
fmts
->
channel_layouts
[
0
]
=
fmt
;
fmts
->
nb_channel_layouts
=
1
;
ret
=
1
;
break
;
}
}
}
}
return
ret
;
return
ret
;
}
}
...
@@ -663,7 +720,23 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter)
...
@@ -663,7 +720,23 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter)
int
out_channels
=
av_get_channel_layout_nb_channels
(
out_chlayout
);
int
out_channels
=
av_get_channel_layout_nb_channels
(
out_chlayout
);
int
count_diff
=
out_channels
-
in_channels
;
int
count_diff
=
out_channels
-
in_channels
;
int
matched_channels
,
extra_channels
;
int
matched_channels
,
extra_channels
;
int
score
=
0
;
int
score
=
100000
;
if
(
FF_LAYOUT2COUNT
(
in_chlayout
)
||
FF_LAYOUT2COUNT
(
out_chlayout
))
{
/* Compute score in case the input or output layout encodes
a channel count; in this case the score is not altered by
the computation afterwards, as in_chlayout and
out_chlayout have both been set to 0 */
if
(
FF_LAYOUT2COUNT
(
in_chlayout
))
in_channels
=
FF_LAYOUT2COUNT
(
in_chlayout
);
if
(
FF_LAYOUT2COUNT
(
out_chlayout
))
out_channels
=
FF_LAYOUT2COUNT
(
out_chlayout
);
score
-=
10000
+
FFABS
(
out_channels
-
in_channels
)
+
(
in_channels
>
out_channels
?
10000
:
0
);
in_chlayout
=
out_chlayout
=
0
;
/* Let the remaining computation run, even if the score
value is not altered */
}
/* channel substitution */
/* channel substitution */
for
(
k
=
0
;
k
<
FF_ARRAY_ELEMS
(
ch_subst
);
k
++
)
{
for
(
k
=
0
;
k
<
FF_ARRAY_ELEMS
(
ch_subst
);
k
++
)
{
...
...
libavfilter/formats.c
View file @
b6afb2dd
...
@@ -19,6 +19,7 @@
...
@@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
*/
#include "libavutil/avassert.h"
#include "libavutil/channel_layout.h"
#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
#include "libavutil/common.h"
#include "libavutil/eval.h"
#include "libavutil/eval.h"
...
@@ -28,6 +29,8 @@
...
@@ -28,6 +29,8 @@
#include "internal.h"
#include "internal.h"
#include "formats.h"
#include "formats.h"
#define KNOWN(l) (!FF_LAYOUT2COUNT(l))
/* for readability */
/**
/**
* Add all refs from a to ret and destroy a.
* Add all refs from a to ret and destroy a.
*/
*/
...
@@ -136,21 +139,77 @@ AVFilterChannelLayouts *ff_merge_channel_layouts(AVFilterChannelLayouts *a,
...
@@ -136,21 +139,77 @@ AVFilterChannelLayouts *ff_merge_channel_layouts(AVFilterChannelLayouts *a,
AVFilterChannelLayouts
*
b
)
AVFilterChannelLayouts
*
b
)
{
{
AVFilterChannelLayouts
*
ret
=
NULL
;
AVFilterChannelLayouts
*
ret
=
NULL
;
unsigned
a_all
=
a
->
all_layouts
+
a
->
all_counts
;
unsigned
b_all
=
b
->
all_layouts
+
b
->
all_counts
;
int
ret_max
,
ret_nb
=
0
,
i
,
j
,
round
;
if
(
a
==
b
)
return
a
;
if
(
a
==
b
)
return
a
;
if
(
a
->
nb_channel_layouts
&&
b
->
nb_channel_layouts
)
{
/* Put the most generic set in a, to avoid doing everything twice */
MERGE_FORMATS
(
ret
,
a
,
b
,
channel_layouts
,
nb_channel_layouts
,
if
(
a_all
<
b_all
)
{
AVFilterChannelLayouts
,
fail
);
FFSWAP
(
AVFilterChannelLayouts
*
,
a
,
b
);
}
else
if
(
a
->
nb_channel_layouts
)
{
FFSWAP
(
unsigned
,
a_all
,
b_all
);
MERGE_REF
(
a
,
b
,
channel_layouts
,
AVFilterChannelLayouts
,
fail
);
}
ret
=
a
;
if
(
a_all
)
{
}
else
{
if
(
a_all
==
1
&&
!
b_all
)
{
/* keep only known layouts in b; works also for b_all = 1 */
for
(
i
=
j
=
0
;
i
<
b
->
nb_channel_layouts
;
i
++
)
if
(
KNOWN
(
b
->
channel_layouts
[
i
]))
b
->
channel_layouts
[
j
++
]
=
b
->
channel_layouts
[
i
];
b
->
nb_channel_layouts
=
j
;
}
MERGE_REF
(
b
,
a
,
channel_layouts
,
AVFilterChannelLayouts
,
fail
);
MERGE_REF
(
b
,
a
,
channel_layouts
,
AVFilterChannelLayouts
,
fail
);
ret
=
b
;
ret
urn
b
;
}
}
ret_max
=
a
->
nb_channel_layouts
+
b
->
nb_channel_layouts
;
if
(
!
(
ret
=
av_mallocz
(
sizeof
(
*
ret
)))
||
!
(
ret
->
channel_layouts
=
av_malloc
(
sizeof
(
*
ret
->
channel_layouts
)
*
ret_max
)))
goto
fail
;
/* a[known] intersect b[known] */
for
(
i
=
0
;
i
<
a
->
nb_channel_layouts
;
i
++
)
{
if
(
!
KNOWN
(
a
->
channel_layouts
[
i
]))
continue
;
for
(
j
=
0
;
j
<
b
->
nb_channel_layouts
;
j
++
)
{
if
(
a
->
channel_layouts
[
i
]
==
b
->
channel_layouts
[
j
])
{
ret
->
channel_layouts
[
ret_nb
++
]
=
a
->
channel_layouts
[
i
];
a
->
channel_layouts
[
i
]
=
b
->
channel_layouts
[
j
]
=
0
;
}
}
}
/* 1st round: a[known] intersect b[generic]
2nd round: a[generic] intersect b[known] */
for
(
round
=
0
;
round
<
2
;
round
++
)
{
for
(
i
=
0
;
i
<
a
->
nb_channel_layouts
;
i
++
)
{
uint64_t
fmt
=
a
->
channel_layouts
[
i
],
bfmt
;
if
(
!
fmt
||
!
KNOWN
(
fmt
))
continue
;
bfmt
=
FF_COUNT2LAYOUT
(
av_get_channel_layout_nb_channels
(
fmt
));
for
(
j
=
0
;
j
<
b
->
nb_channel_layouts
;
j
++
)
if
(
b
->
channel_layouts
[
j
]
==
bfmt
)
ret
->
channel_layouts
[
ret_nb
++
]
=
a
->
channel_layouts
[
i
];
}
/* 1st round: swap to prepare 2nd round; 2nd round: put it back */
FFSWAP
(
AVFilterChannelLayouts
*
,
a
,
b
);
}
/* a[generic] intersect b[generic] */
for
(
i
=
0
;
i
<
a
->
nb_channel_layouts
;
i
++
)
{
if
(
KNOWN
(
a
->
channel_layouts
[
i
]))
continue
;
for
(
j
=
0
;
j
<
b
->
nb_channel_layouts
;
j
++
)
if
(
a
->
channel_layouts
[
i
]
==
b
->
channel_layouts
[
j
])
ret
->
channel_layouts
[
ret_nb
++
]
=
a
->
channel_layouts
[
i
];
}
ret
->
nb_channel_layouts
=
ret_nb
;
if
(
!
ret
->
nb_channel_layouts
)
goto
fail
;
MERGE_REF
(
ret
,
a
,
channel_layouts
,
AVFilterChannelLayouts
,
fail
);
MERGE_REF
(
ret
,
b
,
channel_layouts
,
AVFilterChannelLayouts
,
fail
);
return
ret
;
return
ret
;
fail:
fail:
if
(
ret
)
{
if
(
ret
)
{
av_freep
(
&
ret
->
refs
);
av_freep
(
&
ret
->
refs
);
...
@@ -248,17 +307,19 @@ do { \
...
@@ -248,17 +307,19 @@ do { \
\
\
(*f)->list = fmts; \
(*f)->list = fmts; \
(*f)->list[(*f)->nb++] = fmt; \
(*f)->list[(*f)->nb++] = fmt; \
return 0; \
} while (0)
} while (0)
int
ff_add_format
(
AVFilterFormats
**
avff
,
int64_t
fmt
)
int
ff_add_format
(
AVFilterFormats
**
avff
,
int64_t
fmt
)
{
{
ADD_FORMAT
(
avff
,
fmt
,
int
,
formats
,
format_count
);
ADD_FORMAT
(
avff
,
fmt
,
int
,
formats
,
format_count
);
return
0
;
}
}
int
ff_add_channel_layout
(
AVFilterChannelLayouts
**
l
,
uint64_t
channel_layout
)
int
ff_add_channel_layout
(
AVFilterChannelLayouts
**
l
,
uint64_t
channel_layout
)
{
{
av_assert1
(
!
(
*
l
&&
(
*
l
)
->
all_layouts
));
ADD_FORMAT
(
l
,
channel_layout
,
uint64_t
,
channel_layouts
,
nb_channel_layouts
);
ADD_FORMAT
(
l
,
channel_layout
,
uint64_t
,
channel_layouts
,
nb_channel_layouts
);
return
0
;
}
}
AVFilterFormats
*
ff_all_formats
(
enum
AVMediaType
type
)
AVFilterFormats
*
ff_all_formats
(
enum
AVMediaType
type
)
...
@@ -309,6 +370,9 @@ AVFilterFormats *ff_all_samplerates(void)
...
@@ -309,6 +370,9 @@ AVFilterFormats *ff_all_samplerates(void)
AVFilterChannelLayouts
*
ff_all_channel_layouts
(
void
)
AVFilterChannelLayouts
*
ff_all_channel_layouts
(
void
)
{
{
AVFilterChannelLayouts
*
ret
=
av_mallocz
(
sizeof
(
*
ret
));
AVFilterChannelLayouts
*
ret
=
av_mallocz
(
sizeof
(
*
ret
));
if
(
!
ret
)
return
NULL
;
ret
->
all_layouts
=
1
;
return
ret
;
return
ret
;
}
}
...
...
libavfilter/formats.h
View file @
b6afb2dd
...
@@ -69,14 +69,45 @@ struct AVFilterFormats {
...
@@ -69,14 +69,45 @@ struct AVFilterFormats {
struct
AVFilterFormats
***
refs
;
///< references to this list
struct
AVFilterFormats
***
refs
;
///< references to this list
};
};
/**
* A list of supported channel layouts.
*
* The list works the same as AVFilterFormats, except for the following
* differences:
* - A list with all_layouts = 1 means all channel layouts with a known
* disposition; nb_channel_layouts must then be 0.
* - A list with all_counts = 1 means all channel counts, with a known or
* unknown disposition; nb_channel_layouts must then be 0 and all_layouts 1.
* - The list must not contain a layout with a known disposition and a
* channel count with unknown disposition with the same number of channels
* (e.g. AV_CH_LAYOUT_STEREO and FF_COUNT2LAYOUT(2).
*/
typedef
struct
AVFilterChannelLayouts
{
typedef
struct
AVFilterChannelLayouts
{
uint64_t
*
channel_layouts
;
///< list of channel layouts
uint64_t
*
channel_layouts
;
///< list of channel layouts
int
nb_channel_layouts
;
///< number of channel layouts
int
nb_channel_layouts
;
///< number of channel layouts
char
all_layouts
;
///< accept any known channel layout
char
all_counts
;
///< accept any channel layout or count
unsigned
refcount
;
///< number of references to this list
unsigned
refcount
;
///< number of references to this list
struct
AVFilterChannelLayouts
***
refs
;
///< references to this list
struct
AVFilterChannelLayouts
***
refs
;
///< references to this list
}
AVFilterChannelLayouts
;
}
AVFilterChannelLayouts
;
/**
* Encode a channel count as a channel layout.
* FF_COUNT2LAYOUT(c) means any channel layout with c channels, with a known
* or unknown disposition.
* The result is only valid inside AVFilterChannelLayouts and immediately
* related functions.
*/
#define FF_COUNT2LAYOUT(c) (0x8000000000000000ULL | (c))
/**
* Decode a channel count encoded as a channel layout.
* Return 0 if the channel layout was a real one.
*/
#define FF_LAYOUT2COUNT(l) (((l) & 0x8000000000000000ULL) ? \
(int)((l) & 0x7FFFFFFF) : 0)
/**
/**
* Return a channel layouts/samplerates list which contains the intersection of
* Return a channel layouts/samplerates list which contains the intersection of
* the layouts/samplerates of a and b. Also, all the references of a, all the
* the layouts/samplerates of a and b. Also, all the references of a, all the
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment