From 5073f74aefb91616fb8e1df087747105e46e265d Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Wed, 22 Jan 2025 08:02:14 -0500 Subject: Rough draft of some tui stuff Signed-off-by: Andrew Opalach --- .../notcurses/duration_and_ffmpeg_fix.diff | 166 +++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 subprojects/packagefiles/notcurses/duration_and_ffmpeg_fix.diff (limited to 'subprojects/packagefiles') diff --git a/subprojects/packagefiles/notcurses/duration_and_ffmpeg_fix.diff b/subprojects/packagefiles/notcurses/duration_and_ffmpeg_fix.diff new file mode 100644 index 0000000..71680f7 --- /dev/null +++ b/subprojects/packagefiles/notcurses/duration_and_ffmpeg_fix.diff @@ -0,0 +1,166 @@ +diff --git a/include/notcurses/notcurses.h b/include/notcurses/notcurses.h +index 9e09cb3..f4da60f 100644 +--- a/include/notcurses/notcurses.h ++++ b/include/notcurses/notcurses.h +@@ -3406,6 +3406,10 @@ API int ncvisual_geom(const struct notcurses* nc, const struct ncvisual* n, + const struct ncvisual_options* vopts, ncvgeom* geom) + __attribute__ ((nonnull (4))); + ++ ++API uint64_t ncvisual_get_duration(const struct ncvisual* n) ++ __attribute__ ((nonnull (1))); ++ + // Destroy an ncvisual. Rendered elements will not be disrupted, but the visual + // can be neither decoded nor rendered any further. + API void ncvisual_destroy(struct ncvisual* ncv); +diff --git a/src/lib/visual-details.h b/src/lib/visual-details.h +index e9347e3..6852b76 100644 +--- a/src/lib/visual-details.h ++++ b/src/lib/visual-details.h +@@ -25,6 +25,7 @@ typedef struct ncvisual { + unsigned pixx, pixy; // pixel geometry, *not* cell geometry + // lines are sometimes padded. this many true bytes per row in data. + unsigned rowstride; ++ uint64_t duration; + bool owndata; // we own data iff owndata == true + } ncvisual; + +diff --git a/src/lib/visual.c b/src/lib/visual.c +index 047b68e..25e8422 100644 +--- a/src/lib/visual.c ++++ b/src/lib/visual.c +@@ -458,6 +458,10 @@ int ncvisual_geom(const notcurses* nc, const ncvisual* n, + &disppxy, &disppxx, &outy, &outx, &placey, &placex); + } + ++uint64_t ncvisual_get_duration(const ncvisual* n){ ++ return n->duration; ++} ++ + void* rgb_loose_to_rgba(const void* data, int rows, int* rowstride, int cols, int alpha){ + if(*rowstride % 4){ // must be a multiple of 4 bytes + return NULL; +diff --git a/src/media/ffmpeg.c b/src/media/ffmpeg.c +index 655f269..d2bf399 100644 +--- a/src/media/ffmpeg.c ++++ b/src/media/ffmpeg.c +@@ -33,6 +33,7 @@ typedef struct ncvisual_details { + struct SwsContext* swsctx; + struct SwsContext* rgbactx; + AVSubtitle subtitle; ++ AVRational timebase; + int stream_index; // match against this following av_read_frame() + int sub_stream_index; // subtitle stream index, can be < 0 if no subtitles + bool packet_outstanding; +@@ -224,9 +225,7 @@ struct ncplane* ffmpeg_subtitle(ncplane* parent, const ncvisual* ncv){ + + static int + averr2ncerr(int averr){ +- if(averr == AVERROR_EOF){ +- return 1; +- } ++ (void)averr; + // FIXME need to map averror codes to ncerrors + //fprintf(stderr, "AVERR: %d/%x %d/%x\n", averr, averr, -averr, -averr); + return -1; +@@ -326,6 +325,11 @@ ffmpeg_decode(ncvisual* n){ + /*if(averr != AVERROR_EOF){ + fprintf(stderr, "Error reading frame info (%s)\n", av_err2str(averr)); + }*/ ++ if(averr == AVERROR_EOF){ ++ // Start flush. ++ unref = false; ++ break; ++ } + return averr2ncerr(averr); + } + unref = true; +@@ -339,10 +343,10 @@ ffmpeg_decode(ncvisual* n){ + } + }while(n->details->packet->stream_index != n->details->stream_index); + n->details->packet_outstanding = true; +- int averr = avcodec_send_packet(n->details->codecctx, n->details->packet); ++ int averr = avcodec_send_packet(n->details->codecctx, unref ? n->details->packet : NULL); + if(averr < 0){ +- n->details->packet_outstanding = false; + av_packet_unref(n->details->packet); ++ n->details->packet_outstanding = false; + //fprintf(stderr, "Error processing AVPacket\n"); + return averr2ncerr(averr); + } +@@ -350,10 +354,16 @@ ffmpeg_decode(ncvisual* n){ + int averr = avcodec_receive_frame(n->details->codecctx, n->details->frame); + if(averr >= 0){ + have_frame = true; ++ }else if(averr == AVERROR_EOF){ ++ n->details->packet_outstanding = false; ++ // Where EOF gets returned during normal operation. ++ return 1; + }else if(averr < 0){ +- av_packet_unref(n->details->packet); +- have_frame = false; ++ if(unref){ ++ av_packet_unref(n->details->packet); ++ } + n->details->packet_outstanding = false; ++ have_frame = false; + if(averr != AVERROR(EAGAIN)){ + return averr2ncerr(averr); + } +@@ -365,6 +375,8 @@ ffmpeg_decode(ncvisual* n){ + n->rowstride = f->linesize[0]; + n->pixx = n->details->frame->width; + n->pixy = n->details->frame->height; ++ const uint64_t pktduration = ffmpeg_pkt_duration(f); ++ n->duration = av_rescale_q(pktduration, n->details->timebase, AV_TIME_BASE_Q); + //fprintf(stderr, "good decode! %d/%d %d %p\n", n->details->frame->height, n->details->frame->width, n->rowstride, f->data); + ncvisual_set_data(n, f->data[0], false); + force_rgba(n); +@@ -457,6 +469,7 @@ ffmpeg_from_file(const char* filename){ + goto err; + } + AVStream* st = ncv->details->fmtctx->streams[ncv->details->stream_index]; ++ ncv->details->timebase = st->time_base; + if((ncv->details->codecctx = avcodec_alloc_context3(ncv->details->codec)) == NULL){ + //fprintf(stderr, "Couldn't allocate decoder for %s\n", filename); + goto err; +@@ -501,14 +514,6 @@ ffmpeg_stream(notcurses* nc, ncvisual* ncv, float timescale, + memcpy(&activevopts, vopts, sizeof(*vopts)); + int ncerr; + do{ +- // codecctx seems to be off by a factor of 2 regularly. instead, go with +- // the time_base from the avformatctx. except ts isn't properly reset for +- // all media when we loop =[. we seem to be accurate enough now with the +- // tbase/ppd. see https://github.com/dankamongmen/notcurses/issues/1352. +- double tbase = av_q2d(ncv->details->fmtctx->streams[ncv->details->stream_index]->time_base); +- if(isnan(tbase)){ +- tbase = 0; +- } + if(activevopts.n){ + ncplane_erase(activevopts.n); // new frame could be partially transparent + } +@@ -529,7 +534,7 @@ ffmpeg_stream(notcurses* nc, ncvisual* ncv, float timescale, + } + // display duration in units of time_base + const uint64_t pktduration = ffmpeg_pkt_duration(ncv->details->frame); +- uint64_t duration = pktduration * tbase * NANOSECS_IN_SEC; ++ uint64_t duration = av_rescale_q(pktduration, ncv->details->timebase, (AVRational){1, NANOSECS_IN_SEC}); + double schedns = nsbegin; + sum_duration += (duration * timescale); + schedns += sum_duration; +@@ -561,11 +566,13 @@ static int + ffmpeg_decode_loop(ncvisual* ncv){ + int r = ffmpeg_decode(ncv); + if(r == 1){ +- if(av_seek_frame(ncv->details->fmtctx, ncv->details->stream_index, 0, AVSEEK_FLAG_FRAME) < 0){ ++ avformat_flush(ncv->details->fmtctx); ++ if(avformat_seek_file(ncv->details->fmtctx, ncv->details->stream_index, 0, 0, 0, AVSEEK_FLAG_FRAME) < 0){ + // FIXME log error + return -1; + } +- if(ffmpeg_decode(ncv) < 0){ ++ avcodec_flush_buffers(ncv->details->codecctx); ++ if(ffmpeg_decode(ncv) != 0){ + return -1; + } + } -- cgit v1.2.3-101-g0448