summaryrefslogtreecommitdiff
path: root/subprojects/packagefiles/notcurses
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2025-01-22 08:02:14 -0500
committerAndrew Opalach <andrew@akon.city> 2025-01-22 08:02:14 -0500
commit5073f74aefb91616fb8e1df087747105e46e265d (patch)
treef4de264a561c19cf79b416d33f3ff999d6309630 /subprojects/packagefiles/notcurses
parentf3590721df77b7557a80c437acca33b1a4514a9a (diff)
downloadcamu-5073f74aefb91616fb8e1df087747105e46e265d.tar.gz
camu-5073f74aefb91616fb8e1df087747105e46e265d.tar.bz2
camu-5073f74aefb91616fb8e1df087747105e46e265d.zip
Rough draft of some tui stuff
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'subprojects/packagefiles/notcurses')
-rw-r--r--subprojects/packagefiles/notcurses/duration_and_ffmpeg_fix.diff166
1 files changed, 166 insertions, 0 deletions
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;
+ }
+ }