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
02e8f032
Commit
02e8f032
authored
Oct 02, 2011
by
Luca Barbato
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
segment: introduce segmented chain muxer
It behaves similarly to image2 muxer
parent
1ee5b5e8
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
308 additions
and
0 deletions
+308
-0
Changelog
Changelog
+1
-0
muxers.texi
doc/muxers.texi
+32
-0
Makefile
libavformat/Makefile
+1
-0
allformats.c
libavformat/allformats.c
+1
-0
segment.c
libavformat/segment.c
+273
-0
No files found.
Changelog
View file @
02e8f032
...
...
@@ -109,6 +109,7 @@ easier to use. The changes are:
- Dxtory capture format decoder
- v410 QuickTime uncompressed 4:4:4 10-bit encoder and decoder
- OpenMG Audio muxer
- Simple segmenting muxer
version 0.7:
...
...
doc/muxers.texi
View file @
02e8f032
...
...
@@ -90,6 +90,7 @@ avconv -i INPUT -c:a pcm_u8 -c:v mpeg2video -f framecrc -
See also the @ref{crc} muxer.
@anchor{image2}
@section image2
Image file muxer.
...
...
@@ -267,4 +268,35 @@ For example a 3D WebM clip can be created using the following command line:
avconv -i sample_left_right_clip.mpg -an -c:v libvpx -metadata STEREO_MODE=left_right -y stereo_clip.webm
@end example
@section segment
Basic stream segmenter.
The segmenter muxer outputs streams to a number of separate files of nearly
fixed duration. Output filename pattern can be set in a fashion similar to
@ref{image2}.
Every segment starts with a video keyframe, if a video stream is present.
The segment muxer works best with a single constant frame rate video.
Optionally it can generate a flat list of the created segments, one segment
per line.
@table @option
@item segment_format @var{format}
Override the inner container format, by default it is guessed by the filename
extension.
@item segment_time @var{t}
Set segment duration to @var{t} seconds.
@item segment_list @var{name}
Generate also a listfile named @var{name}.
@item segment_list_size @var{size}
Overwrite the listfile once it reaches @var{size} entries.
@end table
@example
avconv -i in.mkv -c copy -map 0 -f segment -list out.list out%03d.nut
@end example
@c man end MUXERS
libavformat/Makefile
View file @
02e8f032
...
...
@@ -268,6 +268,7 @@ OBJS-$(CONFIG_SAP_DEMUXER) += sapdec.o
OBJS-$(CONFIG_SAP_MUXER)
+=
sapenc.o
rtpenc_chain.o
OBJS-$(CONFIG_SDP_DEMUXER)
+=
rtsp.o
OBJS-$(CONFIG_SEGAFILM_DEMUXER)
+=
segafilm.o
OBJS-$(CONFIG_SEGMENT_MUXER)
+=
segment.o
OBJS-$(CONFIG_SHORTEN_DEMUXER)
+=
rawdec.o
OBJS-$(CONFIG_SIFF_DEMUXER)
+=
siff.o
OBJS-$(CONFIG_SMACKER_DEMUXER)
+=
smacker.o
...
...
libavformat/allformats.c
View file @
02e8f032
...
...
@@ -197,6 +197,7 @@ void av_register_all(void)
av_register_rdt_dynamic_payload_handlers
();
#endif
REGISTER_DEMUXER
(
SEGAFILM
,
segafilm
);
REGISTER_MUXER
(
SEGMENT
,
segment
);
REGISTER_DEMUXER
(
SHORTEN
,
shorten
);
REGISTER_DEMUXER
(
SIFF
,
siff
);
REGISTER_DEMUXER
(
SMACKER
,
smacker
);
...
...
libavformat/segment.c
0 → 100644
View file @
02e8f032
/*
* Generic segmenter
* Copyright (c) 2011, Luca Barbato
*
* This file is part of Libav.
*
* Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <strings.h>
#include <float.h>
#include "avformat.h"
#include "internal.h"
#include "libavutil/log.h"
#include "libavutil/opt.h"
#include "libavutil/avstring.h"
#include "libavutil/parseutils.h"
#include "libavutil/mathematics.h"
typedef
struct
{
const
AVClass
*
class
;
/**< Class for private options. */
int
number
;
AVFormatContext
*
avf
;
char
*
format
;
/**< Set by a private option. */
char
*
list
;
/**< Set by a private option. */
float
time
;
/**< Set by a private option. */
int
size
;
/**< Set by a private option. */
int64_t
offset_time
;
int64_t
recording_time
;
int
has_video
;
AVIOContext
*
pb
;
}
SegmentContext
;
static
int
segment_start
(
AVFormatContext
*
s
)
{
SegmentContext
*
c
=
s
->
priv_data
;
AVFormatContext
*
oc
=
c
->
avf
;
int
err
=
0
;
if
(
av_get_frame_filename
(
oc
->
filename
,
sizeof
(
oc
->
filename
),
s
->
filename
,
c
->
number
++
)
<
0
)
return
AVERROR
(
EINVAL
);
if
((
err
=
avio_open2
(
&
oc
->
pb
,
oc
->
filename
,
AVIO_FLAG_WRITE
,
&
s
->
interrupt_callback
,
NULL
))
<
0
)
return
err
;
if
(
!
oc
->
priv_data
&&
oc
->
oformat
->
priv_data_size
>
0
)
{
oc
->
priv_data
=
av_mallocz
(
oc
->
oformat
->
priv_data_size
);
if
(
!
oc
->
priv_data
)
{
avio_close
(
oc
->
pb
);
return
AVERROR
(
ENOMEM
);
}
if
(
oc
->
oformat
->
priv_class
)
{
*
(
const
AVClass
**
)
oc
->
priv_data
=
oc
->
oformat
->
priv_class
;
av_opt_set_defaults
(
oc
->
priv_data
);
}
}
if
((
err
=
oc
->
oformat
->
write_header
(
oc
))
<
0
)
{
goto
fail
;
}
return
0
;
fail:
avio_close
(
oc
->
pb
);
av_freep
(
&
oc
->
priv_data
);
return
err
;
}
static
int
segment_end
(
AVFormatContext
*
oc
)
{
int
ret
=
0
;
if
(
oc
->
oformat
->
write_trailer
)
ret
=
oc
->
oformat
->
write_trailer
(
oc
);
avio_close
(
oc
->
pb
);
if
(
oc
->
oformat
->
priv_class
)
av_opt_free
(
oc
->
priv_data
);
av_freep
(
&
oc
->
priv_data
);
return
ret
;
}
static
int
seg_write_header
(
AVFormatContext
*
s
)
{
SegmentContext
*
seg
=
s
->
priv_data
;
AVFormatContext
*
oc
;
int
ret
,
i
;
seg
->
number
=
0
;
seg
->
offset_time
=
0
;
seg
->
recording_time
=
seg
->
time
*
1000000
;
if
(
seg
->
list
)
if
((
ret
=
avio_open2
(
&
seg
->
pb
,
seg
->
list
,
AVIO_FLAG_WRITE
,
&
s
->
interrupt_callback
,
NULL
))
<
0
)
return
ret
;
for
(
i
=
0
;
i
<
s
->
nb_streams
;
i
++
)
seg
->
has_video
+=
(
s
->
streams
[
i
]
->
codec
->
codec_type
==
AVMEDIA_TYPE_VIDEO
);
if
(
seg
->
has_video
>
1
)
av_log
(
s
,
AV_LOG_WARNING
,
"More than a single video stream present, "
"expect issues decoding it.
\n
"
);
oc
=
avformat_alloc_context
();
if
(
!
oc
)
{
ret
=
AVERROR
(
ENOMEM
);
goto
fail
;
}
oc
->
oformat
=
av_guess_format
(
seg
->
format
,
s
->
filename
,
NULL
);
if
(
!
oc
->
oformat
)
{
ret
=
AVERROR_MUXER_NOT_FOUND
;
goto
fail
;
}
if
(
oc
->
oformat
->
flags
&
AVFMT_NOFILE
)
{
av_log
(
s
,
AV_LOG_ERROR
,
"format %s not supported.
\n
"
,
oc
->
oformat
->
name
);
ret
=
AVERROR
(
EINVAL
);
goto
fail
;
}
seg
->
avf
=
oc
;
oc
->
streams
=
s
->
streams
;
oc
->
nb_streams
=
s
->
nb_streams
;
if
(
av_get_frame_filename
(
oc
->
filename
,
sizeof
(
oc
->
filename
),
s
->
filename
,
seg
->
number
++
)
<
0
)
{
ret
=
AVERROR
(
EINVAL
);
goto
fail
;
}
if
((
ret
=
avio_open2
(
&
oc
->
pb
,
oc
->
filename
,
AVIO_FLAG_WRITE
,
&
s
->
interrupt_callback
,
NULL
))
<
0
)
goto
fail
;
if
((
ret
=
avformat_write_header
(
oc
,
NULL
))
<
0
)
{
avio_close
(
oc
->
pb
);
goto
fail
;
}
if
(
seg
->
list
)
{
avio_printf
(
seg
->
pb
,
"%s
\n
"
,
oc
->
filename
);
avio_flush
(
seg
->
pb
);
}
fail:
if
(
ret
)
{
oc
->
streams
=
NULL
;
oc
->
nb_streams
=
0
;
if
(
seg
->
list
)
avio_close
(
seg
->
pb
);
avformat_free_context
(
oc
);
}
return
ret
;
}
static
int
seg_write_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
{
SegmentContext
*
seg
=
s
->
priv_data
;
AVFormatContext
*
oc
=
seg
->
avf
;
AVStream
*
st
=
oc
->
streams
[
pkt
->
stream_index
];
int64_t
end_pts
=
seg
->
recording_time
*
seg
->
number
;
int
ret
;
if
((
seg
->
has_video
&&
st
->
codec
->
codec_type
==
AVMEDIA_TYPE_VIDEO
)
&&
av_compare_ts
(
pkt
->
pts
,
st
->
time_base
,
end_pts
,
AV_TIME_BASE_Q
)
>=
0
&&
pkt
->
flags
&
AV_PKT_FLAG_KEY
)
{
av_log
(
s
,
AV_LOG_DEBUG
,
"Next segment starts at %d %"
PRId64
"
\n
"
,
pkt
->
stream_index
,
pkt
->
pts
);
ret
=
segment_end
(
oc
);
if
(
!
ret
)
ret
=
segment_start
(
s
);
if
(
ret
)
goto
fail
;
if
(
seg
->
list
)
{
avio_printf
(
seg
->
pb
,
"%s
\n
"
,
oc
->
filename
);
avio_flush
(
seg
->
pb
);
if
(
!
(
seg
->
number
%
seg
->
size
))
{
avio_close
(
seg
->
pb
);
if
((
ret
=
avio_open2
(
&
seg
->
pb
,
seg
->
list
,
AVIO_FLAG_WRITE
,
&
s
->
interrupt_callback
,
NULL
))
<
0
)
goto
fail
;
}
}
}
ret
=
oc
->
oformat
->
write_packet
(
oc
,
pkt
);
fail:
if
(
ret
<
0
)
{
oc
->
streams
=
NULL
;
oc
->
nb_streams
=
0
;
if
(
seg
->
list
)
avio_close
(
seg
->
pb
);
avformat_free_context
(
oc
);
}
return
ret
;
}
static
int
seg_write_trailer
(
struct
AVFormatContext
*
s
)
{
SegmentContext
*
seg
=
s
->
priv_data
;
AVFormatContext
*
oc
=
seg
->
avf
;
int
ret
=
segment_end
(
oc
);
if
(
seg
->
list
)
avio_close
(
seg
->
pb
);
oc
->
streams
=
NULL
;
oc
->
nb_streams
=
0
;
avformat_free_context
(
oc
);
return
ret
;
}
#define OFFSET(x) offsetof(SegmentContext, x)
#define E AV_OPT_FLAG_ENCODING_PARAM
static
const
AVOption
options
[]
=
{
{
"segment_format"
,
"container format used for the segments"
,
OFFSET
(
format
),
AV_OPT_TYPE_STRING
,
{.
str
=
NULL
},
0
,
0
,
E
},
{
"segment_time"
,
"segment length in seconds"
,
OFFSET
(
time
),
AV_OPT_TYPE_FLOAT
,
{.
dbl
=
2
},
0
,
FLT_MAX
,
E
},
{
"segment_list"
,
"output the segment list"
,
OFFSET
(
list
),
AV_OPT_TYPE_STRING
,
{.
str
=
NULL
},
0
,
0
,
E
},
{
"segment_list_size"
,
"maximum number of playlist entries"
,
OFFSET
(
size
),
AV_OPT_TYPE_INT
,
{.
dbl
=
5
},
0
,
INT_MAX
,
E
},
{
NULL
},
};
static
const
AVClass
seg_class
=
{
.
class_name
=
"segment muxer"
,
.
item_name
=
av_default_item_name
,
.
option
=
options
,
.
version
=
LIBAVUTIL_VERSION_INT
,
};
AVOutputFormat
ff_segment_muxer
=
{
.
name
=
"segment"
,
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"segment muxer"
),
.
priv_data_size
=
sizeof
(
SegmentContext
),
.
flags
=
AVFMT_GLOBALHEADER
|
AVFMT_NOFILE
,
.
write_header
=
seg_write_header
,
.
write_packet
=
seg_write_packet
,
.
write_trailer
=
seg_write_trailer
,
.
priv_class
=
&
seg_class
,
};
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