History

avformat/dashenc: allow splitting fragments following P-Frame reordering

James Almer committed 7 years ago

Commit ea5a9101 parent ceb236c1 file · +67 −2Browse files

Unified · Split

libavformat/dashenc.c+67−2
@@ -62,6 +62,7 @@ enum { · 61 unmodified lines
62 FRAG_TYPE_NONE = 0,62 FRAG_TYPE_NONE = 0,
63 FRAG_TYPE_EVERY_FRAME,63 FRAG_TYPE_EVERY_FRAME,
64 FRAG_TYPE_DURATION,64 FRAG_TYPE_DURATION,
65 FRAG_TYPE_PFRAMES,
65 FRAG_TYPE_NB66 FRAG_TYPE_NB
66};67};
67 68
@@ -91,6 +92,8 @@ typedef struct OutputStream { · 23 unmodified lines
91 AVFormatContext *ctx;92 AVFormatContext *ctx;
92 int ctx_inited, as_idx;93 int ctx_inited, as_idx;
93 AVIOContext *out;94 AVIOContext *out;
95 AVCodecParserContext *parser;
96 AVCodecContext *parser_avctx;
94 int packets_written;97 int packets_written;
95 char initfile[1024];98 char initfile[1024];
96 int64_t init_start_pos, pos;99 int64_t init_start_pos, pos;
@@ -102,6 +105,7 @@ typedef struct OutputStream { · 5 unmodified lines
102 Segment **segments;105 Segment **segments;
103 int64_t first_pts, start_pts, max_pts;106 int64_t first_pts, start_pts, max_pts;
104 int64_t last_dts, last_pts;107 int64_t last_dts, last_pts;
108 int last_flags;
105 int bit_rate;109 int bit_rate;
106 SegmentType segment_type; /* segment type selected for this particular stream */110 SegmentType segment_type; /* segment type selected for this particular stream */
107 const char *format_name;111 const char *format_name;
@@ -117,6 +121,7 @@ typedef struct OutputStream { · 9 unmodified lines
117 char temp_path[1024];121 char temp_path[1024];
118 double availability_time_offset;122 double availability_time_offset;
119 int total_pkt_size;123 int total_pkt_size;
124 int64_t total_pkt_duration;
120 int muxer_overhead;125 int muxer_overhead;
121 int frag_type;126 int frag_type;
122} OutputStream;127} OutputStream;
@@ -606,6 +611,8 @@ static void dash_free(AVFormatContext *s) · 483 unmodified lines
606 }611 }
607 ff_format_io_close(s, &os->out);612 ff_format_io_close(s, &os->out);
608 avformat_free_context(os->ctx);613 avformat_free_context(os->ctx);
614 avcodec_free_context(&os->parser_avctx);
615 av_parser_close(os->parser);
609 for (j = 0; j < os->nb_segments; j++)616 for (j = 0; j < os->nb_segments; j++)
610 av_free(os->segments[j]);617 av_free(os->segments[j]);
611 av_free(os->segments);618 av_free(os->segments);
@@ -933,6 +940,8 @@ static int parse_adaptation_sets(AVFormatContext *s) · 321 unmodified lines
933 940
934 if (!strcmp(type_str, "duration"))941 if (!strcmp(type_str, "duration"))
935 as->frag_type = FRAG_TYPE_DURATION;942 as->frag_type = FRAG_TYPE_DURATION;
943 else if (!strcmp(type_str, "pframes"))
944 as->frag_type = FRAG_TYPE_PFRAMES;
936 else if (!strcmp(type_str, "every_frame"))945 else if (!strcmp(type_str, "every_frame"))
937 as->frag_type = FRAG_TYPE_EVERY_FRAME;946 as->frag_type = FRAG_TYPE_EVERY_FRAME;
938 else if (!strcmp(type_str, "none"))947 else if (!strcmp(type_str, "none"))
@@ -1349,6 +1358,18 @@ static int dash_init(AVFormatContext *s) · 410 unmodified lines
1349 ctx->avoid_negative_ts = s->avoid_negative_ts;1358 ctx->avoid_negative_ts = s->avoid_negative_ts;
1350 ctx->flags = s->flags;1359 ctx->flags = s->flags;
1351 1360
1361 os->parser = av_parser_init(st->codecpar->codec_id);
1362 if (os->parser) {
1363 os->parser_avctx = avcodec_alloc_context3(NULL);
1364 if (!os->parser_avctx)
1365 return AVERROR(ENOMEM);
1366 ret = avcodec_parameters_to_context(os->parser_avctx, st->codecpar);
1367 if (ret < 0)
1368 return ret;
1369 // We only want to parse frame headers
1370 os->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
1371 }
1372
1352 if (c->single_file) {1373 if (c->single_file) {
1353 if (os->single_file_name)1374 if (os->single_file_name)
1354 ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), os->single_file_name, i, 0, os->bit_rate, 0);1375 ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), os->single_file_name, i, 0, os->bit_rate, 0);
@@ -1391,6 +1412,11 @@ static int dash_init(AVFormatContext *s) · 36 unmodified lines
1391 av_log(s, AV_LOG_ERROR, "Fragment duration %"PRId64" is longer than Segment duration %"PRId64"\n", os->frag_duration, os->seg_duration);1412 av_log(s, AV_LOG_ERROR, "Fragment duration %"PRId64" is longer than Segment duration %"PRId64"\n", os->frag_duration, os->seg_duration);
1392 return AVERROR(EINVAL);1413 return AVERROR(EINVAL);
1393 }1414 }
1415 if (os->frag_type == FRAG_TYPE_PFRAMES && (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO || !os->parser)) {
1416 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !os->parser)
1417 av_log(s, AV_LOG_WARNING, "frag_type set to P-Frame reordering, but no parser found for stream %d\n", i);
1418 os->frag_type = c->streaming ? FRAG_TYPE_EVERY_FRAME : FRAG_TYPE_NONE;
1419 }
1394 1420
1395 if (os->segment_type == SEGMENT_TYPE_MP4) {1421 if (os->segment_type == SEGMENT_TYPE_MP4) {
1396 if (c->streaming)1422 if (c->streaming)
@@ -1458,6 +1484,8 @@ static int dash_init(AVFormatContext *s) · 61 unmodified lines
1458 av_log(s, AV_LOG_WARNING, "no video stream and no seg duration set\n");1484 av_log(s, AV_LOG_WARNING, "no video stream and no seg duration set\n");
1459 return AVERROR(EINVAL);1485 return AVERROR(EINVAL);
1460 }1486 }
1487 if (!c->has_video && c->frag_type == FRAG_TYPE_PFRAMES)
1488 av_log(s, AV_LOG_WARNING, "no video stream and P-frame fragmentation set\n");
1461 1489
1462 c->nr_of_streams_flushed = 0;1490 c->nr_of_streams_flushed = 0;
1463 1491
@@ -1730,6 +1758,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) · 266 unmodified lines
1730 av_rescale_q(os->max_pts - os->start_pts,1758 av_rescale_q(os->max_pts - os->start_pts,
1731 st->time_base, AV_TIME_BASE_Q);1759 st->time_base, AV_TIME_BASE_Q);
1732 os->total_pkt_size = 0;1760 os->total_pkt_size = 0;
1761 os->total_pkt_duration = 0;
1733 1762
1734 if (!os->bit_rate) {1763 if (!os->bit_rate) {
1735 // calculate average bitrate of first segment1764 // calculate average bitrate of first segment
@@ -1831,6 +1860,9 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) · 95 unmodified lines
1831 sizeof(c->availability_start_time));1860 sizeof(c->availability_start_time));
1832 }1861 }
1833 1862
1863 if (!os->packets_written)
1864 os->availability_time_offset = 0;
1865
1834 if (!os->availability_time_offset &&1866 if (!os->availability_time_offset &&
1835 ((os->frag_type == FRAG_TYPE_DURATION && os->seg_duration != os->frag_duration) ||1867 ((os->frag_type == FRAG_TYPE_DURATION && os->seg_duration != os->frag_duration) ||
1836 (os->frag_type == FRAG_TYPE_EVERY_FRAME && pkt->duration))) {1868 (os->frag_type == FRAG_TYPE_EVERY_FRAME && pkt->duration))) {
@@ -1895,11 +1927,43 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) · 58 unmodified lines
1895 os->max_pts = pkt->pts + pkt->duration;1927 os->max_pts = pkt->pts + pkt->duration;
1896 else1928 else
1897 os->max_pts = FFMAX(os->max_pts, pkt->pts + pkt->duration);1929 os->max_pts = FFMAX(os->max_pts, pkt->pts + pkt->duration);
1898 os->packets_written++;1930
1899 os->total_pkt_size += pkt->size;1931 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
1932 os->frag_type == FRAG_TYPE_PFRAMES &&
1933 os->packets_written) {
1934 uint8_t *data;
1935 int size;
1936
1937 av_assert0(os->parser);
1938 av_parser_parse2(os->parser, os->parser_avctx,
1939 &data, &size, pkt->data, pkt->size,
1940 pkt->pts, pkt->dts, pkt->pos);
1941
1942 if ((os->parser->pict_type == AV_PICTURE_TYPE_P &&
1943 st->codecpar->video_delay &&
1944 !(os->last_flags & AV_PKT_FLAG_KEY)) ||
1945 pkt->flags & AV_PKT_FLAG_KEY) {
1946 ret = av_write_frame(os->ctx, NULL);
1947 if (ret < 0)
1948 return ret;
1949
1950 if (!os->availability_time_offset) {
1951 int64_t frag_duration = av_rescale_q(os->total_pkt_duration, st->time_base,
1952 AV_TIME_BASE_Q);
1953 os->availability_time_offset = ((double) os->seg_duration -
1954 frag_duration) / AV_TIME_BASE;
1955 }
1956 }
1957 }
1958
1900 if ((ret = ff_write_chained(os->ctx, 0, pkt, s, 0)) < 0)1959 if ((ret = ff_write_chained(os->ctx, 0, pkt, s, 0)) < 0)
1901 return ret;1960 return ret;
1902 1961
1962 os->packets_written++;
1963 os->total_pkt_size += pkt->size;
1964 os->total_pkt_duration += pkt->duration;
1965 os->last_flags = pkt->flags;
1966
1903 if (!os->init_range_length)1967 if (!os->init_range_length)
1904 flush_init_segment(s, os);1968 flush_init_segment(s, os);
1905 1969
@@ -2026,6 +2090,7 @@ static const AVOption options[] = { · 120 unmodified lines
2026 { "none", "one fragment per segment", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_NONE }, 0, UINT_MAX, E, "frag_type"},2090 { "none", "one fragment per segment", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_NONE }, 0, UINT_MAX, E, "frag_type"},
2027 { "every_frame", "fragment at every frame", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_EVERY_FRAME }, 0, UINT_MAX, E, "frag_type"},2091 { "every_frame", "fragment at every frame", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_EVERY_FRAME }, 0, UINT_MAX, E, "frag_type"},
2028 { "duration", "fragment at specific time intervals", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_DURATION }, 0, UINT_MAX, E, "frag_type"},2092 { "duration", "fragment at specific time intervals", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_DURATION }, 0, UINT_MAX, E, "frag_type"},
2093 { "pframes", "fragment at keyframes and following P-Frame reordering (Video only, experimental)", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_PFRAMES }, 0, UINT_MAX, E, "frag_type"},
2029 { "remove_at_exit", "remove all segments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },2094 { "remove_at_exit", "remove all segments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
2030 { "use_template", "Use SegmentTemplate instead of SegmentList", OFFSET(use_template), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },2095 { "use_template", "Use SegmentTemplate instead of SegmentList", OFFSET(use_template), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
2031 { "use_timeline", "Use SegmentTimeline in SegmentTemplate", OFFSET(use_timeline), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },2096 { "use_timeline", "Use SegmentTimeline in SegmentTemplate", OFFSET(use_timeline), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t