segment.c
Go to the documentation of this file.
1 /*
2  * Generic segmenter
3  * Copyright (c) 2011, Luca Barbato
4  *
5  * This file is part of Libav.
6  *
7  * Libav is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * Libav is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include <strings.h>
23 #include <float.h>
24 
25 #include "avformat.h"
26 #include "internal.h"
27 
28 #include "libavutil/log.h"
29 #include "libavutil/opt.h"
30 #include "libavutil/avstring.h"
31 #include "libavutil/parseutils.h"
32 #include "libavutil/mathematics.h"
33 
34 typedef struct {
35  const AVClass *class;
36  int number;
38  char *format;
39  char *list;
40  float time;
41  int size;
42  int64_t offset_time;
43  int64_t recording_time;
44  int has_video;
47 
49 {
50  SegmentContext *c = s->priv_data;
51  AVFormatContext *oc = c->avf;
52  int err = 0;
53 
54  if (av_get_frame_filename(oc->filename, sizeof(oc->filename),
55  s->filename, c->number++) < 0)
56  return AVERROR(EINVAL);
57 
58  if ((err = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
59  &s->interrupt_callback, NULL)) < 0)
60  return err;
61 
62  if (!oc->priv_data && oc->oformat->priv_data_size > 0) {
64  if (!oc->priv_data) {
65  avio_close(oc->pb);
66  return AVERROR(ENOMEM);
67  }
68  if (oc->oformat->priv_class) {
69  *(const AVClass**)oc->priv_data = oc->oformat->priv_class;
71  }
72  }
73 
74  if ((err = oc->oformat->write_header(oc)) < 0) {
75  goto fail;
76  }
77 
78  return 0;
79 
80 fail:
81  avio_close(oc->pb);
82  av_freep(&oc->priv_data);
83 
84  return err;
85 }
86 
88 {
89  int ret = 0;
90 
91  if (oc->oformat->write_trailer)
92  ret = oc->oformat->write_trailer(oc);
93 
94  avio_close(oc->pb);
95  if (oc->oformat->priv_class)
97  av_freep(&oc->priv_data);
98 
99  return ret;
100 }
101 
103 {
104  SegmentContext *seg = s->priv_data;
105  AVFormatContext *oc;
106  int ret, i;
107 
108  seg->number = 0;
109  seg->offset_time = 0;
110  seg->recording_time = seg->time * 1000000;
111 
112  if (seg->list)
113  if ((ret = avio_open2(&seg->pb, seg->list, AVIO_FLAG_WRITE,
114  &s->interrupt_callback, NULL)) < 0)
115  return ret;
116 
117  for (i = 0; i< s->nb_streams; i++)
118  seg->has_video +=
120 
121  if (seg->has_video > 1)
123  "More than a single video stream present, "
124  "expect issues decoding it.\n");
125 
126  oc = avformat_alloc_context();
127 
128  if (!oc) {
129  ret = AVERROR(ENOMEM);
130  goto fail;
131  }
132 
133  oc->oformat = av_guess_format(seg->format, s->filename, NULL);
134 
135  if (!oc->oformat) {
137  goto fail;
138  }
139  if (oc->oformat->flags & AVFMT_NOFILE) {
140  av_log(s, AV_LOG_ERROR, "format %s not supported.\n",
141  oc->oformat->name);
142  ret = AVERROR(EINVAL);
143  goto fail;
144  }
145 
146  seg->avf = oc;
147 
148  oc->streams = s->streams;
149  oc->nb_streams = s->nb_streams;
150 
151  if (av_get_frame_filename(oc->filename, sizeof(oc->filename),
152  s->filename, seg->number++) < 0) {
153  ret = AVERROR(EINVAL);
154  goto fail;
155  }
156 
157  if ((ret = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
158  &s->interrupt_callback, NULL)) < 0)
159  goto fail;
160 
161  if ((ret = avformat_write_header(oc, NULL)) < 0) {
162  avio_close(oc->pb);
163  goto fail;
164  }
165 
166  if (seg->list) {
167  avio_printf(seg->pb, "%s\n", oc->filename);
168  avio_flush(seg->pb);
169  }
170 
171 fail:
172  if (ret) {
173  oc->streams = NULL;
174  oc->nb_streams = 0;
175  if (seg->list)
176  avio_close(seg->pb);
178  }
179  return ret;
180 }
181 
183 {
184  SegmentContext *seg = s->priv_data;
185  AVFormatContext *oc = seg->avf;
186  AVStream *st = oc->streams[pkt->stream_index];
187  int64_t end_pts = seg->recording_time * seg->number;
188  int ret;
189 
190  if ((seg->has_video && st->codec->codec_type == AVMEDIA_TYPE_VIDEO) &&
191  av_compare_ts(pkt->pts, st->time_base,
192  end_pts, AV_TIME_BASE_Q) >= 0 &&
193  pkt->flags & AV_PKT_FLAG_KEY) {
194 
195  av_log(s, AV_LOG_DEBUG, "Next segment starts at %d %"PRId64"\n",
196  pkt->stream_index, pkt->pts);
197 
198  ret = segment_end(oc);
199 
200  if (!ret)
201  ret = segment_start(s);
202 
203  if (ret)
204  goto fail;
205 
206  if (seg->list) {
207  avio_printf(seg->pb, "%s\n", oc->filename);
208  avio_flush(seg->pb);
209  if (!(seg->number % seg->size)) {
210  avio_close(seg->pb);
211  if ((ret = avio_open2(&seg->pb, seg->list, AVIO_FLAG_WRITE,
212  &s->interrupt_callback, NULL)) < 0)
213  goto fail;
214 
215  }
216  }
217  }
218 
219  ret = oc->oformat->write_packet(oc, pkt);
220 
221 fail:
222  if (ret < 0) {
223  oc->streams = NULL;
224  oc->nb_streams = 0;
225  if (seg->list)
226  avio_close(seg->pb);
228  }
229 
230  return ret;
231 }
232 
233 static int seg_write_trailer(struct AVFormatContext *s)
234 {
235  SegmentContext *seg = s->priv_data;
236  AVFormatContext *oc = seg->avf;
237  int ret = segment_end(oc);
238  if (seg->list)
239  avio_close(seg->pb);
240  oc->streams = NULL;
241  oc->nb_streams = 0;
243  return ret;
244 }
245 
246 #define OFFSET(x) offsetof(SegmentContext, x)
247 #define E AV_OPT_FLAG_ENCODING_PARAM
248 static const AVOption options[] = {
249  { "segment_format", "container format used for the segments", OFFSET(format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
250  { "segment_time", "segment length in seconds", OFFSET(time), AV_OPT_TYPE_FLOAT, {.dbl = 2}, 0, FLT_MAX, E },
251  { "segment_list", "output the segment list", OFFSET(list), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
252  { "segment_list_size", "maximum number of playlist entries", OFFSET(size), AV_OPT_TYPE_INT, {.dbl = 5}, 0, INT_MAX, E },
253  { NULL },
254 };
255 
256 static const AVClass seg_class = {
257  .class_name = "segment muxer",
258  .item_name = av_default_item_name,
259  .option = options,
260  .version = LIBAVUTIL_VERSION_INT,
261 };
262 
263 
265  .name = "segment",
266  .long_name = NULL_IF_CONFIG_SMALL("segment muxer"),
267  .priv_data_size = sizeof(SegmentContext),
272  .priv_class = &seg_class,
273 };
static int write_header(AVFormatContext *s)
Definition: assenc.c:28
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:154
AVFormatContext * avf
Definition: segment.c:37
Bytestream IO Context.
Definition: avio.h:68
int size
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1127
AVOption.
Definition: opt.h:244
int avformat_write_header(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and write the stream header to an output media file.
Definition: utils.c:2941
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:117
static int write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: assenc.c:58
void av_opt_set_defaults(void *s)
Set the values of all AVOption fields to their default values.
Definition: opt.c:598
int size
Set by a private option.
Definition: segment.c:41
AVOptions.
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:566
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:954
int(* write_packet)(struct AVFormatContext *, AVPacket *pkt)
Definition: avformat.h:407
static int seg_write_header(AVFormatContext *s)
Definition: segment.c:102
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:147
Format I/O context.
Definition: avformat.h:863
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:38
AVIOContext * pb
Definition: segment.c:45
int flags
can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_RAWPICTURE, AVFMT_GLOBALHEADER, AVFMT_NOTIMESTAMPS, AVFMT_VARIABLE_FPS, AVFMT_NODIMENSIONS, AVFMT_NOSTREAMS
Definition: avformat.h:414
int priv_data_size
size of private data so that it can be allocated in the wrapper
Definition: avformat.h:402
static int seg_write_trailer(struct AVFormatContext *s)
Definition: segment.c:233
AVStream ** streams
Definition: avformat.h:908
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition: options.c:146
int64_t offset_time
Definition: segment.c:42
static int flags
Definition: log.c:34
char * format
Set by a private option.
Definition: segment.c:38
static int write_trailer(AVFormatContext *s)
Definition: assenc.c:67
struct AVOutputFormat * oformat
Definition: avformat.h:877
#define AVERROR(e)
Definition: error.h:43
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:191
int(* write_header)(struct AVFormatContext *)
Definition: avformat.h:406
int avio_close(AVIOContext *s)
Close the resource accessed by the AVIOContext s and free it.
Definition: aviobuf.c:987
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:140
#define OFFSET(x)
Definition: segment.c:246
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:914
int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b)
Compare 2 timestamps each in its own timebases.
Definition: mathematics.c:138
AVCodecContext * codec
codec context
Definition: avformat.h:623
float time
Set by a private option.
Definition: segment.c:40
unsigned int nb_streams
A list of all streams in the file.
Definition: avformat.h:907
int void avio_flush(AVIOContext *s)
Definition: aviobuf.c:205
char filename[1024]
input or output filename
Definition: avformat.h:910
#define time
Definition: internal.h:135
#define AVFMT_GLOBALHEADER
Format wants global header.
Definition: avformat.h:374
const char * name
Definition: avformat.h:390
AVOutputFormat * av_guess_format(const char *short_name, const char *filename, const char *mime_type)
Return the output format in the list of registered output formats which best matches the provided par...
Definition: utils.c:202
const AVClass * priv_class
AVClass for the private context.
Definition: avformat.h:434
LIBAVUTIL_VERSION_INT
Definition: eval.c:50
int av_get_frame_filename(char *buf, int buf_size, const char *path, int number)
Return in 'buf' the path with 'd' replaced by a number.
Definition: utils.c:3563
static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: segment.c:182
Stream structure.
Definition: avformat.h:620
char * list
Set by a private option.
Definition: segment.c:39
NULL
Definition: eval.c:50
enum AVMediaType codec_type
Definition: avcodec.h:1574
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:283
AVIOContext * pb
Definition: avformat.h:896
av_default_item_name
Definition: dnxhdenc.c:43
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:111
AVOutputFormat ff_segment_muxer
Definition: segment.c:264
Describe the class of an AVClass context structure.
Definition: log.h:33
int has_video
Definition: segment.c:44
int avio_open2(AVIOContext **s, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
Create and initialize a AVIOContext for accessing the resource indicated by url.
Definition: aviobuf.c:970
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: utils.c:2702
misc parsing utilities
static const AVClass seg_class
Definition: segment.c:256
Main libavformat public API header.
void av_opt_free(void *obj)
Free all string and binary options in obj.
Definition: opt.c:718
static int segment_start(AVFormatContext *s)
Definition: segment.c:48
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:125
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:368
static int segment_end(AVFormatContext *oc)
Definition: segment.c:87
#define E
Definition: segment.c:247
int64_t recording_time
Definition: segment.c:43
void * priv_data
Format private data.
Definition: avformat.h:883
static const AVOption options[]
Definition: segment.c:248
#define AVERROR_MUXER_NOT_FOUND
Muxer not found.
Definition: error.h:55
int stream_index
Definition: avcodec.h:910
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avformat.h:652
int(* write_trailer)(struct AVFormatContext *)
Definition: avformat.h:408
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:901
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2