&s->interrupt_callback, NULL)) < 0)
return err;
- if (!oc->priv_data && oc->oformat->priv_data_size > 0) {
- oc->priv_data = av_mallocz(oc->oformat->priv_data_size);
- if (!oc->priv_data) {
- avio_close(oc->pb);
- return AVERROR(ENOMEM);
- }
- if (oc->oformat->priv_class) {
- *(const AVClass**)oc->priv_data = oc->oformat->priv_class;
- av_opt_set_defaults(oc->priv_data);
- }
- }
-
- if ((err = oc->oformat->write_header(oc)) < 0) {
- goto fail;
- }
+ if ((err = avformat_write_header(oc, NULL)) < 0)
+ return err;
return 0;
-
- fail:
- av_log(oc, AV_LOG_ERROR, "Failure occurred when starting segment '%s'\n",
- oc->filename);
- avio_close(oc->pb);
- av_freep(&oc->priv_data);
-
- return err;
}
-static int segment_end(AVFormatContext *oc)
+static int segment_list_open(AVFormatContext *s)
+{
+ SegmentContext *seg = s->priv_data;
+ int ret;
+
+ ret = avio_open2(&seg->list_pb, seg->list, AVIO_FLAG_WRITE,
+ &s->interrupt_callback, NULL);
+ if (ret < 0)
+ return ret;
+ seg->list_max_segment_time = 0;
+
+ if (seg->list_type == LIST_TYPE_M3U8) {
+ avio_printf(seg->list_pb, "#EXTM3U\n");
+ avio_printf(seg->list_pb, "#EXT-X-VERSION:3\n");
+ avio_printf(seg->list_pb, "#EXT-X-MEDIA-SEQUENCE:%d\n", seg->list_count);
+ avio_printf(seg->list_pb, "#EXT-X-ALLOWCACHE:%d\n",
+ !!(seg->list_flags & SEGMENT_LIST_FLAG_CACHE));
+ if (seg->list_flags & SEGMENT_LIST_FLAG_LIVE)
+ avio_printf(seg->list_pb,
+ "#EXT-X-TARGETDURATION:%"PRId64"\n", seg->time / 1000000);
+ }
+
+ return ret;
+}
+
+static void segment_list_close(AVFormatContext *s)
+{
+ SegmentContext *seg = s->priv_data;
+
+ if (seg->list_type == LIST_TYPE_M3U8) {
+ if (!(seg->list_flags & SEGMENT_LIST_FLAG_LIVE))
+ avio_printf(seg->list_pb, "#EXT-X-TARGETDURATION:%d\n",
+ (int)ceil(seg->list_max_segment_time));
+ avio_printf(seg->list_pb, "#EXT-X-ENDLIST\n");
+ }
+ seg->list_count++;
+
+ avio_close(seg->list_pb);
+}
+
+static int segment_end(AVFormatContext *s)
{
+ SegmentContext *seg = s->priv_data;
+ AVFormatContext *oc = seg->avf;
int ret = 0;
- if (oc->oformat->write_trailer)
- ret = oc->oformat->write_trailer(oc);
- av_write_trailer(oc);
++ ret = av_write_trailer(oc);
+
+ if (ret < 0)
+ av_log(s, AV_LOG_ERROR, "Failure occurred when ending segment '%s'\n",
+ oc->filename);
+
+ if (seg->list) {
+ if (seg->list_size && !(seg->segment_count % seg->list_size)) {
+ segment_list_close(s);
+ if ((ret = segment_list_open(s)) < 0)
+ goto end;
+ }
+
+ if (seg->list_type == LIST_TYPE_FLAT) {
+ avio_printf(seg->list_pb, "%s\n", oc->filename);
+ } else if (seg->list_type == LIST_TYPE_CSV || seg->list_type == LIST_TYPE_EXT) {
+ print_csv_escaped_str(seg->list_pb, oc->filename);
+ avio_printf(seg->list_pb, ",%f,%f\n", seg->start_time, seg->end_time);
+ } else if (seg->list_type == LIST_TYPE_M3U8) {
+ avio_printf(seg->list_pb, "#EXTINF:%f,\n%s\n",
+ seg->end_time - seg->start_time, oc->filename);
+ }
+ seg->list_max_segment_time = FFMAX(seg->end_time - seg->start_time, seg->list_max_segment_time);
+ avio_flush(seg->list_pb);
+ }
+
+end:
avio_close(oc->pb);
- if (oc->oformat->priv_class)
- av_opt_free(oc->priv_data);
- av_freep(&oc->priv_data);
return ret;
}