int64_t time_delta;
int individual_header_trailer; /**< Set by a private option. */
int write_header_trailer; /**< Set by a private option. */
+ char *header_filename; ///< filename to write the output header to
int reset_timestamps; ///< reset timestamps at the begin of each segment
int64_t initial_offset; ///< initial timestamps offset, expressed in microseconds
}
seg->segment_idx++;
- if ((seg->segment_idx_wrap) && (seg->segment_idx%seg->segment_idx_wrap == 0))
+ if ((seg->segment_idx_wrap) && (seg->segment_idx % seg->segment_idx_wrap == 0))
seg->segment_idx_wrap_nb++;
if ((err = set_segment_filename(s)) < 0)
av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->filename);
return err;
}
+ if (!seg->individual_header_trailer)
+ oc->pb->seekable = 0;
if (oc->oformat->priv_class && oc->priv_data)
av_opt_set(oc->priv_data, "mpegts_flags", "+resend_headers", 0);
av_freep(&entry);
}
- avio_closep(&seg->list_pb);
if ((ret = segment_list_open(s)) < 0)
goto end;
for (entry = seg->segment_list_entries; entry; entry = entry->next)
segment_list_print_entry(seg->list_pb, seg->list_type, entry, s);
if (seg->list_type == LIST_TYPE_M3U8 && is_last)
avio_printf(seg->list_pb, "#EXT-X-ENDLIST\n");
+ avio_closep(&seg->list_pb);
} else {
segment_list_print_entry(seg->list_pb, seg->list_type, &seg->cur_entry, s);
+ avio_flush(seg->list_pb);
}
- avio_flush(seg->list_pb);
}
av_log(s, AV_LOG_VERBOSE, "segment:'%s' count:%d ended\n",
if (!seg->write_header_trailer)
seg->individual_header_trailer = 0;
+ if (seg->header_filename) {
+ seg->write_header_trailer = 1;
+ seg->individual_header_trailer = 0;
+ }
+
if (!!seg->time_str + !!seg->times_str + !!seg->frames_str > 1) {
av_log(s, AV_LOG_ERROR,
"segment_time, segment_times, and segment_frames options "
else if (av_match_ext(seg->list, "ffcat,ffconcat")) seg->list_type = LIST_TYPE_FFCONCAT;
else seg->list_type = LIST_TYPE_FLAT;
}
- if ((ret = segment_list_open(s)) < 0)
- goto fail;
+ if (!seg->list_size && seg->list_type != LIST_TYPE_M3U8)
+ if ((ret = segment_list_open(s)) < 0)
+ goto fail;
}
if (seg->list_type == LIST_TYPE_EXT)
av_log(s, AV_LOG_WARNING, "'ext' list type option is deprecated in favor of 'csv'\n");
goto fail;
if (seg->write_header_trailer) {
- if ((ret = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
+ if ((ret = avio_open2(&oc->pb, seg->header_filename ? seg->header_filename : oc->filename, AVIO_FLAG_WRITE,
&s->interrupt_callback, NULL)) < 0) {
av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->filename);
goto fail;
}
+ if (!seg->individual_header_trailer)
+ oc->pb->seekable = 0;
} else {
if ((ret = open_null_ctx(&oc->pb)) < 0)
goto fail;
if (oc->avoid_negative_ts > 0 && s->avoid_negative_ts < 0)
s->avoid_negative_ts = 1;
- if (!seg->write_header_trailer) {
- close_null_ctxp(&oc->pb);
+ if (!seg->write_header_trailer || seg->header_filename) {
+ if (seg->header_filename) {
+ av_write_frame(oc, NULL);
+ avio_closep(&oc->pb);
+ } else {
+ close_null_ctxp(&oc->pb);
+ }
if ((ret = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
&s->interrupt_callback, NULL)) < 0)
goto fail;
+ if (!seg->individual_header_trailer)
+ oc->pb->seekable = 0;
}
fail:
int64_t avgt = av_gettime();
time_t sec = avgt / 1000000;
localtime_r(&sec, &ti);
- usecs = (int64_t)(ti.tm_hour*3600 + ti.tm_min*60 + ti.tm_sec) * 1000000 + (avgt % 1000000);
+ usecs = (int64_t)(ti.tm_hour * 3600 + ti.tm_min * 60 + ti.tm_sec) * 1000000 + (avgt % 1000000);
wrapped_val = usecs % seg->time;
if (seg->last_cut != usecs && wrapped_val < seg->last_val) {
seg->cut_pending = 1;
}
seg->last_val = wrapped_val;
} else {
- end_pts = seg->time * (seg->segment_count+1);
+ end_pts = seg->time * (seg->segment_count + 1);
}
}
goto fail;
seg->cut_pending = 0;
- seg->cur_entry.index = seg->segment_idx + seg->segment_idx_wrap*seg->segment_idx_wrap_nb;
+ seg->cur_entry.index = seg->segment_idx + seg->segment_idx_wrap * seg->segment_idx_wrap_nb;
seg->cur_entry.start_time = (double)pkt->pts * av_q2d(st->time_base);
seg->cur_entry.start_pts = av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q);
seg->cur_entry.end_time = seg->cur_entry.start_time +
{ "segment_format", "set container format used for the segments", OFFSET(format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
{ "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 },
{ "segment_list", "set the segment list filename", OFFSET(list), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
+ { "segment_header_filename", "write a single file containing the header", OFFSET(header_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
{ "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"},
{ "cache", "allow list caching", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_LIST_FLAG_CACHE }, INT_MIN, INT_MAX, E, "list_flags"},