On 12/19/18, Michael Niedermayer <mich...@niedermayer.cc> wrote: > On Tue, Dec 18, 2018 at 10:55:16PM +0100, Paul B Mahol wrote: >> On 12/18/18, Michael Niedermayer <mich...@niedermayer.cc> wrote: >> > On Tue, Dec 18, 2018 at 02:56:54PM +0100, Paul B Mahol wrote: >> >> Signed-off-by: Paul B Mahol <one...@gmail.com> >> >> --- >> >> libavformat/nut.h | 3 + >> >> libavformat/nutenc.c | 130 >> >> +++++++++++++++++++++++++++++++++++++++++-- >> >> 2 files changed, 129 insertions(+), 4 deletions(-) >> >> >> >> diff --git a/libavformat/nut.h b/libavformat/nut.h >> >> index a4409ee23d..4b15dca1ea 100644 >> >> --- a/libavformat/nut.h >> >> +++ b/libavformat/nut.h >> >> @@ -76,6 +76,9 @@ typedef struct StreamContext { >> >> int last_flags; >> >> int skip_until_key_frame; >> >> int64_t last_pts; >> >> + int64_t eor_pts; >> >> + int64_t eor_dts; >> >> + int eor_flushed; >> >> int time_base_id; >> >> AVRational *time_base; >> >> int msb_pts_shift; >> >> diff --git a/libavformat/nutenc.c b/libavformat/nutenc.c >> >> index e9a3bb49db..9d1c540a9d 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, AVPacket *pkt) >> >> +{ >> >> + AVIOContext *bc = s->pb, *dyn_bc; >> >> + NUTContext *nut = s->priv_data; >> >> + StreamContext *nus = &nut->stream[pkt->stream_index]; >> >> + int ret, frame_code, flags, needed_flags; >> >> + int64_t pts = pkt->pts; >> >> + 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, pkt->dts); >> >> + 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, pkt->stream_index); >> >> + if (flags & FLAG_CODED_PTS) ff_put_v(bc, coded_pts); >> >> + ffio_get_checksum(bc); >> >> + >> >> + nut_update_max_pts(s, pkt->stream_index, pkt->pts); >> >> + >> >> + return 0; >> >> +} >> >> + >> >> static int nut_write_packet(AVFormatContext *s, AVPacket *pkt) >> >> { >> >> NUTContext *nut = s->priv_data; >> > >> >> @@ -956,6 +1030,9 @@ static int nut_write_packet(AVFormatContext *s, >> >> AVPacket *pkt) >> >> int data_size = pkt->size; >> >> uint8_t *sm_buf = NULL; >> >> >> >> + if (!data_size) >> >> + return nut_write_eor(s, pkt); >> > >> > that could happen for non EOR packets too >> >> How would you solve it? > > the flags of the packet should be the easiest way to mark EOR packets >
By adding flag to libavformat ? > >> >> > >> > >> >> + >> >> if (pkt->pts < 0) { >> >> av_log(s, AV_LOG_ERROR, >> >> "Negative pts not supported stream %d, pts >> >> %"PRId64"\n", >> >> @@ -1150,10 +1227,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); >> >> @@ -1161,6 +1235,53 @@ fail: >> >> return ret; >> >> } >> >> >> >> +static int nut_interleave_packet(AVFormatContext *s, AVPacket *out, >> >> + AVPacket *pkt, int flush) >> >> +{ >> >> + NUTContext *nut = s->priv_data; >> >> + int ret; >> >> + >> >> + if (pkt) { >> >> + StreamContext *nus = &nut->stream[pkt->stream_index]; >> >> + >> >> + nus->eor_pts = FFMAX(pkt->pts + pkt->duration, nus->eor_pts); >> >> + nus->eor_dts = FFMAX(pkt->dts + pkt->duration, nus->eor_dts); >> >> + } else if (flush) { >> >> + StreamContext *nus; >> >> + int i; >> >> + >> >> + for (i = 0; i < s->nb_streams; i++) { >> >> + nus = &nut->stream[i]; >> >> + >> >> + if (nus->eor_flushed) >> >> + continue; >> >> + >> >> + if (s->streams[i]->last_in_packet_buffer) >> >> + continue; >> >> + >> >> + break; >> >> + } >> >> + >> >> + if (i < s->nb_streams) { >> >> + pkt = av_packet_alloc(); >> >> + if (!pkt) >> >> + return AVERROR(ENOMEM); >> >> + >> >> + ret = av_new_packet(pkt, 0); >> >> + if (ret < 0) >> >> + return ret; >> >> + pkt->stream_index = i; >> >> + pkt->pts = nus->eor_pts; >> >> + pkt->dts = nus->eor_dts; >> >> + pkt->duration = 0; >> >> + nus->eor_flushed = 1; >> > >> >> + ret = ff_interleave_packet_per_dts(s, out, pkt, 0); >> >> + pkt = NULL; >> >> + } >> >> + } >> >> + return ff_interleave_packet_per_dts(s, out, pkt, flush); >> > >> > this looks a bit odd, shouldnt there be a return after the first call >> > to ff_interleave_packet_per_dts() ? >> > as it would assign the ret variable but then ignore it, would >> > potentially output something in "out" but then overwrite it >> > in the 2nd call >> >> So what you propose? > > to add a return in there, so all the EOR get added and it then resumes > with the flushing but doing one per call > or does this not work ? > > thanks > > > [...] > -- > Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB > > If you think the mosad wants you dead since a long time then you are either > wrong or dead since a long time. > _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel