Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
F
ffmpeg.wasm-core
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
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Linshizhi
ffmpeg.wasm-core
Commits
5ae35633
Commit
5ae35633
authored
Aug 08, 2013
by
Stefano Sabatini
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lavf/tee: add special select option
parent
e6876c7b
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
64 additions
and
14 deletions
+64
-14
muxers.texi
doc/muxers.texi
+5
-0
tee.c
libavformat/tee.c
+58
-13
version.h
libavformat/version.h
+1
-1
No files found.
doc/muxers.texi
View file @
5ae35633
...
...
@@ -871,6 +871,11 @@ separated by @code{/}. If the stream specifier is not specified, the
bistream filters will be applied to all streams in the output.
Several bitstream filters can be specified, separated by ",".
@item select
Select the streams that should be mapped to the slave output,
specified by a stream specifier. If not specified, this defaults to
all the input streams.
@end table
Example: encode something and both archive it in a WebM file and stream it
...
...
libavformat/tee.c
View file @
5ae35633
...
...
@@ -30,6 +30,10 @@
typedef
struct
{
AVFormatContext
*
avf
;
AVBitStreamFilterContext
**
bsfs
;
///< bitstream filters per stream
/** map from input to output streams indexes,
* disabled output streams are set to -1 */
int
*
stream_map
;
}
TeeSlave
;
typedef
struct
TeeContext
{
...
...
@@ -134,24 +138,54 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
AVDictionary
*
options
=
NULL
;
AVDictionaryEntry
*
entry
;
char
*
filename
;
char
*
format
=
NULL
;
char
*
format
=
NULL
,
*
select
=
NULL
;
AVFormatContext
*
avf2
=
NULL
;
AVStream
*
st
,
*
st2
;
int
stream_count
;
if
((
ret
=
parse_slave_options
(
avf
,
slave
,
&
options
,
&
filename
))
<
0
)
return
ret
;
if
((
entry
=
av_dict_get
(
options
,
"f"
,
NULL
,
0
)))
{
format
=
entry
->
value
;
entry
->
value
=
NULL
;
/* prevent it from being freed */
av_dict_set
(
&
options
,
"f"
,
NULL
,
0
);
}
#define STEAL_OPTION(option, field) do { \
if ((entry = av_dict_get(options, option, NULL, 0))) { \
field = entry->value; \
entry->value = NULL;
/* prevent it from being freed */
\
av_dict_set(&options, option, NULL, 0); \
} \
} while (0)
STEAL_OPTION
(
"f"
,
format
);
STEAL_OPTION
(
"select"
,
select
);
ret
=
avformat_alloc_output_context2
(
&
avf2
,
NULL
,
format
,
filename
);
if
(
ret
<
0
)
goto
end
;
tee_slave
->
stream_map
=
av_calloc
(
avf
->
nb_streams
,
sizeof
(
*
tee_slave
->
stream_map
));
if
(
!
tee_slave
->
stream_map
)
{
ret
=
AVERROR
(
ENOMEM
);
goto
end
;
}
stream_count
=
0
;
for
(
i
=
0
;
i
<
avf
->
nb_streams
;
i
++
)
{
st
=
avf
->
streams
[
i
];
if
(
select
)
{
ret
=
avformat_match_stream_specifier
(
avf
,
avf
->
streams
[
i
],
select
);
if
(
ret
<
0
)
{
av_log
(
avf
,
AV_LOG_ERROR
,
"Invalid stream specifier '%s' for output '%s'
\n
"
,
select
,
slave
);
goto
end
;
}
if
(
ret
==
0
)
{
/* no match */
tee_slave
->
stream_map
[
i
]
=
-
1
;
continue
;
}
}
tee_slave
->
stream_map
[
i
]
=
stream_count
++
;
if
(
!
(
st2
=
avformat_new_stream
(
avf2
,
NULL
)))
{
ret
=
AVERROR
(
ENOMEM
);
goto
end
;
...
...
@@ -266,6 +300,7 @@ static void close_slaves(AVFormatContext *avf)
bsf
=
bsf_next
;
}
}
av_freep
(
&
tee
->
slaves
[
i
].
stream_map
);
avio_close
(
avf2
->
pb
);
avf2
->
pb
=
NULL
;
...
...
@@ -329,6 +364,15 @@ static int tee_write_header(AVFormatContext *avf)
}
tee
->
nb_slaves
=
nb_slaves
;
for
(
i
=
0
;
i
<
avf
->
nb_streams
;
i
++
)
{
int
j
,
mapped
=
0
;
for
(
j
=
0
;
j
<
tee
->
nb_slaves
;
j
++
)
mapped
+=
tee
->
slaves
[
j
].
stream_map
[
i
]
>=
0
;
if
(
!
mapped
)
av_log
(
avf
,
AV_LOG_WARNING
,
"Input stream #%d is not mapped "
"to any slave.
\n
"
,
i
);
}
return
0
;
fail:
...
...
@@ -408,29 +452,30 @@ static int tee_write_packet(AVFormatContext *avf, AVPacket *pkt)
AVPacket
pkt2
;
int
ret_all
=
0
,
ret
;
unsigned
i
,
s
;
int
s2
;
AVRational
tb
,
tb2
;
for
(
i
=
0
;
i
<
tee
->
nb_slaves
;
i
++
)
{
avf2
=
tee
->
slaves
[
i
].
avf
;
s
=
pkt
->
stream_index
;
if
(
s
>=
avf2
->
nb_streams
)
{
if
(
!
ret_all
)
ret_all
=
AVERROR
(
EINVAL
);
s2
=
tee
->
slaves
[
i
].
stream_map
[
s
];
if
(
s2
<
0
)
continue
;
}
if
((
ret
=
av_copy_packet
(
&
pkt2
,
pkt
))
<
0
||
(
ret
=
av_dup_packet
(
&
pkt2
))
<
0
)
if
(
!
ret_all
)
{
ret
=
ret_all
;
continue
;
}
tb
=
avf
->
streams
[
s
]
->
time_base
;
tb2
=
avf2
->
streams
[
s
]
->
time_base
;
tb
=
avf
->
streams
[
s
]
->
time_base
;
tb2
=
avf2
->
streams
[
s
2
]
->
time_base
;
pkt2
.
pts
=
av_rescale_q
(
pkt
->
pts
,
tb
,
tb2
);
pkt2
.
dts
=
av_rescale_q
(
pkt
->
dts
,
tb
,
tb2
);
pkt2
.
duration
=
av_rescale_q
(
pkt
->
duration
,
tb
,
tb2
);
pkt2
.
stream_index
=
s2
;
filter_packet
(
avf2
,
&
pkt2
,
avf2
,
tee
->
slaves
[
i
].
bsfs
[
s
]);
filter_packet
(
avf2
,
&
pkt2
,
avf2
,
tee
->
slaves
[
i
].
bsfs
[
s
2
]);
if
((
ret
=
av_interleaved_write_frame
(
avf2
,
&
pkt2
))
<
0
)
if
(
!
ret_all
)
ret_all
=
ret
;
...
...
libavformat/version.h
View file @
5ae35633
...
...
@@ -31,7 +31,7 @@
#define LIBAVFORMAT_VERSION_MAJOR 55
#define LIBAVFORMAT_VERSION_MINOR 14
#define LIBAVFORMAT_VERSION_MICRO 10
0
#define LIBAVFORMAT_VERSION_MICRO 10
1
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
LIBAVFORMAT_VERSION_MINOR, \
...
...
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