diff --git a/CMakeLists.txt b/CMakeLists.txt index 056f51970..98d3d080e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ include(GNUInstallDirs) find_package(PkgConfig REQUIRED) pkg_check_modules(TERMINFO REQUIRED tinfo>=6.1) +pkg_check_modules(AVUTIL REQUIRED libavutil) pkg_check_modules(AVFORMAT REQUIRED libavformat) find_library(LIBRT rt) @@ -61,10 +62,21 @@ target_compile_options(notcurses-demo file(GLOB VIEWSRCS CONFIGURE_DEPENDS src/view/*.cpp) add_executable(notcurses-view ${VIEWSRCS}) -target_include_directories(notcurses-view PRIVATE include) +target_include_directories(notcurses-view + PRIVATE + include + "${PROJECT_BINARY_DIR}/include" + "${AVUTIL_INCLUDE_DIR}" +) +target_link_directories(notcurses-view + PRIVATE + "${AVUTIL_LIBRARY_DIRS}" +) target_link_libraries(notcurses-view PRIVATE notcurses + PRIVATE + "${AVUTIL_LIBRARIES}" ) target_compile_options(notcurses-view PRIVATE diff --git a/src/lib/libav.c b/src/lib/libav.c index 1a40ec106..55dc64599 100644 --- a/src/lib/libav.c +++ b/src/lib/libav.c @@ -8,6 +8,7 @@ typedef struct ncvisual { AVFrame* frame; AVCodec* codec; AVPacket* packet; + int packet_outstanding; } ncvisual; static ncvisual* @@ -32,22 +33,24 @@ void ncvisual_destroy(ncvisual* ncv){ } AVFrame* ncvisual_decode(struct ncvisual* nc){ - int ret = avcodec_send_packet(nc->codecctx, nc->packet); - if(ret < 0){ - fprintf(stderr, "Error processing AVPacket (%s)\n", av_err2str(ret)); - return NULL; - } - do{ - ret = avcodec_receive_frame(nc->codecctx, nc->frame); - if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF){ - return nc->frame; // FIXME is this safe? could it have been blown away? - }else if(ret < 0){ - fprintf(stderr, "Error decoding AVPacket (%s)\n", av_err2str(ret)); + int ret; + if(nc->packet_outstanding){ + ret = avcodec_send_packet(nc->codecctx, nc->packet); + if(ret < 0){ + fprintf(stderr, "Error processing AVPacket (%s)\n", av_err2str(ret)); return NULL; } - fprintf(stderr, "Got frame %05d\n", nc->codecctx->frame_number); - }while(ret > 0); - return NULL; // FIXME + --nc->packet_outstanding; + } + ret = avcodec_receive_frame(nc->codecctx, nc->frame); + if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF){ + return NULL; // FIXME do something smarter + }else if(ret < 0){ + fprintf(stderr, "Error decoding AVPacket (%s)\n", av_err2str(ret)); + return NULL; + } + fprintf(stderr, "Got frame %05d\n", nc->codecctx->frame_number); + return nc->frame; } ncvisual* notcurses_visual_open(struct notcurses* nc __attribute__ ((unused)), @@ -98,6 +101,7 @@ av_dump_format(ncv->fmtctx, 0, filename, false); av_err2str(ret)); goto err; } + ++ncv->packet_outstanding; if((ncv->frame = av_frame_alloc()) == NULL){ fprintf(stderr, "Couldn't allocate frame for %s\n", filename); goto err; diff --git a/src/view/main.cpp b/src/view/main.cpp index 93741b1cb..c3679febe 100644 --- a/src/view/main.cpp +++ b/src/view/main.cpp @@ -1,6 +1,9 @@ #include #include #include +#include +#include +#include #include "notcurses.h" static void usage(std::ostream& os, const char* name, int exitcode) @@ -12,9 +15,13 @@ void usage(std::ostream& o, const char* name, int exitcode){ } int ncview(struct ncvisual* ncv, const notcurses_options* opts){ - if(ncvisual_decode(ncv) == nullptr){ + AVFrame* avf; + if((avf = ncvisual_decode(ncv)) == nullptr){ return -1; } + printf("%s: %dx%d aspect %d:%d %d\n", avf->key_frame ? "Keyframe" : "Frame", + avf->height, avf->width, avf->sample_aspect_ratio.num, + avf->sample_aspect_ratio.den, avf->format); auto nc = notcurses_init(opts); if(nc == nullptr){ return -1;