FFmpeg
segment.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011, Luca Barbato
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /**
22  * @file generic segmenter
23  * M3U8 specification can be find here:
24  * @url{http://tools.ietf.org/id/draft-pantos-http-live-streaming}
25  */
26 
27 #include <float.h>
28 #include <time.h>
29 
30 #include "avformat.h"
31 #include "avio_internal.h"
32 #include "internal.h"
33 
34 #include "libavutil/avassert.h"
35 #include "libavutil/internal.h"
36 #include "libavutil/log.h"
37 #include "libavutil/opt.h"
38 #include "libavutil/avstring.h"
39 #include "libavutil/parseutils.h"
40 #include "libavutil/mathematics.h"
41 #include "libavutil/time.h"
42 #include "libavutil/timecode.h"
44 #include "libavutil/timestamp.h"
45 
46 typedef struct SegmentListEntry {
47  int index;
49  int64_t start_pts;
50  int64_t offset_pts;
51  char *filename;
53  int64_t last_duration;
55 
56 typedef enum {
61  LIST_TYPE_EXT, ///< deprecated
64 } ListType;
65 
66 #define SEGMENT_LIST_FLAG_CACHE 1
67 #define SEGMENT_LIST_FLAG_LIVE 2
68 
69 typedef struct SegmentContext {
70  const AVClass *class; /**< Class for private options. */
71  int segment_idx; ///< index of the segment file to write, starting from 0
72  int segment_idx_wrap; ///< number after which the index wraps
73  int segment_idx_wrap_nb; ///< number of time the index has wraped
74  int segment_count; ///< number of segment files already written
77  char *format; ///< format to use for output segment files
78  char *format_options_str; ///< format options to use for output segment files
80  char *list; ///< filename for the segment list file
81  int list_flags; ///< flags affecting list generation
82  int list_size; ///< number of entries for the segment list file
83 
84  int use_clocktime; ///< flag to cut segments at regular clock time
85  int64_t clocktime_offset; //< clock offset for cutting the segments at regular clock time
86  int64_t clocktime_wrap_duration; //< wrapping duration considered for starting a new segment
87  int64_t last_val; ///< remember last time for wrap around detection
89  int header_written; ///< whether we've already called avformat_write_header
90 
91  char *entry_prefix; ///< prefix to add to list entry filenames
92  int list_type; ///< set the list type
93  AVIOContext *list_pb; ///< list file put-byte context
94  char *time_str; ///< segment duration specification string
95  int64_t time; ///< segment duration
96  int use_strftime; ///< flag to expand filename with strftime
97  int increment_tc; ///< flag to increment timecode if found
98 
99  char *times_str; ///< segment times specification string
100  int64_t *times; ///< list of segment interval specification
101  int nb_times; ///< number of elments in the times array
102 
103  char *frames_str; ///< segment frame numbers specification string
104  int *frames; ///< list of frame number specification
105  int nb_frames; ///< number of elments in the frames array
106  int frame_count; ///< total number of reference frames
107  int segment_frame_count; ///< number of reference frames in the segment
108 
109  int64_t time_delta;
110  int individual_header_trailer; /**< Set by a private option. */
111  int write_header_trailer; /**< Set by a private option. */
112  char *header_filename; ///< filename to write the output header to
113 
114  int reset_timestamps; ///< reset timestamps at the beginning of each segment
115  int64_t initial_offset; ///< initial timestamps offset, expressed in microseconds
116  char *reference_stream_specifier; ///< reference stream specifier
120 
122  char temp_list_filename[1024];
123 
128 
129 static void print_csv_escaped_str(AVIOContext *ctx, const char *str)
130 {
131  int needs_quoting = !!str[strcspn(str, "\",\n\r")];
132 
133  if (needs_quoting)
134  avio_w8(ctx, '"');
135 
136  for (; *str; str++) {
137  if (*str == '"')
138  avio_w8(ctx, '"');
139  avio_w8(ctx, *str);
140  }
141  if (needs_quoting)
142  avio_w8(ctx, '"');
143 }
144 
146 {
147  SegmentContext *seg = s->priv_data;
148  AVFormatContext *oc;
149  int i;
150  int ret;
151 
152  ret = avformat_alloc_output_context2(&seg->avf, seg->oformat, NULL, NULL);
153  if (ret < 0)
154  return ret;
155  oc = seg->avf;
156 
158  oc->max_delay = s->max_delay;
159  av_dict_copy(&oc->metadata, s->metadata, 0);
160  oc->opaque = s->opaque;
161  oc->io_close = s->io_close;
162  oc->io_open = s->io_open;
163  oc->flags = s->flags;
164 
165  for (i = 0; i < s->nb_streams; i++) {
166  AVStream *st;
167  AVCodecParameters *ipar, *opar;
168 
169  if (!(st = avformat_new_stream(oc, NULL)))
170  return AVERROR(ENOMEM);
171  ipar = s->streams[i]->codecpar;
172  opar = st->codecpar;
173  avcodec_parameters_copy(opar, ipar);
174  if (!oc->oformat->codec_tag ||
175  av_codec_get_id (oc->oformat->codec_tag, ipar->codec_tag) == opar->codec_id ||
176  av_codec_get_tag(oc->oformat->codec_tag, ipar->codec_id) <= 0) {
177  opar->codec_tag = ipar->codec_tag;
178  } else {
179  opar->codec_tag = 0;
180  }
182  st->time_base = s->streams[i]->time_base;
184 #if FF_API_LAVF_AVCTX
186  if (s->streams[i]->codecpar->codec_tag == MKTAG('t','m','c','d'))
187  st->codec->time_base = s->streams[i]->codec->time_base;
189 #endif
190  av_dict_copy(&st->metadata, s->streams[i]->metadata, 0);
191  }
192 
193  return 0;
194 }
195 
197 {
198  SegmentContext *seg = s->priv_data;
199  AVFormatContext *oc = seg->avf;
200  size_t size;
201  int ret;
202  char buf[1024];
203  char *new_name;
204 
205  if (seg->segment_idx_wrap)
206  seg->segment_idx %= seg->segment_idx_wrap;
207  if (seg->use_strftime) {
208  time_t now0;
209  struct tm *tm, tmpbuf;
210  time(&now0);
211  tm = localtime_r(&now0, &tmpbuf);
212  if (!strftime(buf, sizeof(buf), s->url, tm)) {
213  av_log(oc, AV_LOG_ERROR, "Could not get segment filename with strftime\n");
214  return AVERROR(EINVAL);
215  }
216  } else if (av_get_frame_filename(buf, sizeof(buf),
217  s->url, seg->segment_idx) < 0) {
218  av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", s->url);
219  return AVERROR(EINVAL);
220  }
221  new_name = av_strdup(buf);
222  if (!new_name)
223  return AVERROR(ENOMEM);
224  ff_format_set_url(oc, new_name);
225 
226  /* copy modified name in list entry */
227  size = strlen(av_basename(oc->url)) + 1;
228  if (seg->entry_prefix)
229  size += strlen(seg->entry_prefix);
230 
231  if ((ret = av_reallocp(&seg->cur_entry.filename, size)) < 0)
232  return ret;
233  snprintf(seg->cur_entry.filename, size, "%s%s",
234  seg->entry_prefix ? seg->entry_prefix : "",
235  av_basename(oc->url));
236 
237  return 0;
238 }
239 
241 {
242  SegmentContext *seg = s->priv_data;
243  AVFormatContext *oc = seg->avf;
244  int err = 0;
245 
246  if (write_header) {
248  seg->avf = NULL;
249  if ((err = segment_mux_init(s)) < 0)
250  return err;
251  oc = seg->avf;
252  }
253 
254  seg->segment_idx++;
255  if ((seg->segment_idx_wrap) && (seg->segment_idx % seg->segment_idx_wrap == 0))
256  seg->segment_idx_wrap_nb++;
257 
258  if ((err = set_segment_filename(s)) < 0)
259  return err;
260 
261  if ((err = s->io_open(s, &oc->pb, oc->url, AVIO_FLAG_WRITE, NULL)) < 0) {
262  av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->url);
263  return err;
264  }
265  if (!seg->individual_header_trailer)
266  oc->pb->seekable = 0;
267 
268  if (oc->oformat->priv_class && oc->priv_data)
269  av_opt_set(oc->priv_data, "mpegts_flags", "+resend_headers", 0);
270 
271  if (write_header) {
273  av_dict_copy(&options, seg->format_options, 0);
274  av_dict_set(&options, "fflags", "-autobsf", 0);
275  err = avformat_write_header(oc, &options);
276  av_dict_free(&options);
277  if (err < 0)
278  return err;
279  }
280 
281  seg->segment_frame_count = 0;
282  return 0;
283 }
284 
286 {
287  SegmentContext *seg = s->priv_data;
288  int ret;
289 
290  snprintf(seg->temp_list_filename, sizeof(seg->temp_list_filename), seg->use_rename ? "%s.tmp" : "%s", seg->list);
291  ret = s->io_open(s, &seg->list_pb, seg->temp_list_filename, AVIO_FLAG_WRITE, NULL);
292  if (ret < 0) {
293  av_log(s, AV_LOG_ERROR, "Failed to open segment list '%s'\n", seg->list);
294  return ret;
295  }
296 
297  if (seg->list_type == LIST_TYPE_M3U8 && seg->segment_list_entries) {
298  SegmentListEntry *entry;
299  double max_duration = 0;
300 
301  avio_printf(seg->list_pb, "#EXTM3U\n");
302  avio_printf(seg->list_pb, "#EXT-X-VERSION:3\n");
303  avio_printf(seg->list_pb, "#EXT-X-MEDIA-SEQUENCE:%d\n", seg->segment_list_entries->index);
304  avio_printf(seg->list_pb, "#EXT-X-ALLOW-CACHE:%s\n",
305  seg->list_flags & SEGMENT_LIST_FLAG_CACHE ? "YES" : "NO");
306 
307  av_log(s, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%d\n",
309 
310  for (entry = seg->segment_list_entries; entry; entry = entry->next)
311  max_duration = FFMAX(max_duration, entry->end_time - entry->start_time);
312  avio_printf(seg->list_pb, "#EXT-X-TARGETDURATION:%"PRId64"\n", (int64_t)ceil(max_duration));
313  } else if (seg->list_type == LIST_TYPE_FFCONCAT) {
314  avio_printf(seg->list_pb, "ffconcat version 1.0\n");
315  }
316 
317  return ret;
318 }
319 
320 static void segment_list_print_entry(AVIOContext *list_ioctx,
321  ListType list_type,
322  const SegmentListEntry *list_entry,
323  void *log_ctx)
324 {
325  switch (list_type) {
326  case LIST_TYPE_FLAT:
327  avio_printf(list_ioctx, "%s\n", list_entry->filename);
328  break;
329  case LIST_TYPE_CSV:
330  case LIST_TYPE_EXT:
331  print_csv_escaped_str(list_ioctx, list_entry->filename);
332  avio_printf(list_ioctx, ",%f,%f\n", list_entry->start_time, list_entry->end_time);
333  break;
334  case LIST_TYPE_M3U8:
335  avio_printf(list_ioctx, "#EXTINF:%f,\n%s\n",
336  list_entry->end_time - list_entry->start_time, list_entry->filename);
337  break;
338  case LIST_TYPE_FFCONCAT:
339  {
340  char *buf;
341  if (av_escape(&buf, list_entry->filename, NULL, AV_ESCAPE_MODE_AUTO, AV_ESCAPE_FLAG_WHITESPACE) < 0) {
342  av_log(log_ctx, AV_LOG_WARNING,
343  "Error writing list entry '%s' in list file\n", list_entry->filename);
344  return;
345  }
346  avio_printf(list_ioctx, "file %s\n", buf);
347  av_free(buf);
348  break;
349  }
350  default:
351  av_assert0(!"Invalid list type");
352  }
353 }
354 
355 static int segment_end(AVFormatContext *s, int write_trailer, int is_last)
356 {
357  SegmentContext *seg = s->priv_data;
358  AVFormatContext *oc = seg->avf;
359  int ret = 0;
360  AVTimecode tc;
361  AVRational rate;
362  AVDictionaryEntry *tcr;
364  int i;
365  int err;
366 
367  if (!oc || !oc->pb)
368  return AVERROR(EINVAL);
369 
370  av_write_frame(oc, NULL); /* Flush any buffered data (fragmented mp4) */
371  if (write_trailer)
372  ret = av_write_trailer(oc);
373 
374  if (ret < 0)
375  av_log(s, AV_LOG_ERROR, "Failure occurred when ending segment '%s'\n",
376  oc->url);
377 
378  if (seg->list) {
379  if (seg->list_size || seg->list_type == LIST_TYPE_M3U8) {
380  SegmentListEntry *entry = av_mallocz(sizeof(*entry));
381  if (!entry) {
382  ret = AVERROR(ENOMEM);
383  goto end;
384  }
385 
386  /* append new element */
387  memcpy(entry, &seg->cur_entry, sizeof(*entry));
388  entry->filename = av_strdup(entry->filename);
389  if (!seg->segment_list_entries)
391  else
392  seg->segment_list_entries_end->next = entry;
393  seg->segment_list_entries_end = entry;
394 
395  /* drop first item */
396  if (seg->list_size && seg->segment_count >= seg->list_size) {
397  entry = seg->segment_list_entries;
399  av_freep(&entry->filename);
400  av_freep(&entry);
401  }
402 
403  if ((ret = segment_list_open(s)) < 0)
404  goto end;
405  for (entry = seg->segment_list_entries; entry; entry = entry->next)
406  segment_list_print_entry(seg->list_pb, seg->list_type, entry, s);
407  if (seg->list_type == LIST_TYPE_M3U8 && is_last)
408  avio_printf(seg->list_pb, "#EXT-X-ENDLIST\n");
409  ff_format_io_close(s, &seg->list_pb);
410  if (seg->use_rename)
411  ff_rename(seg->temp_list_filename, seg->list, s);
412  } else {
413  segment_list_print_entry(seg->list_pb, seg->list_type, &seg->cur_entry, s);
414  avio_flush(seg->list_pb);
415  }
416  }
417 
418  av_log(s, AV_LOG_VERBOSE, "segment:'%s' count:%d ended\n",
419  seg->avf->url, seg->segment_count);
420  seg->segment_count++;
421 
422  if (seg->increment_tc) {
423  tcr = av_dict_get(s->metadata, "timecode", NULL, 0);
424  if (tcr) {
425  /* search the first video stream */
426  for (i = 0; i < s->nb_streams; i++) {
428  rate = s->streams[i]->avg_frame_rate;/* Get fps from the video stream */
429  err = av_timecode_init_from_string(&tc, rate, tcr->value, s);
430  if (err < 0) {
431  av_log(s, AV_LOG_WARNING, "Could not increment global timecode, error occurred during timecode creation.\n");
432  break;
433  }
434  tc.start += (int)((seg->cur_entry.end_time - seg->cur_entry.start_time) * av_q2d(rate));/* increment timecode */
435  av_dict_set(&s->metadata, "timecode",
436  av_timecode_make_string(&tc, buf, 0), 0);
437  break;
438  }
439  }
440  } else {
441  av_log(s, AV_LOG_WARNING, "Could not increment global timecode, no global timecode metadata found.\n");
442  }
443  for (i = 0; i < s->nb_streams; i++) {
445  char st_buf[AV_TIMECODE_STR_SIZE];
446  AVTimecode st_tc;
447  AVRational st_rate = s->streams[i]->avg_frame_rate;
448  AVDictionaryEntry *st_tcr = av_dict_get(s->streams[i]->metadata, "timecode", NULL, 0);
449  if (st_tcr) {
450  if ((av_timecode_init_from_string(&st_tc, st_rate, st_tcr->value, s) < 0)) {
451  av_log(s, AV_LOG_WARNING, "Could not increment stream %d timecode, error occurred during timecode creation.\n", i);
452  continue;
453  }
454  st_tc.start += (int)((seg->cur_entry.end_time - seg->cur_entry.start_time) * av_q2d(st_rate)); // increment timecode
455  av_dict_set(&s->streams[i]->metadata, "timecode", av_timecode_make_string(&st_tc, st_buf, 0), 0);
456  }
457  }
458  }
459  }
460 
461 end:
462  ff_format_io_close(oc, &oc->pb);
463 
464  return ret;
465 }
466 
467 static int parse_times(void *log_ctx, int64_t **times, int *nb_times,
468  const char *times_str)
469 {
470  char *p;
471  int i, ret = 0;
472  char *times_str1 = av_strdup(times_str);
473  char *saveptr = NULL;
474 
475  if (!times_str1)
476  return AVERROR(ENOMEM);
477 
478 #define FAIL(err) ret = err; goto end
479 
480  *nb_times = 1;
481  for (p = times_str1; *p; p++)
482  if (*p == ',')
483  (*nb_times)++;
484 
485  *times = av_malloc_array(*nb_times, sizeof(**times));
486  if (!*times) {
487  av_log(log_ctx, AV_LOG_ERROR, "Could not allocate forced times array\n");
488  FAIL(AVERROR(ENOMEM));
489  }
490 
491  p = times_str1;
492  for (i = 0; i < *nb_times; i++) {
493  int64_t t;
494  char *tstr = av_strtok(p, ",", &saveptr);
495  p = NULL;
496 
497  if (!tstr || !tstr[0]) {
498  av_log(log_ctx, AV_LOG_ERROR, "Empty time specification in times list %s\n",
499  times_str);
500  FAIL(AVERROR(EINVAL));
501  }
502 
503  ret = av_parse_time(&t, tstr, 1);
504  if (ret < 0) {
505  av_log(log_ctx, AV_LOG_ERROR,
506  "Invalid time duration specification '%s' in times list %s\n", tstr, times_str);
507  FAIL(AVERROR(EINVAL));
508  }
509  (*times)[i] = t;
510 
511  /* check on monotonicity */
512  if (i && (*times)[i-1] > (*times)[i]) {
513  av_log(log_ctx, AV_LOG_ERROR,
514  "Specified time %f is greater than the following time %f\n",
515  (float)((*times)[i])/1000000, (float)((*times)[i-1])/1000000);
516  FAIL(AVERROR(EINVAL));
517  }
518  }
519 
520 end:
521  av_free(times_str1);
522  return ret;
523 }
524 
525 static int parse_frames(void *log_ctx, int **frames, int *nb_frames,
526  const char *frames_str)
527 {
528  char *p;
529  int i, ret = 0;
530  char *frames_str1 = av_strdup(frames_str);
531  char *saveptr = NULL;
532 
533  if (!frames_str1)
534  return AVERROR(ENOMEM);
535 
536 #define FAIL(err) ret = err; goto end
537 
538  *nb_frames = 1;
539  for (p = frames_str1; *p; p++)
540  if (*p == ',')
541  (*nb_frames)++;
542 
543  *frames = av_malloc_array(*nb_frames, sizeof(**frames));
544  if (!*frames) {
545  av_log(log_ctx, AV_LOG_ERROR, "Could not allocate forced frames array\n");
546  FAIL(AVERROR(ENOMEM));
547  }
548 
549  p = frames_str1;
550  for (i = 0; i < *nb_frames; i++) {
551  long int f;
552  char *tailptr;
553  char *fstr = av_strtok(p, ",", &saveptr);
554 
555  p = NULL;
556  if (!fstr) {
557  av_log(log_ctx, AV_LOG_ERROR, "Empty frame specification in frame list %s\n",
558  frames_str);
559  FAIL(AVERROR(EINVAL));
560  }
561  f = strtol(fstr, &tailptr, 10);
562  if (*tailptr || f <= 0 || f >= INT_MAX) {
563  av_log(log_ctx, AV_LOG_ERROR,
564  "Invalid argument '%s', must be a positive integer <= INT64_MAX\n",
565  fstr);
566  FAIL(AVERROR(EINVAL));
567  }
568  (*frames)[i] = f;
569 
570  /* check on monotonicity */
571  if (i && (*frames)[i-1] > (*frames)[i]) {
572  av_log(log_ctx, AV_LOG_ERROR,
573  "Specified frame %d is greater than the following frame %d\n",
574  (*frames)[i], (*frames)[i-1]);
575  FAIL(AVERROR(EINVAL));
576  }
577  }
578 
579 end:
580  av_free(frames_str1);
581  return ret;
582 }
583 
585 {
586  int buf_size = 32768;
587  uint8_t *buf = av_malloc(buf_size);
588  if (!buf)
589  return AVERROR(ENOMEM);
590  *ctx = avio_alloc_context(buf, buf_size, AVIO_FLAG_WRITE, NULL, NULL, NULL, NULL);
591  if (!*ctx) {
592  av_free(buf);
593  return AVERROR(ENOMEM);
594  }
595  return 0;
596 }
597 
598 static void close_null_ctxp(AVIOContext **pb)
599 {
600  av_freep(&(*pb)->buffer);
601  avio_context_free(pb);
602 }
603 
605 {
606  SegmentContext *seg = s->priv_data;
607  int ret, i;
608 
609  seg->reference_stream_index = -1;
610  if (!strcmp(seg->reference_stream_specifier, "auto")) {
611  /* select first index of type with highest priority */
612  int type_index_map[AVMEDIA_TYPE_NB];
613  static const enum AVMediaType type_priority_list[] = {
619  };
620  enum AVMediaType type;
621 
622  for (i = 0; i < AVMEDIA_TYPE_NB; i++)
623  type_index_map[i] = -1;
624 
625  /* select first index for each type */
626  for (i = 0; i < s->nb_streams; i++) {
627  type = s->streams[i]->codecpar->codec_type;
628  if ((unsigned)type < AVMEDIA_TYPE_NB && type_index_map[type] == -1
629  /* ignore attached pictures/cover art streams */
631  type_index_map[type] = i;
632  }
633 
634  for (i = 0; i < FF_ARRAY_ELEMS(type_priority_list); i++) {
635  type = type_priority_list[i];
636  if ((seg->reference_stream_index = type_index_map[type]) >= 0)
637  break;
638  }
639  } else {
640  for (i = 0; i < s->nb_streams; i++) {
643  if (ret < 0)
644  return ret;
645  if (ret > 0) {
646  seg->reference_stream_index = i;
647  break;
648  }
649  }
650  }
651 
652  if (seg->reference_stream_index < 0) {
653  av_log(s, AV_LOG_ERROR, "Could not select stream matching identifier '%s'\n",
655  return AVERROR(EINVAL);
656  }
657 
658  return 0;
659 }
660 
662 {
663  SegmentContext *seg = s->priv_data;
664  ff_format_io_close(seg->avf, &seg->list_pb);
666  seg->avf = NULL;
667 }
668 
670 {
671  SegmentContext *seg = s->priv_data;
672  AVFormatContext *oc = seg->avf;
674  int ret;
675  int i;
676 
677  seg->segment_count = 0;
678  if (!seg->write_header_trailer)
679  seg->individual_header_trailer = 0;
680 
681  if (seg->header_filename) {
682  seg->write_header_trailer = 1;
683  seg->individual_header_trailer = 0;
684  }
685 
686  if (seg->initial_offset > 0) {
687  av_log(s, AV_LOG_WARNING, "NOTE: the option initial_offset is deprecated,"
688  "you can use output_ts_offset instead of it\n");
689  }
690 
691  if (!!seg->time_str + !!seg->times_str + !!seg->frames_str > 1) {
692  av_log(s, AV_LOG_ERROR,
693  "segment_time, segment_times, and segment_frames options "
694  "are mutually exclusive, select just one of them\n");
695  return AVERROR(EINVAL);
696  }
697 
698  if (seg->times_str) {
699  if ((ret = parse_times(s, &seg->times, &seg->nb_times, seg->times_str)) < 0)
700  return ret;
701  } else if (seg->frames_str) {
702  if ((ret = parse_frames(s, &seg->frames, &seg->nb_frames, seg->frames_str)) < 0)
703  return ret;
704  } else {
705  /* set default value if not specified */
706  if (!seg->time_str)
707  seg->time_str = av_strdup("2");
708  if ((ret = av_parse_time(&seg->time, seg->time_str, 1)) < 0) {
709  av_log(s, AV_LOG_ERROR,
710  "Invalid time duration specification '%s' for segment_time option\n",
711  seg->time_str);
712  return ret;
713  }
714  if (seg->use_clocktime) {
715  if (seg->time <= 0) {
716  av_log(s, AV_LOG_ERROR, "Invalid negative segment_time with segment_atclocktime option set\n");
717  return AVERROR(EINVAL);
718  }
719  seg->clocktime_offset = seg->time - (seg->clocktime_offset % seg->time);
720  }
721  }
722 
723  if (seg->format_options_str) {
724  ret = av_dict_parse_string(&seg->format_options, seg->format_options_str, "=", ":", 0);
725  if (ret < 0) {
726  av_log(s, AV_LOG_ERROR, "Could not parse format options list '%s'\n",
727  seg->format_options_str);
728  return ret;
729  }
730  }
731 
732  if (seg->list) {
733  if (seg->list_type == LIST_TYPE_UNDEFINED) {
734  if (av_match_ext(seg->list, "csv" )) seg->list_type = LIST_TYPE_CSV;
735  else if (av_match_ext(seg->list, "ext" )) seg->list_type = LIST_TYPE_EXT;
736  else if (av_match_ext(seg->list, "m3u8")) seg->list_type = LIST_TYPE_M3U8;
737  else if (av_match_ext(seg->list, "ffcat,ffconcat")) seg->list_type = LIST_TYPE_FFCONCAT;
738  else seg->list_type = LIST_TYPE_FLAT;
739  }
740  if (!seg->list_size && seg->list_type != LIST_TYPE_M3U8) {
741  if ((ret = segment_list_open(s)) < 0)
742  return ret;
743  } else {
744  const char *proto = avio_find_protocol_name(seg->list);
745  seg->use_rename = proto && !strcmp(proto, "file");
746  }
747  }
748 
749  if (seg->list_type == LIST_TYPE_EXT)
750  av_log(s, AV_LOG_WARNING, "'ext' list type option is deprecated in favor of 'csv'\n");
751 
752  if ((ret = select_reference_stream(s)) < 0)
753  return ret;
754  av_log(s, AV_LOG_VERBOSE, "Selected stream id:%d type:%s\n",
757 
758  seg->oformat = av_guess_format(seg->format, s->url, NULL);
759 
760  if (!seg->oformat)
762  if (seg->oformat->flags & AVFMT_NOFILE) {
763  av_log(s, AV_LOG_ERROR, "format %s not supported.\n",
764  seg->oformat->name);
765  return AVERROR(EINVAL);
766  }
767 
768  if ((ret = segment_mux_init(s)) < 0)
769  return ret;
770 
771  if ((ret = set_segment_filename(s)) < 0)
772  return ret;
773  oc = seg->avf;
774 
775  if (seg->write_header_trailer) {
776  if ((ret = s->io_open(s, &oc->pb,
777  seg->header_filename ? seg->header_filename : oc->url,
778  AVIO_FLAG_WRITE, NULL)) < 0) {
779  av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->url);
780  return ret;
781  }
782  if (!seg->individual_header_trailer)
783  oc->pb->seekable = 0;
784  } else {
785  if ((ret = open_null_ctx(&oc->pb)) < 0)
786  return ret;
787  }
788 
789  av_dict_copy(&options, seg->format_options, 0);
790  av_dict_set(&options, "fflags", "-autobsf", 0);
791  ret = avformat_init_output(oc, &options);
792  if (av_dict_count(options)) {
793  av_log(s, AV_LOG_ERROR,
794  "Some of the provided format options in '%s' are not recognized\n", seg->format_options_str);
795  av_dict_free(&options);
796  return AVERROR(EINVAL);
797  }
798  av_dict_free(&options);
799 
800  if (ret < 0) {
801  ff_format_io_close(oc, &oc->pb);
802  return ret;
803  }
804  seg->segment_frame_count = 0;
805 
806  av_assert0(s->nb_streams == oc->nb_streams);
807  if (ret == AVSTREAM_INIT_IN_WRITE_HEADER) {
808  ret = avformat_write_header(oc, NULL);
809  if (ret < 0)
810  return ret;
811  seg->header_written = 1;
812  }
813 
814  for (i = 0; i < s->nb_streams; i++) {
815  AVStream *inner_st = oc->streams[i];
816  AVStream *outer_st = s->streams[i];
817  avpriv_set_pts_info(outer_st, inner_st->pts_wrap_bits, inner_st->time_base.num, inner_st->time_base.den);
818  }
819 
820  if (oc->avoid_negative_ts > 0 && s->avoid_negative_ts < 0)
821  s->avoid_negative_ts = 1;
822 
823  return ret;
824 }
825 
827 {
828  SegmentContext *seg = s->priv_data;
829  AVFormatContext *oc = seg->avf;
830  int ret, i;
831 
832  if (!seg->header_written) {
833  for (i = 0; i < s->nb_streams; i++) {
834  AVStream *st = oc->streams[i];
835  AVCodecParameters *ipar, *opar;
836 
837  ipar = s->streams[i]->codecpar;
838  opar = oc->streams[i]->codecpar;
839  avcodec_parameters_copy(opar, ipar);
840  if (!oc->oformat->codec_tag ||
841  av_codec_get_id (oc->oformat->codec_tag, ipar->codec_tag) == opar->codec_id ||
842  av_codec_get_tag(oc->oformat->codec_tag, ipar->codec_id) <= 0) {
843  opar->codec_tag = ipar->codec_tag;
844  } else {
845  opar->codec_tag = 0;
846  }
848  st->time_base = s->streams[i]->time_base;
849  }
850  ret = avformat_write_header(oc, NULL);
851  if (ret < 0)
852  return ret;
853  }
854 
855  if (!seg->write_header_trailer || seg->header_filename) {
856  if (seg->header_filename) {
857  av_write_frame(oc, NULL);
858  ff_format_io_close(oc, &oc->pb);
859  } else {
860  close_null_ctxp(&oc->pb);
861  }
862  if ((ret = oc->io_open(oc, &oc->pb, oc->url, AVIO_FLAG_WRITE, NULL)) < 0)
863  return ret;
864  if (!seg->individual_header_trailer)
865  oc->pb->seekable = 0;
866  }
867 
868  return 0;
869 }
870 
872 {
873  SegmentContext *seg = s->priv_data;
874  AVStream *st = s->streams[pkt->stream_index];
875  int64_t end_pts = INT64_MAX, offset;
876  int start_frame = INT_MAX;
877  int ret;
878  struct tm ti;
879  int64_t usecs;
880  int64_t wrapped_val;
881 
882  if (!seg->avf || !seg->avf->pb)
883  return AVERROR(EINVAL);
884 
885  if (!st->codecpar->extradata_size) {
886  int pkt_extradata_size = 0;
887  uint8_t *pkt_extradata = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &pkt_extradata_size);
888  if (pkt_extradata && pkt_extradata_size > 0) {
889  ret = ff_alloc_extradata(st->codecpar, pkt_extradata_size);
890  if (ret < 0) {
891  av_log(s, AV_LOG_WARNING, "Unable to add extradata to stream. Output segments may be invalid.\n");
892  goto calc_times;
893  }
894  memcpy(st->codecpar->extradata, pkt_extradata, pkt_extradata_size);
895  st->codecpar->extradata_size = pkt_extradata_size;
896  }
897  }
898 
899 calc_times:
900  if (seg->times) {
901  end_pts = seg->segment_count < seg->nb_times ?
902  seg->times[seg->segment_count] : INT64_MAX;
903  } else if (seg->frames) {
904  start_frame = seg->segment_count < seg->nb_frames ?
905  seg->frames[seg->segment_count] : INT_MAX;
906  } else {
907  if (seg->use_clocktime) {
908  int64_t avgt = av_gettime();
909  time_t sec = avgt / 1000000;
910  localtime_r(&sec, &ti);
911  usecs = (int64_t)(ti.tm_hour * 3600 + ti.tm_min * 60 + ti.tm_sec) * 1000000 + (avgt % 1000000);
912  wrapped_val = (usecs + seg->clocktime_offset) % seg->time;
913  if (wrapped_val < seg->last_val && wrapped_val < seg->clocktime_wrap_duration)
914  seg->cut_pending = 1;
915  seg->last_val = wrapped_val;
916  } else {
917  end_pts = seg->time * (seg->segment_count + 1);
918  }
919  }
920 
921  ff_dlog(s, "packet stream:%d pts:%s pts_time:%s duration_time:%s is_key:%d frame:%d\n",
922  pkt->stream_index, av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base),
923  av_ts2timestr(pkt->duration, &st->time_base),
924  pkt->flags & AV_PKT_FLAG_KEY,
925  pkt->stream_index == seg->reference_stream_index ? seg->frame_count : -1);
926 
927  if (pkt->stream_index == seg->reference_stream_index &&
928  (pkt->flags & AV_PKT_FLAG_KEY || seg->break_non_keyframes) &&
929  (seg->segment_frame_count > 0 || seg->write_empty) &&
930  (seg->cut_pending || seg->frame_count >= start_frame ||
931  (pkt->pts != AV_NOPTS_VALUE &&
932  av_compare_ts(pkt->pts, st->time_base,
933  end_pts - seg->time_delta, AV_TIME_BASE_Q) >= 0))) {
934  /* sanitize end time in case last packet didn't have a defined duration */
935  if (seg->cur_entry.last_duration == 0)
936  seg->cur_entry.end_time = (double)pkt->pts * av_q2d(st->time_base);
937 
938  if ((ret = segment_end(s, seg->individual_header_trailer, 0)) < 0)
939  goto fail;
940 
941  if ((ret = segment_start(s, seg->individual_header_trailer)) < 0)
942  goto fail;
943 
944  seg->cut_pending = 0;
946  seg->cur_entry.start_time = (double)pkt->pts * av_q2d(st->time_base);
949 
950  if (seg->times || (!seg->frames && !seg->use_clocktime) && seg->write_empty)
951  goto calc_times;
952  }
953 
954  if (pkt->stream_index == seg->reference_stream_index) {
955  if (pkt->pts != AV_NOPTS_VALUE)
956  seg->cur_entry.end_time =
957  FFMAX(seg->cur_entry.end_time, (double)(pkt->pts + pkt->duration) * av_q2d(st->time_base));
958  seg->cur_entry.last_duration = pkt->duration;
959  }
960 
961  if (seg->segment_frame_count == 0) {
962  av_log(s, AV_LOG_VERBOSE, "segment:'%s' starts with packet stream:%d pts:%s pts_time:%s frame:%d\n",
963  seg->avf->url, pkt->stream_index,
964  av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base), seg->frame_count);
965  }
966 
967  av_log(s, AV_LOG_DEBUG, "stream:%d start_pts_time:%s pts:%s pts_time:%s dts:%s dts_time:%s",
968  pkt->stream_index,
970  av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base),
971  av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base));
972 
973  /* compute new timestamps */
974  offset = av_rescale_q(seg->initial_offset - (seg->reset_timestamps ? seg->cur_entry.start_pts : 0),
976  if (pkt->pts != AV_NOPTS_VALUE)
977  pkt->pts += offset;
978  if (pkt->dts != AV_NOPTS_VALUE)
979  pkt->dts += offset;
980 
981  av_log(s, AV_LOG_DEBUG, " -> pts:%s pts_time:%s dts:%s dts_time:%s\n",
982  av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base),
983  av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base));
984 
985  ret = ff_write_chained(seg->avf, pkt->stream_index, pkt, s, seg->initial_offset || seg->reset_timestamps);
986 
987 fail:
988  if (pkt->stream_index == seg->reference_stream_index) {
989  seg->frame_count++;
990  seg->segment_frame_count++;
991  }
992 
993  return ret;
994 }
995 
997 {
998  SegmentContext *seg = s->priv_data;
999  AVFormatContext *oc = seg->avf;
1000  SegmentListEntry *cur, *next;
1001  int ret = 0;
1002 
1003  if (!oc)
1004  goto fail;
1005 
1006  if (!seg->write_header_trailer) {
1007  if ((ret = segment_end(s, 0, 1)) < 0)
1008  goto fail;
1009  if ((ret = open_null_ctx(&oc->pb)) < 0)
1010  goto fail;
1011  ret = av_write_trailer(oc);
1012  close_null_ctxp(&oc->pb);
1013  } else {
1014  ret = segment_end(s, 1, 1);
1015  }
1016 fail:
1017  if (seg->list)
1018  ff_format_io_close(s, &seg->list_pb);
1019 
1021  av_opt_free(seg);
1022  av_freep(&seg->times);
1023  av_freep(&seg->frames);
1024  av_freep(&seg->cur_entry.filename);
1025 
1026  cur = seg->segment_list_entries;
1027  while (cur) {
1028  next = cur->next;
1029  av_freep(&cur->filename);
1030  av_free(cur);
1031  cur = next;
1032  }
1033 
1035  seg->avf = NULL;
1036  return ret;
1037 }
1038 
1039 static int seg_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt)
1040 {
1041  SegmentContext *seg = s->priv_data;
1042  AVFormatContext *oc = seg->avf;
1043  if (oc->oformat->check_bitstream) {
1044  int ret = oc->oformat->check_bitstream(oc, pkt);
1045  if (ret == 1) {
1046  AVStream *st = s->streams[pkt->stream_index];
1047  AVStream *ost = oc->streams[pkt->stream_index];
1048  st->internal->bsfcs = ost->internal->bsfcs;
1049  st->internal->nb_bsfcs = ost->internal->nb_bsfcs;
1050  ost->internal->bsfcs = NULL;
1051  ost->internal->nb_bsfcs = 0;
1052  }
1053  return ret;
1054  }
1055  return 1;
1056 }
1057 
1058 #define OFFSET(x) offsetof(SegmentContext, x)
1059 #define E AV_OPT_FLAG_ENCODING_PARAM
1060 static const AVOption options[] = {
1061  { "reference_stream", "set reference stream", OFFSET(reference_stream_specifier), AV_OPT_TYPE_STRING, {.str = "auto"}, CHAR_MIN, CHAR_MAX, E },
1062  { "segment_format", "set container format used for the segments", OFFSET(format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
1063  { "segment_format_options", "set list of options for the container format used for the segments", OFFSET(format_options_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
1064  { "segment_list", "set the segment list filename", OFFSET(list), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
1065  { "segment_header_filename", "write a single file containing the header", OFFSET(header_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
1066 
1067  { "segment_list_flags","set flags affecting segment list generation", OFFSET(list_flags), AV_OPT_TYPE_FLAGS, {.i64 = SEGMENT_LIST_FLAG_CACHE }, 0, UINT_MAX, E, "list_flags"},
1068  { "cache", "allow list caching", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_LIST_FLAG_CACHE }, INT_MIN, INT_MAX, E, "list_flags"},
1069  { "live", "enable live-friendly list generation (useful for HLS)", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_LIST_FLAG_LIVE }, INT_MIN, INT_MAX, E, "list_flags"},
1070 
1071  { "segment_list_size", "set the maximum number of playlist entries", OFFSET(list_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
1072 
1073  { "segment_list_type", "set the segment list type", OFFSET(list_type), AV_OPT_TYPE_INT, {.i64 = LIST_TYPE_UNDEFINED}, -1, LIST_TYPE_NB-1, E, "list_type" },
1074  { "flat", "flat format", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_FLAT }, INT_MIN, INT_MAX, E, "list_type" },
1075  { "csv", "csv format", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_CSV }, INT_MIN, INT_MAX, E, "list_type" },
1076  { "ext", "extended format", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_EXT }, INT_MIN, INT_MAX, E, "list_type" },
1077  { "ffconcat", "ffconcat format", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_FFCONCAT }, INT_MIN, INT_MAX, E, "list_type" },
1078  { "m3u8", "M3U8 format", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_M3U8 }, INT_MIN, INT_MAX, E, "list_type" },
1079  { "hls", "Apple HTTP Live Streaming compatible", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_M3U8 }, INT_MIN, INT_MAX, E, "list_type" },
1080 
1081  { "segment_atclocktime", "set segment to be cut at clocktime", OFFSET(use_clocktime), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E},
1082  { "segment_clocktime_offset", "set segment clocktime offset", OFFSET(clocktime_offset), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, 86400000000LL, E},
1083  { "segment_clocktime_wrap_duration", "set segment clocktime wrapping duration", OFFSET(clocktime_wrap_duration), AV_OPT_TYPE_DURATION, {.i64 = INT64_MAX}, 0, INT64_MAX, E},
1084  { "segment_time", "set segment duration", OFFSET(time_str),AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
1085  { "segment_time_delta","set approximation value used for the segment times", OFFSET(time_delta), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, E },
1086  { "segment_times", "set segment split time points", OFFSET(times_str),AV_OPT_TYPE_STRING,{.str = NULL}, 0, 0, E },
1087  { "segment_frames", "set segment split frame numbers", OFFSET(frames_str),AV_OPT_TYPE_STRING,{.str = NULL}, 0, 0, E },
1088  { "segment_wrap", "set number after which the index wraps", OFFSET(segment_idx_wrap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
1089  { "segment_list_entry_prefix", "set base url prefix for segments", OFFSET(entry_prefix), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
1090  { "segment_start_number", "set the sequence number of the first segment", OFFSET(segment_idx), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
1091  { "segment_wrap_number", "set the number of wrap before the first segment", OFFSET(segment_idx_wrap_nb), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
1092  { "strftime", "set filename expansion with strftime at segment creation", OFFSET(use_strftime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
1093  { "increment_tc", "increment timecode between each segment", OFFSET(increment_tc), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
1094  { "break_non_keyframes", "allow breaking segments on non-keyframes", OFFSET(break_non_keyframes), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E },
1095 
1096  { "individual_header_trailer", "write header/trailer to each segment", OFFSET(individual_header_trailer), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, E },
1097  { "write_header_trailer", "write a header to the first segment and a trailer to the last one", OFFSET(write_header_trailer), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, E },
1098  { "reset_timestamps", "reset timestamps at the beginning of each segment", OFFSET(reset_timestamps), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E },
1099  { "initial_offset", "set initial timestamp offset", OFFSET(initial_offset), AV_OPT_TYPE_DURATION, {.i64 = 0}, -INT64_MAX, INT64_MAX, E },
1100  { "write_empty_segments", "allow writing empty 'filler' segments", OFFSET(write_empty), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E },
1101  { NULL },
1102 };
1103 
1104 #if CONFIG_SEGMENT_MUXER
1105 static const AVClass seg_class = {
1106  .class_name = "segment muxer",
1107  .item_name = av_default_item_name,
1108  .option = options,
1109  .version = LIBAVUTIL_VERSION_INT,
1110 };
1111 
1113  .name = "segment",
1114  .long_name = NULL_IF_CONFIG_SMALL("segment"),
1115  .priv_data_size = sizeof(SegmentContext),
1117  .init = seg_init,
1121  .deinit = seg_free,
1122  .check_bitstream = seg_check_bitstream,
1123  .priv_class = &seg_class,
1124 };
1125 #endif
1126 
1127 #if CONFIG_STREAM_SEGMENT_MUXER
1128 static const AVClass sseg_class = {
1129  .class_name = "stream_segment muxer",
1130  .item_name = av_default_item_name,
1131  .option = options,
1132  .version = LIBAVUTIL_VERSION_INT,
1133 };
1134 
1136  .name = "stream_segment,ssegment",
1137  .long_name = NULL_IF_CONFIG_SMALL("streaming segment muxer"),
1138  .priv_data_size = sizeof(SegmentContext),
1139  .flags = AVFMT_NOFILE,
1140  .init = seg_init,
1144  .deinit = seg_free,
1145  .check_bitstream = seg_check_bitstream,
1146  .priv_class = &sseg_class,
1147 };
1148 #endif
struct SegmentListEntry * next
Definition: segment.c:52
static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int unqueue)
Definition: ffmpeg.c:689
int(* io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **options)
A callback for opening new IO streams.
Definition: avformat.h:1940
#define NULL
Definition: coverity.c:32
AVOutputFormat ff_segment_muxer
AVFormatContext * avf
Definition: segment.c:76
Bytestream IO Context.
Definition: avio.h:161
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1636
char * header_filename
filename to write the output header to
Definition: segment.c:112
AVOption.
Definition: opt.h:246
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition: mux.c:878
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
char * entry_prefix
prefix to add to list entry filenames
Definition: segment.c:91
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: utils.c:4896
int av_parse_time(int64_t *timeval, const char *timestr, int duration)
Parse timestr and return in *time a corresponding number of microseconds.
Definition: parseutils.c:587
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int av_escape(char **dst, const char *src, const char *special_chars, enum AVEscapeMode mode, int flags)
Escape string in src, and put the escaped string in an allocated string in *dst, which must be freed ...
Definition: avstring.c:327
AVDictionary * format_options
Definition: segment.c:79
static int segment_start(AVFormatContext *s, int write_header)
Definition: segment.c:240
int segment_idx_wrap
number after which the index wraps
Definition: segment.c:72
int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt, AVFormatContext *src, int interleave)
Write a packet to another muxer than the one the user originally intended.
Definition: mux.c:1318
#define FAIL(err)
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3960
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:943
int num
Numerator.
Definition: rational.h:59
int av_dict_count(const AVDictionary *m)
Get number of entries in dictionary.
Definition: dict.c:35
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:191
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:675
#define tc
Definition: regdef.h:69
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
Definition: dict.c:217
GLint GLenum type
Definition: opengl_enc.c:104
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:236
static AVPacket pkt
int segment_frame_count
number of reference frames in the segment
Definition: segment.c:107
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample format(the sample packing is implied by the sample format) and sample rate.The lists are not just lists
if it could not because there are no more frames
char * filename
Definition: segment.c:51
This struct describes the properties of an encoded stream.
Definition: avcodec.h:3952
static int parse_frames(void *log_ctx, int **frames, int *nb_frames, const char *frames_str)
Definition: segment.c:525
static int seg_write_header(AVFormatContext *s)
Definition: segment.c:826
static int segment_end(AVFormatContext *s, int write_trailer, int is_last)
Definition: segment.c:355
int list_flags
flags affecting list generation
Definition: segment.c:81
static int segment_mux_init(AVFormatContext *s)
Definition: segment.c:145
Format I/O context.
Definition: avformat.h:1358
int64_t last_duration
Definition: segment.c:53
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:72
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
static void close_null_ctxp(AVIOContext **pb)
Definition: segment.c:598
int av_timecode_init_from_string(AVTimecode *tc, AVRational rate, const char *str, void *log_ctx)
Parse timecode representation (hh:mm:ss[:;.
Definition: timecode.c:194
static int seg_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt)
Definition: segment.c:1039
const char * av_basename(const char *path)
Thread safe basename.
Definition: avstring.c:258
int flags
can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_GLOBALHEADER, AVFMT_NOTIMESTAMPS, AVFMT_VARIABLE_FPS, AVFMT_NODIMENSIONS, AVFMT_NOSTREAMS, AVFMT_ALLOW_FLUSH, AVFMT_TS_NONSTRICT, AVFMT_TS_NEGATIVE
Definition: avformat.h:524
uint8_t
#define av_malloc(s)
Opaque data information usually continuous.
Definition: avutil.h:203
char temp_list_filename[1024]
Definition: segment.c:122
AVOptions.
enum AVCodecID av_codec_get_id(const struct AVCodecTag *const *tags, unsigned int tag)
Get the AVCodecID for the given codec tag tag.
timestamp utils, mostly useful for debugging/logging purposes
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
#define f(width, name)
Definition: cbs_vp9.c:255
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: avcodec.h:1498
void ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
Definition: utils.c:5651
int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
Check if the stream st contained in s is matched by the stream specifier spec.
Definition: utils.c:5277
static int seg_write_trailer(struct AVFormatContext *s)
Definition: segment.c:996
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4469
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1426
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:40
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1489
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition: rational.h:104
int start
timecode frame start (first base frame number)
Definition: timecode.h:42
#define ff_dlog(a,...)
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
int av_match_ext(const char *filename, const char *extensions)
Return a positive value if the given filename has one of the given extensions, 0 otherwise.
Definition: format.c:38
ptrdiff_t size
Definition: opengl_enc.c:100
#define AVSTREAM_INIT_IN_WRITE_HEADER
stream parameters initialized in avformat_write_header
Definition: avformat.h:2521
char * format
format to use for output segment files
Definition: segment.c:77
static int select_reference_stream(AVFormatContext *s)
Definition: segment.c:604
#define av_log(a,...)
int break_non_keyframes
Definition: segment.c:118
int64_t time_delta
Definition: segment.c:109
int64_t initial_offset
initial timestamps offset, expressed in microseconds
Definition: segment.c:115
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1512
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
#define ff_const59
The ff_const59 define is not part of the public API and will be removed without further warning...
Definition: avformat.h:549
AVIOContext * avio_alloc_context(unsigned char *buffer, int buffer_size, int write_flag, void *opaque, int(*read_packet)(void *opaque, uint8_t *buf, int buf_size), int(*write_packet)(void *opaque, uint8_t *buf, int buf_size), int64_t(*seek)(void *opaque, int64_t offset, int whence))
Allocate and initialize an AVIOContext for buffered I/O.
Definition: aviobuf.c:131
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
Definition: utils.c:2024
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
AVDictionary * metadata
Metadata that applies to the whole file.
Definition: avformat.h:1598
int individual_header_trailer
Set by a private option.
Definition: segment.c:110
uint8_t * av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type, int *size)
Get side information from packet.
Definition: avpacket.c:350
#define av_ts2timestr(ts, tb)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: timestamp.h:76
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
int(* check_bitstream)(struct AVFormatContext *, const AVPacket *pkt)
Set up any necessary bitstream filtering and extract any extra data needed for the global header...
Definition: avformat.h:639
char * url
input or output URL.
Definition: avformat.h:1454
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
Definition: dict.c:203
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:3956
simple assert() macros that are a bit more flexible than ISO C assert().
int use_rename
Definition: segment.c:121
int avformat_alloc_output_context2(AVFormatContext **ctx, ff_const59 AVOutputFormat *oformat, const char *format_name, const char *filename)
Allocate an AVFormatContext for an output format.
Definition: mux.c:148
int64_t * times
list of segment interval specification
Definition: segment.c:100
AVRational avg_frame_rate
Average framerate.
Definition: avformat.h:954
char * reference_stream_specifier
reference stream specifier
Definition: segment.c:116
#define FFMAX(a, b)
Definition: common.h:94
static int set_segment_filename(AVFormatContext *s)
Definition: segment.c:196
int64_t offset_pts
Definition: segment.c:50
#define fail()
Definition: checkasm.h:121
int reference_stream_index
Definition: segment.c:117
static int seg_init(AVFormatContext *s)
Definition: segment.c:669
int nb_times
number of elments in the times array
Definition: segment.c:101
#define OFFSET(x)
Definition: segment.c:1058
static int segment_list_open(AVFormatContext *s)
Definition: segment.c:285
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1486
int64_t last_val
remember last time for wrap around detection
Definition: segment.c:87
int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b)
Compare two timestamps each in its own time base.
Definition: mathematics.c:147
int extradata_size
Size of the extradata content in bytes.
Definition: avcodec.h:3978
void * opaque
User data.
Definition: avformat.h:1864
Use auto-selected escaping mode.
Definition: avstring.h:314
AVIOContext * list_pb
list file put-byte context
Definition: segment.c:93
common internal API header
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1414
AVBSFContext ** bsfcs
bitstream filters to run on stream
Definition: internal.h:161
static void print_csv_escaped_str(AVIOContext *ctx, const char *str)
Definition: segment.c:129
int seekable
A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
Definition: avio.h:260
int ff_alloc_extradata(AVCodecParameters *par, int size)
Allocate extradata with additional AV_INPUT_BUFFER_PADDING_SIZE at end which is always set to 0...
Definition: utils.c:3298
int cut_pending
Definition: segment.c:88
av_warn_unused_result int avformat_write_header(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and write the stream header to an output media file.
Definition: mux.c:508
static int write_trailer(AVFormatContext *s1)
Definition: v4l2enc.c:94
#define AVFMT_GLOBALHEADER
Format wants global header.
Definition: avformat.h:466
int use_strftime
flag to expand filename with strftime
Definition: segment.c:96
const char * name
Definition: avformat.h:505
ff_const59 AVOutputFormat * oformat
Definition: segment.c:75
AVFormatContext * ctx
Definition: movenc.c:48
int reset_timestamps
reset timestamps at the beginning of each segment
Definition: segment.c:114
int use_clocktime
flag to cut segments at regular clock time
Definition: segment.c:84
ListType
Definition: segment.c:56
#define s(width, name)
Definition: cbs_vp9.c:257
int avoid_negative_ts
Avoid negative timestamps during muxing.
Definition: avformat.h:1689
int increment_tc
flag to increment timecode if found
Definition: segment.c:97
void ff_format_set_url(AVFormatContext *s, char *url)
Set AVFormatContext url field to the provided pointer.
Definition: utils.c:5811
AVDictionary * metadata
Definition: avformat.h:945
Opaque data information usually sparse.
Definition: avutil.h:205
const AVClass * priv_class
AVClass for the private context.
Definition: avformat.h:533
av_warn_unused_result int avformat_init_output(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and initialize the codec, but do not write the header.
Definition: mux.c:488
#define FF_ARRAY_ELEMS(a)
#define AV_DISPOSITION_ATTACHED_PIC
The stream is stored in the file as an attached picture/"cover art" (e.g.
Definition: avformat.h:849
int av_get_frame_filename(char *buf, int buf_size, const char *path, int number)
Definition: utils.c:4737
ff_const59 struct AVOutputFormat * oformat
The output container format.
Definition: avformat.h:1377
static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: segment.c:871
if(ret)
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
Stream structure.
Definition: avformat.h:881
char * list
filename for the segment list file
Definition: segment.c:80
int av_dict_parse_string(AVDictionary **pm, const char *str, const char *key_val_sep, const char *pairs_sep, int flags)
Parse the key/value pairs list and add the parsed entries to a dictionary.
Definition: dict.c:180
char * frames_str
segment frame numbers specification string
Definition: segment.c:103
The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format that the extradata buffer was...
Definition: avcodec.h:1202
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
Definition: mem.c:163
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:251
AVStreamInternal * internal
An opaque field for libavformat internal usage.
Definition: avformat.h:1238
static void seg_free(AVFormatContext *s)
Definition: segment.c:661
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:260
int header_written
whether we&#39;ve already called avformat_write_header
Definition: segment.c:89
Timecode helpers header.
AVIOContext * pb
I/O context.
Definition: avformat.h:1400
const struct AVCodecTag *const * codec_tag
List of supported codec_id-codec_tag pairs, ordered by "better choice first".
Definition: avformat.h:530
void avio_w8(AVIOContext *s, int b)
Definition: aviobuf.c:196
int64_t time
segment duration
Definition: segment.c:95
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining list
void(* io_close)(struct AVFormatContext *s, AVIOContext *pb)
A callback for closing the streams opened with AVFormatContext.io_open().
Definition: avformat.h:1946
void * buf
Definition: avisynth_c.h:766
int list_type
set the list type
Definition: segment.c:92
static int ff_rename(const char *oldpath, const char *newpath, void *logctx)
Wrap errno on rename() error.
Definition: internal.h:591
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:70
int segment_idx
index of the segment file to write, starting from 0
Definition: segment.c:71
Describe the class of an AVClass context structure.
Definition: log.h:67
int * frames
list of frame number specification
Definition: segment.c:104
int64_t start_pts
Definition: segment.c:49
ff_const59 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: format.c:51
Rational number (pair of numerator and denominator).
Definition: rational.h:58
char * time_str
segment duration specification string
Definition: segment.c:94
void avio_flush(AVIOContext *s)
Force flushing of buffered data.
Definition: aviobuf.c:238
AVMediaType
Definition: avutil.h:199
#define snprintf
Definition: snprintf.h:34
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: utils.c:4403
misc parsing utilities
const char * avio_find_protocol_name(const char *url)
Return the name of the protocol that will handle the passed URL.
Definition: avio.c:473
SegmentListEntry * segment_list_entries
Definition: segment.c:125
const char * av_get_media_type_string(enum AVMediaType media_type)
Return a string describing the media_type enum, NULL if media_type is unknown.
Definition: utils.c:76
#define flags(name, subs,...)
Definition: cbs_av1.c:561
int nb_frames
number of elments in the frames array
Definition: segment.c:105
char * av_timecode_make_string(const AVTimecode *tc, char *buf, int framenum)
Load timecode string in buf.
Definition: timecode.c:84
int write_header_trailer
Set by a private option.
Definition: segment.c:111
char * format_options_str
format options to use for output segment files
Definition: segment.c:78
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok()...
Definition: avstring.c:184
static void segment_list_print_entry(AVIOContext *list_ioctx, ListType list_type, const SegmentListEntry *list_entry, void *log_ctx)
Definition: segment.c:320
double end_time
Definition: segment.c:48
static AVStream * ost
Main libavformat public API header.
int
void av_opt_free(void *obj)
Free all allocated objects in obj.
Definition: opt.c:1558
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:84
int write_empty
Definition: segment.c:119
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:463
int64_t clocktime_wrap_duration
Definition: segment.c:86
int disposition
AV_DISPOSITION_* bit field.
Definition: avformat.h:934
void avio_context_free(AVIOContext **s)
Free the supplied IO context and everything associated with it.
Definition: aviobuf.c:148
#define SEGMENT_LIST_FLAG_CACHE
Definition: segment.c:66
#define E
Definition: segment.c:1059
int pts_wrap_bits
number of bits in pts (used for wrapping control)
Definition: avformat.h:1073
#define localtime_r
Definition: time_internal.h:46
static int parse_times(void *log_ctx, int64_t **times, int *nb_times, const char *times_str)
Definition: segment.c:467
int den
Denominator.
Definition: rational.h:60
double start_time
Definition: segment.c:48
#define av_free(p)
int segment_idx_wrap_nb
number of time the index has wraped
Definition: segment.c:73
char * value
Definition: dict.h:87
#define FF_ENABLE_DEPRECATION_WARNINGS
Definition: internal.h:85
#define av_ts2str(ts)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: timestamp.h:54
int64_t clocktime_offset
Definition: segment.c:85
void * priv_data
Format private data.
Definition: avformat.h:1386
static const AVOption options[]
Definition: segment.c:1060
#define AV_ESCAPE_FLAG_WHITESPACE
Consider spaces special and escape them even in the middle of the string.
Definition: avstring.h:327
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:337
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: avcodec.h:3974
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
Definition: avcodec.h:1479
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition: mux.c:1254
static int open_null_ctx(AVIOContext **ctx)
Definition: segment.c:584
#define av_freep(p)
#define AVERROR_MUXER_NOT_FOUND
Muxer not found.
Definition: error.h:60
int segment_count
number of segment files already written
Definition: segment.c:74
AVOutputFormat ff_stream_segment_muxer
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1028
char * times_str
segment times specification string
Definition: segment.c:99
#define av_malloc_array(a, b)
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition: avcodec.h:3964
int stream_index
Definition: avcodec.h:1482
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avformat.h:910
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
SegmentListEntry cur_entry
Definition: segment.c:124
#define MKTAG(a, b, c, d)
Definition: common.h:366
unsigned int av_codec_get_tag(const struct AVCodecTag *const *tags, enum AVCodecID id)
Get the codec tag for the given codec id id.
int list_size
number of entries for the segment list file
Definition: segment.c:82
deprecated
Definition: segment.c:61
This structure stores compressed data.
Definition: avcodec.h:1457
int frame_count
total number of reference frames
Definition: segment.c:106
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition: opt.c:449
#define SEGMENT_LIST_FLAG_LIVE
Definition: segment.c:67
SegmentListEntry * segment_list_entries_end
Definition: segment.c:126
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1473
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2
Writes a formatted string to the context.
#define AV_TIMECODE_STR_SIZE
Definition: timecode.h:33