libav: throw an swscaler in the mix #61

pull/63/head
nick black 5 years ago committed by Nick Black
parent f948904f7b
commit 5dfb07183c

@ -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);

@ -1,4 +1,5 @@
#include <libavutil/error.h>
#include <libswscale/swscale.h>
#include <libavformat/avformat.h>
#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));

@ -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);

@ -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));
}

Loading…
Cancel
Save