diff --git a/include/notcurses.h b/include/notcurses.h index c1b5b96eb..079011555 100644 --- a/include/notcurses.h +++ b/include/notcurses.h @@ -134,7 +134,7 @@ API struct ncplane* notcurses_newplane(struct notcurses* nc, int rows, int cols, // Destroy the specified ncplane. None of its contents will be visible after // the next call to notcurses_render(). It is an error to attempt to destroy // the standard plane. -API int ncplane_destroy(struct ncplane* n); +API int ncplane_destroy(struct notcurses* nc, struct ncplane* ncp); // Move this plane relative to the standard plane. API int ncplane_move_yx(struct ncplane* n, int y, int x); @@ -429,8 +429,7 @@ ncplane_rounded_box_cells(struct ncplane* n, cell* ul, cell* ur, cell* ll, // multimedia functionality struct AVFrame; -API struct ncvisual* notcurses_visual_open(struct notcurses* nc, - const char* filename); +API struct ncvisual* ncplane_visual_open(struct ncplane* nc, const char* file); API void ncvisual_destroy(struct ncvisual* ncv); diff --git a/src/lib/libav.c b/src/lib/libav.c index 55dc64599..7bb9a1b5d 100644 --- a/src/lib/libav.c +++ b/src/lib/libav.c @@ -1,4 +1,5 @@ #include +#include #include #include "notcurses.h" @@ -8,7 +9,9 @@ typedef struct ncvisual { AVFrame* frame; AVCodec* codec; AVPacket* packet; + struct SwsContext* swsctx; int packet_outstanding; + int dstwidth, dstheight; } ncvisual; static ncvisual* @@ -26,6 +29,7 @@ void ncvisual_destroy(ncvisual* ncv){ avcodec_close(ncv->codecctx); avcodec_free_context(&ncv->codecctx); av_frame_free(&ncv->frame); + sws_freeContext(ncv->swsctx); av_packet_free(&ncv->packet); avformat_close_input(&ncv->fmtctx); free(ncv); @@ -50,16 +54,29 @@ AVFrame* ncvisual_decode(struct ncvisual* nc){ return NULL; } fprintf(stderr, "Got frame %05d\n", nc->codecctx->frame_number); + nc->swsctx = sws_getCachedContext(nc->swsctx, + nc->frame->width, + nc->frame->height, + nc->frame->format, + nc->dstwidth, + nc->dstheight, + AV_PIX_FMT_RGB24, + SWS_LANCZOS, + NULL, NULL, NULL); + if(nc->swsctx == NULL){ + fprintf(stderr, "Error retrieving swsctx (%s)\n", av_err2str(ret)); + return NULL; + } return nc->frame; } -ncvisual* notcurses_visual_open(struct notcurses* nc __attribute__ ((unused)), - const char* filename){ +ncvisual* ncplane_visual_open(struct ncplane* nc, const char* filename){ ncvisual* ncv = ncvisual_create(); if(ncv == NULL){ fprintf(stderr, "Couldn't create %s (%s)\n", filename, strerror(errno)); return NULL; } + ncplane_dimyx(nc, &ncv->dstheight, &ncv->dstwidth); int ret = avformat_open_input(&ncv->fmtctx, filename, NULL, NULL); if(ret < 0){ fprintf(stderr, "Couldn't open %s (%s)\n", filename, av_err2str(ret)); diff --git a/tests/libav.cpp b/tests/libav.cpp index d5d121087..da8160416 100644 --- a/tests/libav.cpp +++ b/tests/libav.cpp @@ -4,21 +4,37 @@ class LibavTest : public :: testing::Test { protected: void SetUp() override { + setlocale(LC_ALL, nullptr); + if(getenv("TERM") == nullptr){ + GTEST_SKIP(); + } + notcurses_options nopts{}; + nopts.outfp = stdin; + nc_ = notcurses_init(&nopts); + ASSERT_NE(nullptr, nc_); + ncp_ = notcurses_stdplane(nc_); + ASSERT_NE(nullptr, ncp_); } void TearDown() override { + if(nc_){ + EXPECT_EQ(0, notcurses_stop(nc_)); + } } + + notcurses* nc_{}; + ncplane* ncp_{}; }; TEST_F(LibavTest, LoadImage) { - auto ncv = notcurses_visual_open(nullptr, "../tools/dsscaw-purp.png"); + auto ncv = ncplane_visual_open(ncp_, "../tools/dsscaw-purp.png"); ASSERT_NE(nullptr, ncv); ASSERT_NE(nullptr, ncvisual_decode(ncv)); ncvisual_destroy(ncv); } TEST_F(LibavTest, LoadVideo) { - auto ncv = notcurses_visual_open(nullptr, "../tools/atliens.mkv"); + auto ncv = ncplane_visual_open(ncp_, "../tools/atliens.mkv"); ASSERT_NE(nullptr, ncv); ASSERT_NE(nullptr, ncvisual_decode(ncv)); ncvisual_destroy(ncv); diff --git a/tests/notcurses.cpp b/tests/notcurses.cpp index 38767013f..a91dbf954 100644 --- a/tests/notcurses.cpp +++ b/tests/notcurses.cpp @@ -65,3 +65,10 @@ TEST_F(NotcursesTest, CursesStyles) { unsigned attrs = notcurses_supported_styles(nc_); EXPECT_EQ(1, !!(WA_BOLD & attrs)); } + +// it is an error to attempt to destroy the standard plane +TEST_F(NotcursesTest, RejectDestroyStdPlane) { + ncplane* ncp = notcurses_stdplane(nc_); + ASSERT_NE(nullptr, ncp); + ASSERT_NE(0, ncplane_destroy(nc_, ncp)); +}