History

Merge commit 'c94e2e85cb6af8a570d8542a830556243bd32873'

* commit 'c94e2e85cb6af8a570d8542a830556243bd32873': nut: Support experimental NUT 4 features Conflicts: doc/nut.texi libavformat/nut.h libavformat/nutdec.c libavformat/nutenc.c

Michael Niedermayer committed 12 years ago

Commit a8499cb2 parents d858ee7 c94e2e85 files · +111 −9Browse files

Unified · Split

5 files
  1. doc/muxers.texi +17 −0
  2. doc/nut.texi +21 −0
  3. libavformat/nut.h +8 −2
  4. libavformat/nutdec.c +23 −4
  5. libavformat/nutenc.c +42 −3
doc/muxers.texi+17−0
@@ -706,6 +706,23 @@ Alternatively you can write the command as: · 705 unmodified lines
706706 ffmpeg -benchmark -i INPUT -f null -
707707 @end example
708708
709+@section nut
710+
711+@table @option
712+@item -syncpoints @var{flags}
713+Change the syncpoint usage in nut:
714+@table @option
715+@item @var{default} use the normal low-overhead seeking aids.
716+@item @var{none} do not use the syncpoints at all, reducing the overhead but making the stream non-seekable;
717+@item @var{timestamped} extend the syncpoint with a wallclock field.
718+@end table
719+The @var{none} and @var{timestamped} flags are experimental.
720+@end table
721+
722+@example
723+ffmpeg -i INPUT -f_strict experimental -syncpoints none - | processor
724+@end example
725+
709726 @section ogg
710727
711728 Ogg container muxer.
doc/nut.texi+21−0
@@ -21,6 +21,27 @@ The official nut specification is at svn://svn.mplayerhq.hu/nut · 20 unmodified lines
2121 In case of any differences between this text and the official specification,
2222 the official specification shall prevail.
2323
24+@chapter Modes
25+NUT has some variants signaled by using the flags field in its main header.
26+
27+@multitable @columnfractions .4 .4
28+@item BROADCAST @tab Extend the syncpoint to report the sender wallclock
29+@item PIPE @tab Omit completely the syncpoint
30+@end multitable
31+
32+@section BROADCAST
33+
34+The BROADCAST variant provides a secondary time reference to facilitate
35+detecting endpoint latency and network delays.
36+It assumes all the endpoint clocks are syncronized.
37+To be used in real-time scenarios.
38+
39+@section PIPE
40+
41+The PIPE variant assumes NUT is used as non-seekable intermediate container,
42+by not using syncpoint removes unneeded overhead and reduces the overall
43+memory usage.
44+
2445 @chapter Container-specific codec tags
2546
2647 @section Generic raw YUVA formats
libavformat/nut.h+8−2
@@ -36,7 +36,9 @@ · 35 unmodified lines
3636
3737 #define MAX_DISTANCE (1024*32-1)
3838
39−#define NUT_VERSION 3
39+#define NUT_MAX_VERSION 4
40+#define NUT_STABLE_VERSION 3
41+#define NUT_MIN_VERSION 2
4042
4143 typedef enum{
4244 FLAG_KEY = 1, ///<if set, frame is keyframe
@@ -87,6 +89,7 @@ typedef struct ChapterContext { · 44 unmodified lines
8789 } ChapterContext;
8890
8991 typedef struct NUTContext {
92+ const AVClass *av_class;
9093 AVFormatContext *avf;
9194 // int written_packet_size;
9295 // int64_t packet_start;
@@ -105,7 +108,10 @@ typedef struct NUTContext { · 12 unmodified lines
105108 int sp_count;
106109 int64_t max_pts;
107110 AVRational *max_pts_tb;
108− int version;
111+#define NUT_BROADCAST 1 // use extended syncpoints
112+#define NUT_PIPE 2 // do not write syncpoints
113+ int flags;
114+ int version; // version currently in use
109115 int minor_version;
110116 } NUTContext;
111117
libavformat/nutdec.c+23−4
@@ -229,7 +229,7 @@ static int decode_main_header(NUTContext *nut) · 228 unmodified lines
229229 end += avio_tell(bc);
230230
231231 tmp = ffio_read_varlen(bc);
232− if (tmp < 2 && tmp > 4) {
232+ if (tmp < NUT_MIN_VERSION && tmp > NUT_MAX_VERSION) {
233233 av_log(s, AV_LOG_ERROR, "Version %"PRId64" not supported.\n",
234234 tmp);
235235 return AVERROR(ENOSYS);
@@ -340,6 +340,11 @@ static int decode_main_header(NUTContext *nut) · 104 unmodified lines
340340 av_assert0(nut->header_len[0] == 0);
341341 }
342342
343+ // flags had been effectively introduced in version 4
344+ if (nut->version > NUT_STABLE_VERSION) {
345+ nut->flags = ffio_read_varlen(bc);
346+ }
347+
343348 if (skip_reserved(bc, end) || ffio_get_checksum(bc)) {
344349 av_log(s, AV_LOG_ERROR, "main header checksum mismatch\n");
345350 return AVERROR_INVALIDDATA;
@@ -578,6 +583,14 @@ static int decode_syncpoint(NUTContext *nut, int64_t *ts, int64_t *back_ptr) · 232 unmodified lines
578583 ff_nut_reset_ts(nut, nut->time_base[tmp % nut->time_base_count],
579584 tmp / nut->time_base_count);
580585
586+ if (nut->flags & NUT_BROADCAST) {
587+ tmp = ffio_read_varlen(bc);
588+ av_log(s, AV_LOG_VERBOSE, "Syncpoint wallclock %"PRId64"\n",
589+ av_rescale_q(tmp / nut->time_base_count,
590+ nut->time_base[tmp % nut->time_base_count],
591+ AV_TIME_BASE_Q));
592+ }
593+
581594 if (skip_reserved(bc, end) || ffio_get_checksum(bc)) {
582595 av_log(s, AV_LOG_ERROR, "sync point checksum mismatch\n");
583596 return AVERROR_INVALIDDATA;
@@ -898,7 +911,8 @@ static int decode_frame_header(NUTContext *nut, int64_t *pts, int *stream_id, · 314 unmodified lines
898911 int size, flags, size_mul, pts_delta, i, reserved_count;
899912 uint64_t tmp;
900913
901− if (avio_tell(bc) > nut->last_syncpoint_pos + nut->max_distance) {
914+ if (!(nut->flags & NUT_PIPE) &&
915+ avio_tell(bc) > nut->last_syncpoint_pos + nut->max_distance) {
902916 av_log(s, AV_LOG_ERROR,
903917 "Last frame must have been damaged %"PRId64" > %"PRId64" + %d\n",
904918 avio_tell(bc), nut->last_syncpoint_pos, nut->max_distance);
@@ -951,8 +965,9 @@ static int decode_frame_header(NUTContext *nut, int64_t *pts, int *stream_id, · 46 unmodified lines
951965
952966 if (flags & FLAG_CHECKSUM) {
953967 avio_rb32(bc); // FIXME check this
954− } else if (size > 2 * nut->max_distance || FFABS(stc->last_pts - *pts) >
955− stc->max_pts_distance) {
968+ } else if (!(nut->flags & NUT_PIPE) &&
969+ size > 2 * nut->max_distance ||
970+ FFABS(stc->last_pts - *pts) > stc->max_pts_distance) {
956971 av_log(s, AV_LOG_ERROR, "frame size > 2max_distance and no checksum\n");
957972 return AVERROR_INVALIDDATA;
958973 }
@@ -1118,6 +1133,10 @@ static int read_seek(AVFormatContext *s, int stream_index, · 159 unmodified lines
11181133 int64_t pos, pos2, ts;
11191134 int i;
11201135
1136+ if (nut->flags & NUT_PIPE) {
1137+ return AVERROR(ENOSYS);
1138+ }
1139+
11211140 if (st->index_entries) {
11221141 int index = av_index_search_timestamp(st, pts, flags);
11231142 if (index < 0)
libavformat/nutenc.c+42−3
@@ -26,6 +26,8 @@ · 25 unmodified lines
2626 #include "libavutil/tree.h"
2727 #include "libavutil/dict.h"
2828 #include "libavutil/avassert.h"
29+#include "libavutil/time.h"
30+#include "libavutil/opt.h"
2931 #include "libavcodec/bytestream.h"
3032 #include "libavcodec/mpegaudiodata.h"
3133 #include "nut.h"
@@ -338,7 +340,7 @@ static void write_mainheader(NUTContext *nut, AVIOContext *bc) · 306 unmodified lines
338340 tmp_head_idx;
339341 int64_t tmp_match;
340342
341− ff_put_v(bc, nut->version = NUT_VERSION);
343+ ff_put_v(bc, nut->version);
342344 if (nut->version > 3)
343345 ff_put_v(bc, nut->minor_version);
344346 ff_put_v(bc, nut->avf->nb_streams);
@@ -407,6 +409,9 @@ static void write_mainheader(NUTContext *nut, AVIOContext *bc) · 62 unmodified lines
407409 ff_put_v(bc, nut->header_len[i]);
408410 avio_write(bc, nut->header[i], nut->header_len[i]);
409411 }
412+ // flags had been effectively introduced in version 4
413+ if (nut->version > NUT_STABLE_VERSION)
414+ ff_put_v(bc, nut->flags);
410415 }
411416
412417 static int write_streamheader(AVFormatContext *avctx, AVIOContext *bc,
@@ -692,6 +697,16 @@ static int nut_write_header(AVFormatContext *s) · 279 unmodified lines
692697
693698 nut->avf = s;
694699
700+ nut->version = NUT_STABLE_VERSION + !!nut->flags;
701+ if (nut->flags && s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
702+ av_log(s, AV_LOG_ERROR,
703+ "The additional syncpoint modes require version %d, "
704+ "that is currently not finalized, "
705+ "please set -f_strict experimental in order to enable it.\n",
706+ nut->version);
707+ return AVERROR_EXPERIMENTAL;
708+ }
709+
695710 nut->stream = av_calloc(s->nb_streams, sizeof(*nut->stream ));
696711 nut->chapter = av_calloc(s->nb_chapters, sizeof(*nut->chapter));
697712 nut->time_base= av_calloc(s->nb_streams +
@@ -974,7 +989,8 @@ static int nut_write_packet(AVFormatContext *s, AVPacket *pkt) · 276 unmodified lines
974989
975990 //FIXME: Ensure store_sp is 1 in the first place.
976991
977− if (store_sp) {
992+ if (store_sp &&
993+ (!(nut->flags & NUT_PIPE) || nut->last_syncpoint_pos == INT_MIN)) {
978994 Syncpoint *sp, dummy = { .pos = INT64_MAX };
979995
980996 ff_nut_reset_ts(nut, *nus->time_base, pkt->dts);
@@ -1000,6 +1016,11 @@ static int nut_write_packet(AVFormatContext *s, AVPacket *pkt) · 19 unmodified lines
10001016 return ret;
10011017 put_tt(nut, nus->time_base, dyn_bc, pkt->dts);
10021018 ff_put_v(dyn_bc, sp ? (nut->last_syncpoint_pos - sp->pos) >> 4 : 0);
1019+
1020+ if (nut->flags & NUT_BROADCAST) {
1021+ put_tt(nut, nus->time_base, dyn_bc,
1022+ av_rescale_q(av_gettime(), AV_TIME_BASE_Q, *nus->time_base));
1023+ }
10031024 put_packet(nut, bc, dyn_bc, 1, SYNCPOINT_STARTCODE);
10041025
10051026 if ((ret = ff_nut_add_sp(nut, nut->last_syncpoint_pos, 0 /*unused*/, pkt->dts)) < 0)
@@ -1110,7 +1131,7 @@ static int nut_write_packet(AVFormatContext *s, AVPacket *pkt) · 104 unmodified lines
11101131 nus->last_pts = pkt->pts;
11111132
11121133 //FIXME just store one per syncpoint
1113− if (flags & FLAG_KEY) {
1134+ if (flags & FLAG_KEY && !(nut->flags & NUT_PIPE)) {
11141135 av_add_index_entry(
11151136 s->streams[pkt->stream_index],
11161137 nut->last_syncpoint_pos,
@@ -1156,6 +1177,23 @@ static int nut_write_trailer(AVFormatContext *s) · 39 unmodified lines
11561177 return 0;
11571178 }
11581179
1180+#define OFFSET(x) offsetof(NUTContext, x)
1181+#define E AV_OPT_FLAG_ENCODING_PARAM
1182+static const AVOption options[] = {
1183+ { "syncpoints", "NUT syncpoint behaviour", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, E, "syncpoints" },
1184+ { "default", "", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, INT_MIN, INT_MAX, E, "syncpoints" },
1185+ { "none", "Disable syncpoints, low overhead and unseekable", 0, AV_OPT_TYPE_CONST, {.i64 = NUT_PIPE}, INT_MIN, INT_MAX, E, "syncpoints" },
1186+ { "timestamped", "Extend syncpoints with a wallclock timestamp", 0, AV_OPT_TYPE_CONST, {.i64 = NUT_BROADCAST}, INT_MIN, INT_MAX, E, "syncpoints" },
1187+ { NULL },
1188+};
1189+
1190+static const AVClass class = {
1191+ .class_name = "nutenc",
1192+ .item_name = av_default_item_name,
1193+ .option = options,
1194+ .version = LIBAVUTIL_VERSION_INT,
1195+};
1196+
11591197 AVOutputFormat ff_nut_muxer = {
11601198 .name = "nut",
11611199 .long_name = NULL_IF_CONFIG_SMALL("NUT"),
@@ -1170,4 +1208,5 @@ AVOutputFormat ff_nut_muxer = { · 8 unmodified lines
11701208 .write_trailer = nut_write_trailer,
11711209 .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS,
11721210 .codec_tag = ff_nut_codec_tags,
1211+ .priv_class = &class,
11731212 };

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