On Mon, Dec 17, 2018 at 06:04:40PM +0100, Paul B Mahol wrote: > Hi, > > patches attached.
> nut.h | 2 + > nutdec.c | 3 ++ > nutenc.c | 87 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- > 3 files changed, 88 insertions(+), 4 deletions(-) > 870df19d733f29294a2cb2e3ea5ed1a09745f3a4 > 0001-avformat-nut-fix-duration-estimation-by-writing-EOR-.patch > From 80d6805fdf386182341fe72035ab88e06a602752 Mon Sep 17 00:00:00 2001 > From: Paul B Mahol <one...@gmail.com> > Date: Mon, 17 Dec 2018 16:43:57 +0100 > Subject: [PATCH 1/2] avformat/nut: fix duration estimation by writing EOR > packets > > Signed-off-by: Paul B Mahol <one...@gmail.com> > --- > libavformat/nut.h | 2 + > libavformat/nutdec.c | 3 ++ > libavformat/nutenc.c | 87 ++++++++++++++++++++++++++++++++++++++++++-- > 3 files changed, 88 insertions(+), 4 deletions(-) > > diff --git a/libavformat/nut.h b/libavformat/nut.h > index a4409ee23d..d7ba86b5e5 100644 > --- a/libavformat/nut.h > +++ b/libavformat/nut.h > @@ -76,6 +76,8 @@ typedef struct StreamContext { > int last_flags; > int skip_until_key_frame; > int64_t last_pts; > + int64_t last_dts; > + int64_t last_duration; > int time_base_id; > AVRational *time_base; > int msb_pts_shift; > diff --git a/libavformat/nutdec.c b/libavformat/nutdec.c > index 056ef59d00..f2490f9842 100644 > --- a/libavformat/nutdec.c > +++ b/libavformat/nutdec.c > @@ -1080,6 +1080,9 @@ static int decode_frame(NUTContext *nut, AVPacket *pkt, > int frame_code) > > stc = &nut->stream[stream_id]; > > + if (stc->last_flags & FLAG_EOR) > + return 1; EOR can occur in the middle of subtitle streams. It would be used to mark areas with no vissible subtitles. (The point behind this is that it allows seeking to consider a subtitle stream if and only if there are actually any displayed subtitles at that time) this code would break that also demxuer and muxer changes should be in seperate patches > + > if (stc->last_flags & FLAG_KEY) > stc->skip_until_key_frame = 0; > > diff --git a/libavformat/nutenc.c b/libavformat/nutenc.c > index e9a3bb49db..c12b4cc8cf 100644 > --- a/libavformat/nutenc.c > +++ b/libavformat/nutenc.c > @@ -940,6 +940,80 @@ fail: > return ret; > } > > +static void nut_update_max_pts(AVFormatContext *s, int stream_index, int64_t > pts) > +{ > + NUTContext *nut = s->priv_data; > + StreamContext *nus = &nut->stream[stream_index]; > + > + if (!nut->max_pts_tb || av_compare_ts(nut->max_pts, *nut->max_pts_tb, > pts, *nus->time_base) < 0) { > + nut->max_pts = pts; > + nut->max_pts_tb = nus->time_base; > + } > +} > + > +static int nut_write_eor(AVFormatContext *s, int stream_index) > +{ > + AVIOContext *bc = s->pb, *dyn_bc; > + NUTContext *nut = s->priv_data; > + StreamContext *nus = &nut->stream[stream_index]; > + int ret, frame_code, flags, needed_flags; > + int64_t pts = nus->last_pts + nus->last_duration; > + int64_t coded_pts; > + FrameCode *fc; > + > + coded_pts = pts & ((1 << nus->msb_pts_shift) - 1); > + if (ff_lsb2full(nus, coded_pts) != pts) > + coded_pts = pts + (1 << nus->msb_pts_shift); > + > + nut->last_syncpoint_pos = avio_tell(bc); > + ret = avio_open_dyn_buf(&dyn_bc); > + if (ret < 0) > + return ret; > + put_tt(nut, nus->time_base, dyn_bc, nus->last_dts + nus->last_duration); > + ff_put_v(dyn_bc, 0); > + > + if (nut->flags & NUT_BROADCAST) { > + put_tt(nut, nus->time_base, dyn_bc, > + av_rescale_q(av_gettime(), AV_TIME_BASE_Q, *nus->time_base)); > + } > + put_packet(nut, bc, dyn_bc, 1, SYNCPOINT_STARTCODE); > + > + frame_code = -1; > + for (int i = 0; i < 256; i++) { > + FrameCode *fc = &nut->frame_code[i]; > + int flags = fc->flags; > + > + if (flags & FLAG_INVALID) > + continue; > + > + if (!(flags & FLAG_CODED)) { > + continue; > + } > + > + frame_code = i; > + break; > + } > + av_assert0(frame_code != -1); > + > + fc = &nut->frame_code[frame_code]; > + flags = fc->flags; > + needed_flags = FLAG_KEY | FLAG_EOR | FLAG_CODED_PTS | FLAG_STREAM_ID; > + > + ffio_init_checksum(bc, ff_crc04C11DB7_update, 0); > + avio_w8(bc, frame_code); > + if (flags & FLAG_CODED) { > + ff_put_v(bc, (flags ^ needed_flags) & ~(FLAG_CODED)); > + flags = needed_flags; > + } > + if (flags & FLAG_STREAM_ID) ff_put_v(bc, stream_index); > + if (flags & FLAG_CODED_PTS) ff_put_v(bc, coded_pts); > + ffio_get_checksum(bc); > + > + nut_update_max_pts(s, stream_index, nus->last_pts + nus->last_duration); > + > + return 0; > +} > + > static int nut_write_packet(AVFormatContext *s, AVPacket *pkt) > { > NUTContext *nut = s->priv_data; > @@ -1136,6 +1210,8 @@ static int nut_write_packet(AVFormatContext *s, > AVPacket *pkt) > > nus->last_flags = flags; > nus->last_pts = pkt->pts; > + nus->last_dts = pkt->dts; > + nus->last_duration = pkt->duration; > > //FIXME just store one per syncpoint > if (flags & FLAG_KEY && !(nut->flags & NUT_PIPE)) { > @@ -1150,10 +1226,7 @@ static int nut_write_packet(AVFormatContext *s, > AVPacket *pkt) > nus->keyframe_pts[nut->sp_count] = pkt->pts; > } > > - if (!nut->max_pts_tb || av_compare_ts(nut->max_pts, *nut->max_pts_tb, > pkt->pts, *nus->time_base) < 0) { > - nut->max_pts = pkt->pts; > - nut->max_pts_tb = nus->time_base; > - } > + nut_update_max_pts(s, pkt->stream_index, pkt->pts); > > fail: > av_freep(&sm_buf); > @@ -1167,6 +1240,12 @@ static int nut_write_trailer(AVFormatContext *s) > AVIOContext *bc = s->pb, *dyn_bc; > int ret; > > + for (int i = 0; i < s->nb_streams; i++) { > + ret = nut_write_eor(s, i); > + if (ret < 0) > + return ret; > + } > + > while (nut->header_count < 3) > write_headers(s, bc); This violates the packet interleaving requirements if one stream ends. lets say at time 5sec and one continues with frames at 6,7,8 sec then the EOR frame for the stream ending at 5sec has to be written before the later frames. The best way to implement this will likely be with oformat->interleave_packet because at this level you know when the last packet is reached and you can also trivially inject an additional packet. That should then get interleaved automatically. also i suspect that index & syncpoint related code will need changes to support EORs [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB In fact, the RIAA has been known to suggest that students drop out of college or go to community college in order to be able to afford settlements. -- The RIAA
signature.asc
Description: PGP signature
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel