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
79  char *list; ///< filename for the segment list file
80  int list_flags; ///< flags affecting list generation
81  int list_size; ///< number of entries for the segment list file
82 
83  int use_clocktime; ///< flag to cut segments at regular clock time
84  int64_t clocktime_offset; //< clock offset for cutting the segments at regular clock time
85  int64_t clocktime_wrap_duration; //< wrapping duration considered for starting a new segment
86  int64_t last_val; ///< remember last time for wrap around detection
88  int header_written; ///< whether we've already called avformat_write_header
89 
90  char *entry_prefix; ///< prefix to add to list entry filenames
91  int list_type; ///< set the list type
92  AVIOContext *list_pb; ///< list file put-byte context
93  char *time_str; ///< segment duration specification string
94  int64_t time; ///< segment duration
95  int use_strftime; ///< flag to expand filename with strftime
96  int increment_tc; ///< flag to increment timecode if found
97 
98  char *times_str; ///< segment times specification string
99  int64_t *times; ///< list of segment interval specification
100  int nb_times; ///< number of elments in the times array
101 
102  char *frames_str; ///< segment frame numbers specification string
103  int *frames; ///< list of frame number specification
104  int nb_frames; ///< number of elments in the frames array
105  int frame_count; ///< total number of reference frames
106  int segment_frame_count; ///< number of reference frames in the segment
107 
108  int64_t time_delta;
109  int individual_header_trailer; /**< Set by a private option. */
110  int write_header_trailer; /**< Set by a private option. */
111  char *header_filename; ///< filename to write the output header to
112 
113  int reset_timestamps; ///< reset timestamps at the beginning of each segment
114  int64_t initial_offset; ///< initial timestamps offset, expressed in microseconds
115  char *reference_stream_specifier; ///< reference stream specifier
119 
121  char temp_list_filename[1024];
122 
127 
128 static void print_csv_escaped_str(AVIOContext *ctx, const char *str)
129 {
130  int needs_quoting = !!str[strcspn(str, "\",\n\r")];
131 
132  if (needs_quoting)
133  avio_w8(ctx, '"');
134 
135  for (; *str; str++) {
136  if (*str == '"')
137  avio_w8(ctx, '"');
138  avio_w8(ctx, *str);
139  }
140  if (needs_quoting)
141  avio_w8(ctx, '"');
142 }
143 
145 {
146  SegmentContext *seg = s->priv_data;
147  AVFormatContext *oc;
148  int i;
149  int ret;
150 
151  ret = avformat_alloc_output_context2(&seg->avf, seg->oformat, NULL, NULL);
152  if (ret < 0)
153  return ret;
154  oc = seg->avf;
155 
157  oc->max_delay = s->max_delay;
158  av_dict_copy(&oc->metadata, s->metadata, 0);
159  oc->opaque = s->opaque;
160  oc->io_close = s->io_close;
161  oc->io_open = s->io_open;
162  oc->flags = s->flags;
163 
164  for (i = 0; i < s->nb_streams; i++) {
165  AVStream *st;
166  AVCodecParameters *ipar, *opar;
167 
168  if (!(st = avformat_new_stream(oc, NULL)))
169  return AVERROR(ENOMEM);
170  ipar = s->streams[i]->codecpar;
171  opar = st->codecpar;
172  avcodec_parameters_copy(opar, ipar);
173  if (!oc->oformat->codec_tag ||
174  av_codec_get_id (oc->oformat->codec_tag, ipar->codec_tag) == opar->codec_id ||
175  av_codec_get_tag(oc->oformat->codec_tag, ipar->codec_id) <= 0) {
176  opar->codec_tag = ipar->codec_tag;
177  } else {
178  opar->codec_tag = 0;
179  }
181  st->time_base = s->streams[i]->time_base;
183 #if FF_API_LAVF_AVCTX
185  if (s->streams[i]->codecpar->codec_tag == MKTAG('t','m','c','d'))
186  st->codec->time_base = s->streams[i]->codec->time_base;
188 #endif
189  av_dict_copy(&st->metadata, s->streams[i]->metadata, 0);
190  }
191 
192  return 0;
193 }
194 
196 {
197  SegmentContext *seg = s->priv_data;
198  AVFormatContext *oc = seg->avf;
199  size_t size;
200  int ret;
201  char buf[1024];
202  char *new_name;
203 
204  if (seg->segment_idx_wrap)
205  seg->segment_idx %= seg->segment_idx_wrap;
206  if (seg->use_strftime) {
207  time_t now0;
208  struct tm *tm, tmpbuf;
209  time(&now0);
210  tm = localtime_r(&now0, &tmpbuf);
211  if (!strftime(buf, sizeof(buf), s->url, tm)) {
212  av_log(oc, AV_LOG_ERROR, "Could not get segment filename with strftime\n");
213  return AVERROR(EINVAL);
214  }
215  } else if (av_get_frame_filename(buf, sizeof(buf),
216  s->url, seg->segment_idx) < 0) {
217  av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", s->url);
218  return AVERROR(EINVAL);
219  }
220  new_name = av_strdup(buf);
221  if (!new_name)
222  return AVERROR(ENOMEM);
223  ff_format_set_url(oc, new_name);
224 
225  /* copy modified name in list entry */
226  size = strlen(av_basename(oc->url)) + 1;
227  if (seg->entry_prefix)
228  size += strlen(seg->entry_prefix);
229 
230  if ((ret = av_reallocp(&seg->cur_entry.filename, size)) < 0)
231  return ret;
232  snprintf(seg->cur_entry.filename, size, "%s%s",
233  seg->entry_prefix ? seg->entry_prefix : "",
234  av_basename(oc->url));
235 
236  return 0;
237 }
238 
240 {
241  SegmentContext *seg = s->priv_data;
242  AVFormatContext *oc = seg->avf;
243  int err = 0;
244 
245  if (write_header) {
247  seg->avf = NULL;
248  if ((err = segment_mux_init(s)) < 0)
249  return err;
250  oc = seg->avf;
251  }
252 
253  seg->segment_idx++;
254  if ((seg->segment_idx_wrap) && (seg->segment_idx % seg->segment_idx_wrap == 0))
255  seg->segment_idx_wrap_nb++;
256 
257  if ((err = set_segment_filename(s)) < 0)
258  return err;
259 
260  if ((err = s->io_open(s, &oc->pb, oc->url, AVIO_FLAG_WRITE, NULL)) < 0) {
261  av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->url);
262  return err;
263  }
264  if (!seg->individual_header_trailer)
265  oc->pb->seekable = 0;
266 
267  if (oc->oformat->priv_class && oc->priv_data)
268  av_opt_set(oc->priv_data, "mpegts_flags", "+resend_headers", 0);
269 
270  if (write_header) {
272  av_dict_copy(&options, seg->format_options, 0);
273  av_dict_set(&options, "fflags", "-autobsf", 0);
274  err = avformat_write_header(oc, &options);
275  av_dict_free(&options);
276  if (err < 0)
277  return err;
278  }
279 
280  seg->segment_frame_count = 0;
281  return 0;
282 }
283 
285 {
286  SegmentContext *seg = s->priv_data;
287  int ret;
288 
289  snprintf(seg->temp_list_filename, sizeof(seg->temp_list_filename), seg->use_rename ? "%s.tmp" : "%s", seg->list);
290  ret = s->io_open(s, &seg->list_pb, seg->temp_list_filename, AVIO_FLAG_WRITE, NULL);
291  if (ret < 0) {
292  av_log(s, AV_LOG_ERROR, "Failed to open segment list '%s'\n", seg->list);
293  return ret;
294  }
295 
296  if (seg->list_type == LIST_TYPE_M3U8 && seg->segment_list_entries) {
297  SegmentListEntry *entry;
298  double max_duration = 0;
299 
300  avio_printf(seg->list_pb, "#EXTM3U\n");
301  avio_printf(seg->list_pb, "#EXT-X-VERSION:3\n");
302  avio_printf(seg->list_pb, "#EXT-X-MEDIA-SEQUENCE:%d\n", seg->segment_list_entries->index);
303  avio_printf(seg->list_pb, "#EXT-X-ALLOW-CACHE:%s\n",
304  seg->list_flags & SEGMENT_LIST_FLAG_CACHE ? "YES" : "NO");
305 
306  av_log(s, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%d\n",
308 
309  for (entry = seg->segment_list_entries; entry; entry = entry->next)
310  max_duration = FFMAX(max_duration, entry->end_time - entry->start_time);
311  avio_printf(seg->list_pb, "#EXT-X-TARGETDURATION:%"PRId64"\n", (int64_t)ceil(max_duration));
312  } else if (seg->list_type == LIST_TYPE_FFCONCAT) {
313  avio_printf(seg->list_pb, "ffconcat version 1.0\n");
314  }
315 
316  return ret;
317 }
318 
319 static void segment_list_print_entry(AVIOContext *list_ioctx,
320  ListType list_type,
321  const SegmentListEntry *list_entry,
322  void *log_ctx)
323 {
324  switch (list_type) {
325  case LIST_TYPE_FLAT:
326  avio_printf(list_ioctx, "%s\n", list_entry->filename);
327  break;
328  case LIST_TYPE_CSV:
329  case LIST_TYPE_EXT:
330  print_csv_escaped_str(list_ioctx, list_entry->filename);
331  avio_printf(list_ioctx, ",%f,%f\n", list_entry->start_time, list_entry->end_time);
332  break;
333  case LIST_TYPE_M3U8:
334  avio_printf(list_ioctx, "#EXTINF:%f,\n%s\n",
335  list_entry->end_time - list_entry->start_time, list_entry->filename);
336  break;
337  case LIST_TYPE_FFCONCAT:
338  {
339  char *buf;
340  if (av_escape(&buf, list_entry->filename, NULL, AV_ESCAPE_MODE_AUTO, AV_ESCAPE_FLAG_WHITESPACE) < 0) {
341  av_log(log_ctx, AV_LOG_WARNING,
342  "Error writing list entry '%s' in list file\n", list_entry->filename);
343  return;
344  }
345  avio_printf(list_ioctx, "file %s\n", buf);
346  av_free(buf);
347  break;
348  }
349  default:
350  av_assert0(!"Invalid list type");
351  }
352 }
353 
354 static int segment_end(AVFormatContext *s, int write_trailer, int is_last)
355 {
356  SegmentContext *seg = s->priv_data;
357  AVFormatContext *oc = seg->avf;
358  int ret = 0;
359  AVTimecode tc;
360  AVRational rate;
361  AVDictionaryEntry *tcr;
363  int i;
364  int err;
365 
366  if (!oc || !oc->pb)
367  return AVERROR(EINVAL);
368 
369  av_write_frame(oc, NULL); /* Flush any buffered data (fragmented mp4) */
370  if (write_trailer)
371  ret = av_write_trailer(oc);
372 
373  if (ret < 0)
374  av_log(s, AV_LOG_ERROR, "Failure occurred when ending segment '%s'\n",
375  oc->url);
376 
377  if (seg->list) {
378  if (seg->list_size || seg->list_type == LIST_TYPE_M3U8) {
379  SegmentListEntry *entry = av_mallocz(sizeof(*entry));
380  if (!entry) {
381  ret = AVERROR(ENOMEM);
382  goto end;
383  }
384 
385  /* append new element */
386  memcpy(entry, &seg->cur_entry, sizeof(*entry));
387  entry->filename = av_strdup(entry->filename);
388  if (!seg->segment_list_entries)
390  else
391  seg->segment_list_entries_end->next = entry;
392  seg->segment_list_entries_end = entry;
393 
394  /* drop first item */
395  if (seg->list_size && seg->segment_count >= seg->list_size) {
396  entry = seg->segment_list_entries;
398  av_freep(&entry->filename);
399  av_freep(&entry);
400  }
401 
402  if ((ret = segment_list_open(s)) < 0)
403  goto end;
404  for (entry = seg->segment_list_entries; entry; entry = entry->next)
405  segment_list_print_entry(seg->list_pb, seg->list_type, entry, s);
406  if (seg->list_type == LIST_TYPE_M3U8 && is_last)
407  avio_printf(seg->list_pb, "#EXT-X-ENDLIST\n");
408  ff_format_io_close(s, &seg->list_pb);
409  if (seg->use_rename)
410  ff_rename(seg->temp_list_filename, seg->list, s);
411  } else {
412  segment_list_print_entry(seg->list_pb, seg->list_type, &seg->cur_entry, s);
413  avio_flush(seg->list_pb);
414  }
415  }
416 
417  av_log(s, AV_LOG_VERBOSE, "segment:'%s' count:%d ended\n",
418  seg->avf->url, seg->segment_count);
419  seg->segment_count++;
420 
421  if (seg->increment_tc) {
422  tcr = av_dict_get(s->metadata, "timecode", NULL, 0);
423  if (tcr) {
424  /* search the first video stream */
425  for (i = 0; i < s->nb_streams; i++) {
427  rate = s->streams[i]->avg_frame_rate;/* Get fps from the video stream */
428  err = av_timecode_init_from_string(&tc, rate, tcr->value, s);
429  if (err < 0) {
430  av_log(s, AV_LOG_WARNING, "Could not increment global timecode, error occurred during timecode creation.\n");
431  break;
432  }
433  tc.start += (int)((seg->cur_entry.end_time - seg->cur_entry.start_time) * av_q2d(rate));/* increment timecode */
434  av_dict_set(&s->metadata, "timecode",
435  av_timecode_make_string(&tc, buf, 0), 0);
436  break;
437  }
438  }
439  } else {
440  av_log(s, AV_LOG_WARNING, "Could not increment global timecode, no global timecode metadata found.\n");
441  }
442  for (i = 0; i < s->nb_streams; i++) {
444  char st_buf[AV_TIMECODE_STR_SIZE];
445  AVTimecode st_tc;
446  AVRational st_rate = s->streams[i]->avg_frame_rate;
447  AVDictionaryEntry *st_tcr = av_dict_get(s->streams[i]->metadata, "timecode", NULL, 0);
448  if (st_tcr) {
449  if ((av_timecode_init_from_string(&st_tc, st_rate, st_tcr->value, s) < 0)) {
450  av_log(s, AV_LOG_WARNING, "Could not increment stream %d timecode, error occurred during timecode creation.\n", i);
451  continue;
452  }
453  st_tc.start += (int)((seg->cur_entry.end_time - seg->cur_entry.start_time) * av_q2d(st_rate)); // increment timecode
454  av_dict_set(&s->streams[i]->metadata, "timecode", av_timecode_make_string(&st_tc, st_buf, 0), 0);
455  }
456  }
457  }
458  }
459 
460 end:
461  ff_format_io_close(oc, &oc->pb);
462 
463  return ret;
464 }
465 
466 static int parse_times(void *log_ctx, int64_t **times, int *nb_times,
467  const char *times_str)
468 {
469  char *p;
470  int i, ret = 0;
471  char *times_str1 = av_strdup(times_str);
472  char *saveptr = NULL;
473 
474  if (!times_str1)
475  return AVERROR(ENOMEM);
476 
477 #define FAIL(err) ret = err; goto end
478 
479  *nb_times = 1;
480  for (p = times_str1; *p; p++)
481  if (*p == ',')
482  (*nb_times)++;
483 
484  *times = av_malloc_array(*nb_times, sizeof(**times));
485  if (!*times) {
486  av_log(log_ctx, AV_LOG_ERROR, "Could not allocate forced times array\n");
487  FAIL(AVERROR(ENOMEM));
488  }
489 
490  p = times_str1;
491  for (i = 0; i < *nb_times; i++) {
492  int64_t t;
493  char *tstr = av_strtok(p, ",", &saveptr);
494  p = NULL;
495 
496  if (!tstr || !tstr[0]) {
497  av_log(log_ctx, AV_LOG_ERROR, "Empty time specification in times list %s\n",
498  times_str);
499  FAIL(AVERROR(EINVAL));
500  }
501 
502  ret = av_parse_time(&t, tstr, 1);
503  if (ret < 0) {
504  av_log(log_ctx, AV_LOG_ERROR,
505  "Invalid time duration specification '%s' in times list %s\n", tstr, times_str);
506  FAIL(AVERROR(EINVAL));
507  }
508  (*times)[i] = t;
509 
510  /* check on monotonicity */
511  if (i && (*times)[i-1] > (*times)[i]) {
512  av_log(log_ctx, AV_LOG_ERROR,
513  "Specified time %f is greater than the following time %f\n",
514  (float)((*times)[i])/1000000, (float)((*times)[i-1])/1000000);
515  FAIL(AVERROR(EINVAL));
516  }
517  }
518 
519 end:
520  av_free(times_str1);
521  return ret;
522 }
523 
524 static int parse_frames(void *log_ctx, int **frames, int *nb_frames,
525  const char *frames_str)
526 {
527  char *p;
528  int i, ret = 0;
529  char *frames_str1 = av_strdup(frames_str);
530  char *saveptr = NULL;
531 
532  if (!frames_str1)
533  return AVERROR(ENOMEM);
534 
535 #define FAIL(err) ret = err; goto end
536 
537  *nb_frames = 1;
538  for (p = frames_str1; *p; p++)
539  if (*p == ',')
540  (*nb_frames)++;
541 
542  *frames = av_malloc_array(*nb_frames, sizeof(**frames));
543  if (!*frames) {
544  av_log(log_ctx, AV_LOG_ERROR, "Could not allocate forced frames array\n");
545  FAIL(AVERROR(ENOMEM));
546  }
547 
548  p = frames_str1;
549  for (i = 0; i < *nb_frames; i++) {
550  long int f;
551  char *tailptr;
552  char *fstr = av_strtok(p, ",", &saveptr);
553 
554  p = NULL;
555  if (!fstr) {
556  av_log(log_ctx, AV_LOG_ERROR, "Empty frame specification in frame list %s\n",
557  frames_str);
558  FAIL(AVERROR(EINVAL));
559  }
560  f = strtol(fstr, &tailptr, 10);
561  if (*tailptr || f <= 0 || f >= INT_MAX) {
562  av_log(log_ctx, AV_LOG_ERROR,
563  "Invalid argument '%s', must be a positive integer <= INT64_MAX\n",
564  fstr);
565  FAIL(AVERROR(EINVAL));
566  }
567  (*frames)[i] = f;
568 
569  /* check on monotonicity */
570  if (i && (*frames)[i-1] > (*frames)[i]) {
571  av_log(log_ctx, AV_LOG_ERROR,
572  "Specified frame %d is greater than the following frame %d\n",
573  (*frames)[i], (*frames)[i-1]);
574  FAIL(AVERROR(EINVAL));
575  }
576  }
577 
578 end:
579  av_free(frames_str1);
580  return ret;
581 }
582 
584 {
585  int buf_size = 32768;
586  uint8_t *buf = av_malloc(buf_size);
587  if (!buf)
588  return AVERROR(ENOMEM);
589  *ctx = avio_alloc_context(buf, buf_size, AVIO_FLAG_WRITE, NULL, NULL, NULL, NULL);
590  if (!*ctx) {
591  av_free(buf);
592  return AVERROR(ENOMEM);
593  }
594  return 0;
595 }
596 
597 static void close_null_ctxp(AVIOContext **pb)
598 {
599  av_freep(&(*pb)->buffer);
600  avio_context_free(pb);
601 }
602 
604 {
605  SegmentContext *seg = s->priv_data;
606  int ret, i;
607 
608  seg->reference_stream_index = -1;
609  if (!strcmp(seg->reference_stream_specifier, "auto")) {
610  /* select first index of type with highest priority */
611  int type_index_map[AVMEDIA_TYPE_NB];
612  static const enum AVMediaType type_priority_list[] = {
618  };
619  enum AVMediaType type;
620 
621  for (i = 0; i < AVMEDIA_TYPE_NB; i++)
622  type_index_map[i] = -1;
623 
624  /* select first index for each type */
625  for (i = 0; i < s->nb_streams; i++) {
626  type = s->streams[i]->codecpar->codec_type;
627  if ((unsigned)type < AVMEDIA_TYPE_NB && type_index_map[type] == -1
628  /* ignore attached pictures/cover art streams */
630  type_index_map[type] = i;
631  }
632 
633  for (i = 0; i < FF_ARRAY_ELEMS(type_priority_list); i++) {
634  type = type_priority_list[i];
635  if ((seg->reference_stream_index = type_index_map[type]) >= 0)
636  break;
637  }
638  } else {
639  for (i = 0; i < s->nb_streams; i++) {
642  if (ret < 0)
643  return ret;
644  if (ret > 0) {
645  seg->reference_stream_index = i;
646  break;
647  }
648  }
649  }
650 
651  if (seg->reference_stream_index < 0) {
652  av_log(s, AV_LOG_ERROR, "Could not select stream matching identifier '%s'\n",
654  return AVERROR(EINVAL);
655  }
656 
657  return 0;
658 }
659 
661 {
662  SegmentContext *seg = s->priv_data;
663  ff_format_io_close(seg->avf, &seg->list_pb);
665  seg->avf = NULL;
666 }
667 
669 {
670  SegmentContext *seg = s->priv_data;
671  AVFormatContext *oc = seg->avf;
673  int ret;
674  int i;
675 
676  seg->segment_count = 0;
677  if (!seg->write_header_trailer)
678  seg->individual_header_trailer = 0;
679 
680  if (seg->header_filename) {
681  seg->write_header_trailer = 1;
682  seg->individual_header_trailer = 0;
683  }
684 
685  if (seg->initial_offset > 0) {
686  av_log(s, AV_LOG_WARNING, "NOTE: the option initial_offset is deprecated,"
687  "you can use output_ts_offset instead of it\n");
688  }
689 
690  if (!!seg->time_str + !!seg->times_str + !!seg->frames_str > 1) {
691  av_log(s, AV_LOG_ERROR,
692  "segment_time, segment_times, and segment_frames options "
693  "are mutually exclusive, select just one of them\n");
694  return AVERROR(EINVAL);
695  }
696 
697  if (seg->times_str) {
698  if ((ret = parse_times(s, &seg->times, &seg->nb_times, seg->times_str)) < 0)
699  return ret;
700  } else if (seg->frames_str) {
701  if ((ret = parse_frames(s, &seg->frames, &seg->nb_frames, seg->frames_str)) < 0)
702  return ret;
703  } else {
704  /* set default value if not specified */
705  if (!seg->time_str)
706  seg->time_str = av_strdup("2");
707  if ((ret = av_parse_time(&seg->time, seg->time_str, 1)) < 0) {
708  av_log(s, AV_LOG_ERROR,
709  "Invalid time duration specification '%s' for segment_time option\n",
710  seg->time_str);
711  return ret;
712  }
713  if (seg->use_clocktime) {
714  if (seg->time <= 0) {
715  av_log(s, AV_LOG_ERROR, "Invalid negative segment_time with segment_atclocktime option set\n");
716  return AVERROR(EINVAL);
717  }
718  seg->clocktime_offset = seg->time - (seg->clocktime_offset % seg->time);
719  }
720  }
721 
722  if (seg->list) {
723  if (seg->list_type == LIST_TYPE_UNDEFINED) {
724  if (av_match_ext(seg->list, "csv" )) seg->list_type = LIST_TYPE_CSV;
725  else if (av_match_ext(seg->list, "ext" )) seg->list_type = LIST_TYPE_EXT;
726  else if (av_match_ext(seg->list, "m3u8")) seg->list_type = LIST_TYPE_M3U8;
727  else if (av_match_ext(seg->list, "ffcat,ffconcat")) seg->list_type = LIST_TYPE_FFCONCAT;
728  else seg->list_type = LIST_TYPE_FLAT;
729  }
730  if (!seg->list_size && seg->list_type != LIST_TYPE_M3U8) {
731  if ((ret = segment_list_open(s)) < 0)
732  return ret;
733  } else {
734  const char *proto = avio_find_protocol_name(seg->list);
735  seg->use_rename = proto && !strcmp(proto, "file");
736  }
737  }
738 
739  if (seg->list_type == LIST_TYPE_EXT)
740  av_log(s, AV_LOG_WARNING, "'ext' list type option is deprecated in favor of 'csv'\n");
741 
742  if ((ret = select_reference_stream(s)) < 0)
743  return ret;
744  av_log(s, AV_LOG_VERBOSE, "Selected stream id:%d type:%s\n",
747 
748  seg->oformat = av_guess_format(seg->format, s->url, NULL);
749 
750  if (!seg->oformat)
752  if (seg->oformat->flags & AVFMT_NOFILE) {
753  av_log(s, AV_LOG_ERROR, "format %s not supported.\n",
754  seg->oformat->name);
755  return AVERROR(EINVAL);
756  }
757 
758  if ((ret = segment_mux_init(s)) < 0)
759  return ret;
760 
761  if ((ret = set_segment_filename(s)) < 0)
762  return ret;
763  oc = seg->avf;
764 
765  if (seg->write_header_trailer) {
766  if ((ret = s->io_open(s, &oc->pb,
767  seg->header_filename ? seg->header_filename : oc->url,
768  AVIO_FLAG_WRITE, NULL)) < 0) {
769  av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->url);
770  return ret;
771  }
772  if (!seg->individual_header_trailer)
773  oc->pb->seekable = 0;
774  } else {
775  if ((ret = open_null_ctx(&oc->pb)) < 0)
776  return ret;
777  }
778 
779  av_dict_copy(&options, seg->format_options, 0);
780  av_dict_set(&options, "fflags", "-autobsf", 0);
781  ret = avformat_init_output(oc, &options);
782  if (av_dict_count(options)) {
783  av_log(s, AV_LOG_ERROR,
784  "Some of the provided format options are not recognized\n");
785  av_dict_free(&options);
786  return AVERROR(EINVAL);
787  }
788  av_dict_free(&options);
789 
790  if (ret < 0) {
791  ff_format_io_close(oc, &oc->pb);
792  return ret;
793  }
794  seg->segment_frame_count = 0;
795 
796  av_assert0(s->nb_streams == oc->nb_streams);
797  if (ret == AVSTREAM_INIT_IN_WRITE_HEADER) {
798  ret = avformat_write_header(oc, NULL);
799  if (ret < 0)
800  return ret;
801  seg->header_written = 1;
802  }
803 
804  for (i = 0; i < s->nb_streams; i++) {
805  AVStream *inner_st = oc->streams[i];
806  AVStream *outer_st = s->streams[i];
807  avpriv_set_pts_info(outer_st, inner_st->pts_wrap_bits, inner_st->time_base.num, inner_st->time_base.den);
808  }
809 
810  if (oc->avoid_negative_ts > 0 && s->avoid_negative_ts < 0)
811  s->avoid_negative_ts = 1;
812 
813  return ret;
814 }
815 
817 {
818  SegmentContext *seg = s->priv_data;
819  AVFormatContext *oc = seg->avf;
820  int ret, i;
821 
822  if (!seg->header_written) {
823  for (i = 0; i < s->nb_streams; i++) {
824  AVStream *st = oc->streams[i];
825  AVCodecParameters *ipar, *opar;
826 
827  ipar = s->streams[i]->codecpar;
828  opar = oc->streams[i]->codecpar;
829  avcodec_parameters_copy(opar, ipar);
830  if (!oc->oformat->codec_tag ||
831  av_codec_get_id (oc->oformat->codec_tag, ipar->codec_tag) == opar->codec_id ||
832  av_codec_get_tag(oc->oformat->codec_tag, ipar->codec_id) <= 0) {
833  opar->codec_tag = ipar->codec_tag;
834  } else {
835  opar->codec_tag = 0;
836  }
838  st->time_base = s->streams[i]->time_base;
839  }
840  ret = avformat_write_header(oc, NULL);
841  if (ret < 0)
842  return ret;
843  }
844 
845  if (!seg->write_header_trailer || seg->header_filename) {
846  if (seg->header_filename) {
847  av_write_frame(oc, NULL);
848  ff_format_io_close(oc, &oc->pb);
849  } else {
850  close_null_ctxp(&oc->pb);
851  }
852  if ((ret = oc->io_open(oc, &oc->pb, oc->url, AVIO_FLAG_WRITE, NULL)) < 0)
853  return ret;
854  if (!seg->individual_header_trailer)
855  oc->pb->seekable = 0;
856  }
857 
858  return 0;
859 }
860 
862 {
863  SegmentContext *seg = s->priv_data;
864  AVStream *st = s->streams[pkt->stream_index];
865  int64_t end_pts = INT64_MAX, offset;
866  int start_frame = INT_MAX;
867  int ret;
868  struct tm ti;
869  int64_t usecs;
870  int64_t wrapped_val;
871 
872  if (!seg->avf || !seg->avf->pb)
873  return AVERROR(EINVAL);
874 
875  if (!st->codecpar->extradata_size) {
876  int pkt_extradata_size = 0;
877  uint8_t *pkt_extradata = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &pkt_extradata_size);
878  if (pkt_extradata && pkt_extradata_size > 0) {
879  ret = ff_alloc_extradata(st->codecpar, pkt_extradata_size);
880  if (ret < 0) {
881  av_log(s, AV_LOG_WARNING, "Unable to add extradata to stream. Output segments may be invalid.\n");
882  goto calc_times;
883  }
884  memcpy(st->codecpar->extradata, pkt_extradata, pkt_extradata_size);
885  st->codecpar->extradata_size = pkt_extradata_size;
886  }
887  }
888 
889 calc_times:
890  if (seg->times) {
891  end_pts = seg->segment_count < seg->nb_times ?
892  seg->times[seg->segment_count] : INT64_MAX;
893  } else if (seg->frames) {
894  start_frame = seg->segment_count < seg->nb_frames ?
895  seg->frames[seg->segment_count] : INT_MAX;
896  } else {
897  if (seg->use_clocktime) {
898  int64_t avgt = av_gettime();
899  time_t sec = avgt / 1000000;
900  localtime_r(&sec, &ti);
901  usecs = (int64_t)(ti.tm_hour * 3600 + ti.tm_min * 60 + ti.tm_sec) * 1000000 + (avgt % 1000000);
902  wrapped_val = (usecs + seg->clocktime_offset) % seg->time;
903  if (wrapped_val < seg->last_val && wrapped_val < seg->clocktime_wrap_duration)
904  seg->cut_pending = 1;
905  seg->last_val = wrapped_val;
906  } else {
907  end_pts = seg->time * (seg->segment_count + 1);
908  }
909  }
910 
911  ff_dlog(s, "packet stream:%d pts:%s pts_time:%s duration_time:%s is_key:%d frame:%d\n",
912  pkt->stream_index, av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base),
913  av_ts2timestr(pkt->duration, &st->time_base),
914  pkt->flags & AV_PKT_FLAG_KEY,
915  pkt->stream_index == seg->reference_stream_index ? seg->frame_count : -1);
916 
917  if (pkt->stream_index == seg->reference_stream_index &&
918  (pkt->flags & AV_PKT_FLAG_KEY || seg->break_non_keyframes) &&
919  (seg->segment_frame_count > 0 || seg->write_empty) &&
920  (seg->cut_pending || seg->frame_count >= start_frame ||
921  (pkt->pts != AV_NOPTS_VALUE &&
922  av_compare_ts(pkt->pts, st->time_base,
923  end_pts - seg->time_delta, AV_TIME_BASE_Q) >= 0))) {
924  /* sanitize end time in case last packet didn't have a defined duration */
925  if (seg->cur_entry.last_duration == 0)
926  seg->cur_entry.end_time = (double)pkt->pts * av_q2d(st->time_base);
927 
928  if ((ret = segment_end(s, seg->individual_header_trailer, 0)) < 0)
929  goto fail;
930 
931  if ((ret = segment_start(s, seg->individual_header_trailer)) < 0)
932  goto fail;
933 
934  seg->cut_pending = 0;
936  seg->cur_entry.start_time = (double)pkt->pts * av_q2d(st->time_base);
939 
940  if (seg->times || (!seg->frames && !seg->use_clocktime) && seg->write_empty)
941  goto calc_times;
942  }
943 
944  if (pkt->stream_index == seg->reference_stream_index) {
945  if (pkt->pts != AV_NOPTS_VALUE)
946  seg->cur_entry.end_time =
947  FFMAX(seg->cur_entry.end_time, (double)(pkt->pts + pkt->duration) * av_q2d(st->time_base));
948  seg->cur_entry.last_duration = pkt->duration;
949  }
950 
951  if (seg->segment_frame_count == 0) {
952  av_log(s, AV_LOG_VERBOSE, "segment:'%s' starts with packet stream:%d pts:%s pts_time:%s frame:%d\n",
953  seg->avf->url, pkt->stream_index,
954  av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base), seg->frame_count);
955  }
956 
957  av_log(s, AV_LOG_DEBUG, "stream:%d start_pts_time:%s pts:%s pts_time:%s dts:%s dts_time:%s",
958  pkt->stream_index,
960  av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base),
961  av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base));
962 
963  /* compute new timestamps */
964  offset = av_rescale_q(seg->initial_offset - (seg->reset_timestamps ? seg->cur_entry.start_pts : 0),
966  if (pkt->pts != AV_NOPTS_VALUE)
967  pkt->pts += offset;
968  if (pkt->dts != AV_NOPTS_VALUE)
969  pkt->dts += offset;
970 
971  av_log(s, AV_LOG_DEBUG, " -> pts:%s pts_time:%s dts:%s dts_time:%s\n",
972  av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base),
973  av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base));
974 
975  ret = ff_write_chained(seg->avf, pkt->stream_index, pkt, s, seg->initial_offset || seg->reset_timestamps);
976 
977 fail:
978  if (pkt->stream_index == seg->reference_stream_index) {
979  seg->frame_count++;
980  seg->segment_frame_count++;
981  }
982 
983  return ret;
984 }
985 
987 {
988  SegmentContext *seg = s->priv_data;
989  AVFormatContext *oc = seg->avf;
990  SegmentListEntry *cur, *next;
991  int ret = 0;
992 
993  if (!oc)
994  goto fail;
995 
996  if (!seg->write_header_trailer) {
997  if ((ret = segment_end(s, 0, 1)) < 0)
998  goto fail;
999  if ((ret = open_null_ctx(&oc->pb)) < 0)
1000  goto fail;
1001  ret = av_write_trailer(oc);
1002  close_null_ctxp(&oc->pb);
1003  } else {
1004  ret = segment_end(s, 1, 1);
1005  }
1006 fail:
1007  if (seg->list)
1008  ff_format_io_close(s, &seg->list_pb);
1009 
1010  av_opt_free(seg);
1011  av_freep(&seg->times);
1012  av_freep(&seg->frames);
1013  av_freep(&seg->cur_entry.filename);
1014 
1015  cur = seg->segment_list_entries;
1016  while (cur) {
1017  next = cur->next;
1018  av_freep(&cur->filename);
1019  av_free(cur);
1020  cur = next;
1021  }
1022 
1024  seg->avf = NULL;
1025  return ret;
1026 }
1027 
1028 static int seg_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt)
1029 {
1030  SegmentContext *seg = s->priv_data;
1031  AVFormatContext *oc = seg->avf;
1032  if (oc->oformat->check_bitstream) {
1033  int ret = oc->oformat->check_bitstream(oc, pkt);
1034  if (ret == 1) {
1035  AVStream *st = s->streams[pkt->stream_index];
1036  AVStream *ost = oc->streams[pkt->stream_index];
1037  st->internal->bsfcs = ost->internal->bsfcs;
1038  st->internal->nb_bsfcs = ost->internal->nb_bsfcs;
1039  ost->internal->bsfcs = NULL;
1040  ost->internal->nb_bsfcs = 0;
1041  }
1042  return ret;
1043  }
1044  return 1;
1045 }
1046 
1047 #define OFFSET(x) offsetof(SegmentContext, x)
1048 #define E AV_OPT_FLAG_ENCODING_PARAM
1049 static const AVOption options[] = {
1050  { "reference_stream", "set reference stream", OFFSET(reference_stream_specifier), AV_OPT_TYPE_STRING, {.str = "auto"}, CHAR_MIN, CHAR_MAX, E },
1051  { "segment_format", "set container format used for the segments", OFFSET(format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
1052  { "segment_format_options", "set list of options for the container format used for the segments", OFFSET(format_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E },
1053  { "segment_list", "set the segment list filename", OFFSET(list), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
1054  { "segment_header_filename", "write a single file containing the header", OFFSET(header_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
1055 
1056  { "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"},
1057  { "cache", "allow list caching", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_LIST_FLAG_CACHE }, INT_MIN, INT_MAX, E, "list_flags"},
1058  { "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"},
1059 
1060  { "segment_list_size", "set the maximum number of playlist entries", OFFSET(list_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
1061 
1062  { "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" },
1063  { "flat", "flat format", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_FLAT }, INT_MIN, INT_MAX, E, "list_type" },
1064  { "csv", "csv format", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_CSV }, INT_MIN, INT_MAX, E, "list_type" },
1065  { "ext", "extended format", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_EXT }, INT_MIN, INT_MAX, E, "list_type" },
1066  { "ffconcat", "ffconcat format", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_FFCONCAT }, INT_MIN, INT_MAX, E, "list_type" },
1067  { "m3u8", "M3U8 format", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_M3U8 }, INT_MIN, INT_MAX, E, "list_type" },
1068  { "hls", "Apple HTTP Live Streaming compatible", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_M3U8 }, INT_MIN, INT_MAX, E, "list_type" },
1069 
1070  { "segment_atclocktime", "set segment to be cut at clocktime", OFFSET(use_clocktime), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E},
1071  { "segment_clocktime_offset", "set segment clocktime offset", OFFSET(clocktime_offset), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, 86400000000LL, E},
1072  { "segment_clocktime_wrap_duration", "set segment clocktime wrapping duration", OFFSET(clocktime_wrap_duration), AV_OPT_TYPE_DURATION, {.i64 = INT64_MAX}, 0, INT64_MAX, E},
1073  { "segment_time", "set segment duration", OFFSET(time_str),AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
1074  { "segment_time_delta","set approximation value used for the segment times", OFFSET(time_delta), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, E },
1075  { "segment_times", "set segment split time points", OFFSET(times_str),AV_OPT_TYPE_STRING,{.str = NULL}, 0, 0, E },
1076  { "segment_frames", "set segment split frame numbers", OFFSET(frames_str),AV_OPT_TYPE_STRING,{.str = NULL}, 0, 0, E },
1077  { "segment_wrap", "set number after which the index wraps", OFFSET(segment_idx_wrap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
1078  { "segment_list_entry_prefix", "set base url prefix for segments", OFFSET(entry_prefix), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
1079  { "segment_start_number", "set the sequence number of the first segment", OFFSET(segment_idx), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
1080  { "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 },
1081  { "strftime", "set filename expansion with strftime at segment creation", OFFSET(use_strftime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
1082  { "increment_tc", "increment timecode between each segment", OFFSET(increment_tc), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
1083  { "break_non_keyframes", "allow breaking segments on non-keyframes", OFFSET(break_non_keyframes), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E },
1084 
1085  { "individual_header_trailer", "write header/trailer to each segment", OFFSET(individual_header_trailer), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, E },
1086  { "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 },
1087  { "reset_timestamps", "reset timestamps at the beginning of each segment", OFFSET(reset_timestamps), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E },
1088  { "initial_offset", "set initial timestamp offset", OFFSET(initial_offset), AV_OPT_TYPE_DURATION, {.i64 = 0}, -INT64_MAX, INT64_MAX, E },
1089  { "write_empty_segments", "allow writing empty 'filler' segments", OFFSET(write_empty), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E },
1090  { NULL },
1091 };
1092 
1093 #if CONFIG_SEGMENT_MUXER
1094 static const AVClass seg_class = {
1095  .class_name = "segment muxer",
1096  .item_name = av_default_item_name,
1097  .option = options,
1098  .version = LIBAVUTIL_VERSION_INT,
1099 };
1100 
1102  .name = "segment",
1103  .long_name = NULL_IF_CONFIG_SMALL("segment"),
1104  .priv_data_size = sizeof(SegmentContext),
1106  .init = seg_init,
1110  .deinit = seg_free,
1111  .check_bitstream = seg_check_bitstream,
1112  .priv_class = &seg_class,
1113 };
1114 #endif
1115 
1116 #if CONFIG_STREAM_SEGMENT_MUXER
1117 static const AVClass sseg_class = {
1118  .class_name = "stream_segment muxer",
1119  .item_name = av_default_item_name,
1120  .option = options,
1121  .version = LIBAVUTIL_VERSION_INT,
1122 };
1123 
1125  .name = "stream_segment,ssegment",
1126  .long_name = NULL_IF_CONFIG_SMALL("streaming segment muxer"),
1127  .priv_data_size = sizeof(SegmentContext),
1128  .flags = AVFMT_NOFILE,
1129  .init = seg_init,
1133  .deinit = seg_free,
1134  .check_bitstream = seg_check_bitstream,
1135  .priv_class = &sseg_class,
1136 };
1137 #endif
struct SegmentListEntry * next
Definition: segment.c:52
static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int unqueue)
Definition: ffmpeg.c:690
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:1939
#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:1635
char * header_filename
filename to write the output header to
Definition: segment.c:111
AVOption.
Definition: opt.h:246
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition: mux.c:885
#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:90
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:4931
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:333
AVDictionary * format_options
Definition: segment.c:78
static int segment_start(AVFormatContext *s, int write_header)
Definition: segment.c:239
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:3987
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:942
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:106
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:3979
static int parse_frames(void *log_ctx, int **frames, int *nb_frames, const char *frames_str)
Definition: segment.c:524
static int seg_write_header(AVFormatContext *s)
Definition: segment.c:816
static int segment_end(AVFormatContext *s, int write_trailer, int is_last)
Definition: segment.c:354
int list_flags
flags affecting list generation
Definition: segment.c:80
static int segment_mux_init(AVFormatContext *s)
Definition: segment.c:144
Format I/O context.
Definition: avformat.h:1357
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:597
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:1028
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:121
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:1512
void ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
Definition: utils.c:5685
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:5312
static int seg_write_trailer(struct AVFormatContext *s)
Definition: segment.c:986
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4504
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1425
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:1488
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:2527
char * format
format to use for output segment files
Definition: segment.c:77
static int select_reference_stream(AVFormatContext *s)
Definition: segment.c:603
#define av_log(a,...)
int break_non_keyframes
Definition: segment.c:117
int64_t time_delta
Definition: segment.c:108
int64_t initial_offset
initial timestamps offset, expressed in microseconds
Definition: segment.c:114
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1526
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:2043
#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:1597
int individual_header_trailer
Set by a private option.
Definition: segment.c:109
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:1453
#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:3983
simple assert() macros that are a bit more flexible than ISO C assert().
int use_rename
Definition: segment.c:120
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:99
AVRational avg_frame_rate
Average framerate.
Definition: avformat.h:953
char * reference_stream_specifier
reference stream specifier
Definition: segment.c:115
#define FFMAX(a, b)
Definition: common.h:94
static int set_segment_filename(AVFormatContext *s)
Definition: segment.c:195
int64_t offset_pts
Definition: segment.c:50
#define fail()
Definition: checkasm.h:122
int reference_stream_index
Definition: segment.c:116
static int seg_init(AVFormatContext *s)
Definition: segment.c:668
int nb_times
number of elments in the times array
Definition: segment.c:100
#define OFFSET(x)
Definition: segment.c:1047
static int segment_list_open(AVFormatContext *s)
Definition: segment.c:284
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1500
int64_t last_val
remember last time for wrap around detection
Definition: segment.c:86
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:4005
void * opaque
User data.
Definition: avformat.h:1863
Use auto-selected escaping mode.
Definition: avstring.h:319
AVIOContext * list_pb
list file put-byte context
Definition: segment.c:92
common internal API header
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1413
int ff_rename(const char *url_src, const char *url_dst, void *logctx)
Wrap avpriv_io_move and log if error happens.
Definition: avio.c:670
AVBSFContext ** bsfcs
bitstream filters to run on stream
Definition: internal.h:159
static void print_csv_escaped_str(AVIOContext *ctx, const char *str)
Definition: segment.c:128
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:3323
int cut_pending
Definition: segment.c:87
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:516
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:95
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:113
int use_clocktime
flag to cut segments at regular clock time
Definition: segment.c:83
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:1688
int increment_tc
flag to increment timecode if found
Definition: segment.c:96
void ff_format_set_url(AVFormatContext *s, char *url)
Set AVFormatContext url field to the provided pointer.
Definition: utils.c:5845
AVDictionary * metadata
Definition: avformat.h:944
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:496
#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:848
int av_get_frame_filename(char *buf, int buf_size, const char *path, int number)
Definition: utils.c:4772
ff_const59 struct AVOutputFormat * oformat
The output container format.
Definition: avformat.h:1376
static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: segment.c:861
if(ret)
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
Stream structure.
Definition: avformat.h:880
char * list
filename for the segment list file
Definition: segment.c:79
char * frames_str
segment frame numbers specification string
Definition: segment.c:102
The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format that the extradata buffer was...
Definition: avcodec.h:1211
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:1237
static void seg_free(AVFormatContext *s)
Definition: segment.c:660
#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:88
Timecode helpers header.
AVIOContext * pb
I/O context.
Definition: avformat.h:1399
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:94
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:1945
void * buf
Definition: avisynth_c.h:766
int list_type
set the list type
Definition: segment.c:91
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:103
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:93
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:4435
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:472
SegmentListEntry * segment_list_entries
Definition: segment.c:124
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:564
int nb_frames
number of elments in the frames array
Definition: segment.c:104
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:110
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:319
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:1612
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:84
int write_empty
Definition: segment.c:118
#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:85
int disposition
AV_DISPOSITION_* bit field.
Definition: avformat.h:933
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:1048
int pts_wrap_bits
number of bits in pts (used for wrapping control)
Definition: avformat.h:1072
#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:466
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:84
void * priv_data
Format private data.
Definition: avformat.h:1385
static const AVOption options[]
Definition: segment.c:1049
#define AV_ESCAPE_FLAG_WHITESPACE
Consider spaces special and escape them even in the middle of the string.
Definition: avstring.h:332
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:349
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: avcodec.h:4001
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
Definition: avcodec.h:1493
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition: mux.c:1258
static int open_null_ctx(AVIOContext **ctx)
Definition: segment.c:583
#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:1027
char * times_str
segment times specification string
Definition: segment.c:98
#define av_malloc_array(a, b)
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition: avcodec.h:3991
int stream_index
Definition: avcodec.h:1496
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avformat.h:909
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:123
#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:81
deprecated
Definition: segment.c:61
This structure stores compressed data.
Definition: avcodec.h:1471
int frame_count
total number of reference frames
Definition: segment.c:105
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition: opt.c:467
#define SEGMENT_LIST_FLAG_LIVE
Definition: segment.c:67
SegmentListEntry * segment_list_entries_end
Definition: segment.c:125
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1487
#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