ncvisual_destroy() implemented

This commit is contained in:
nick black 2019-11-27 15:22:43 -05:00 committed by Nick Black
parent dc6ce9ba90
commit 4b2bf26ee2
2 changed files with 68 additions and 62 deletions

View File

@ -18,6 +18,7 @@ API const char* notcurses_version(void);
struct cell; // a coordinate on an ncplane: an EGC plus styling struct cell; // a coordinate on an ncplane: an EGC plus styling
struct ncplane; // a drawable notcurses surface, composed of cells struct ncplane; // a drawable notcurses surface, composed of cells
struct ncvisual; // a visual bit of multimedia opened with LibAV
struct notcurses; // notcurses state for a given terminal, composed of ncplanes struct notcurses; // notcurses state for a given terminal, composed of ncplanes
// A cell corresponds to a single character cell on some plane, which can be // A cell corresponds to a single character cell on some plane, which can be
@ -427,7 +428,9 @@ ncplane_rounded_box_cells(struct ncplane* n, cell* ul, cell* ur, cell* ll,
} }
// multimedia functionality // multimedia functionality
API int notcurses_visual_open(struct notcurses* nc, const char* filename); API struct ncvisual* notcurses_visual_open(struct notcurses* nc,
const char* filename);
API void ncvisual_destroy(struct ncvisual* ncv);
#undef API #undef API

View File

@ -2,86 +2,89 @@
#include <libavformat/avformat.h> #include <libavformat/avformat.h>
#include "notcurses.h" #include "notcurses.h"
int notcurses_visual_open(struct notcurses* nc __attribute__ ((unused)), typedef struct ncvisual {
AVFormatContext* fmtctx;
AVCodecContext* codecctx;
AVFrame* frame;
AVCodec* codec;
AVPacket* packet;
} ncvisual;
static ncvisual*
ncvisual_create(void){
ncvisual* ret = malloc(sizeof(*ret));
if(ret == NULL){
return NULL;
}
memset(ret, 0, sizeof(*ret));
return ret;
}
void ncvisual_destroy(ncvisual* ncv){
if(ncv){
avcodec_close(ncv->codecctx);
avcodec_free_context(&ncv->codecctx);
av_frame_free(&ncv->frame);
av_packet_free(&ncv->packet);
avformat_close_input(&ncv->fmtctx);
free(ncv);
}
}
ncvisual* notcurses_visual_open(struct notcurses* nc __attribute__ ((unused)),
const char* filename){ const char* filename){
AVFormatContext* ps = NULL; ncvisual* ncv = ncvisual_create();
int ret = avformat_open_input(&ps, filename, NULL, NULL); if(ncv == NULL){
return NULL;
}
int ret = avformat_open_input(&ncv->fmtctx, filename, NULL, NULL);
if(ret < 0){ if(ret < 0){
fprintf(stderr, "Couldn't open %s (%s)\n", filename, av_err2str(ret)); fprintf(stderr, "Couldn't open %s (%s)\n", filename, av_err2str(ret));
return ret; goto err;
} }
if((ret = avformat_find_stream_info(ps, NULL)) < 0){ if((ret = avformat_find_stream_info(ncv->fmtctx, NULL)) < 0){
fprintf(stderr, "Error extracting stream info from %s (%s)\n", filename, fprintf(stderr, "Error extracting stream info from %s (%s)\n", filename,
av_err2str(ret)); av_err2str(ret));
avformat_close_input(&ps); goto err;
return ret;
} }
av_dump_format(ps, 0, filename, false); av_dump_format(ncv->fmtctx, 0, filename, false);
AVPacket* packet = av_packet_alloc(); if((ncv->packet = av_packet_alloc()) == NULL){
if((ret = av_read_frame(ps, packet)) < 0){ fprintf(stderr, "Couldn't allocate packet for %s\n", filename);
goto err;
}
if((ret = av_read_frame(ncv->fmtctx, ncv->packet)) < 0){
fprintf(stderr, "Error reading frame info from %s (%s)\n", filename, fprintf(stderr, "Error reading frame info from %s (%s)\n", filename,
av_err2str(ret)); av_err2str(ret));
av_packet_free(&packet); goto err;
avformat_close_input(&ps);
return -1;
} }
AVCodec* codec; if((ret = av_find_best_stream(ncv->fmtctx, AVMEDIA_TYPE_VIDEO, -1, -1, &ncv->codec, 0)) < 0){
if((ret = av_find_best_stream(ps, AVMEDIA_TYPE_VIDEO, -1, -1, &codec, 0)) < 0){
fprintf(stderr, "Couldn't find visuals in %s (%s)\n", filename, av_err2str(ret)); fprintf(stderr, "Couldn't find visuals in %s (%s)\n", filename, av_err2str(ret));
av_packet_free(&packet); goto err;
avformat_close_input(&ps);
return -1;
} }
if(codec == NULL){ if(ncv->codec == NULL){
fprintf(stderr, "Couldn't find decoder for %s\n", filename); fprintf(stderr, "Couldn't find decoder for %s\n", filename);
av_packet_free(&packet); goto err;
avformat_close_input(&ps);
return -1;
} }
/* if((ncv->codecctx = avcodec_alloc_context3(ncv->codec)) == NULL){
stream = ret; fprintf(stderr, "Couldn't allocate decoder for %s\n", filename);
AVStream* avstream = ps->streams[stream]; goto err;
AVCodecContext* codecctx = avstream->codec;
AVCodec* codec = avcodec_find_decoder(codecctx->codec_id);
if(codec == NULL){
fprintf(stderr, "Couldn't find decoder for %s (%s)\n", filename);
avcodec_close(codecctx);
av_packet_free(&packet);
avformat_close_input(&ps);
return -1;
} }
*/ if((ret = avcodec_open2(ncv->codecctx, ncv->codec, NULL)) < 0){
AVCodecContext* codecctx = avcodec_alloc_context3(codec);
if((ret = avcodec_open2(codecctx, codec, NULL)) < 0){
fprintf(stderr, "Couldn't open codec for %s (%s)\n", filename, av_err2str(ret)); fprintf(stderr, "Couldn't open codec for %s (%s)\n", filename, av_err2str(ret));
avcodec_free_context(&codecctx); goto err;
av_packet_free(&packet);
avformat_close_input(&ps);
return -1;
} }
if((ret = avcodec_send_packet(codecctx, packet)) < 0){ if((ret = avcodec_send_packet(ncv->codecctx, ncv->packet)) < 0){
fprintf(stderr, "Error decoding packet from %s (%s)\n", filename, fprintf(stderr, "Error decoding packet from %s (%s)\n", filename,
av_err2str(ret)); av_err2str(ret));
avcodec_close(codecctx); goto err;
avcodec_free_context(&codecctx);
av_packet_free(&packet);
avformat_close_input(&ps);
return -1;
} }
AVFrame* frame = av_frame_alloc(); if((ncv->frame = av_frame_alloc()) == NULL){
if(frame == NULL){ fprintf(stderr, "Couldn't allocate frame for %s\n", filename);
avcodec_close(codecctx); goto err;
avcodec_free_context(&codecctx);
av_packet_free(&packet);
avformat_close_input(&ps);
return -1;
} }
return ncv;
// FIXME err:
avcodec_close(codecctx); ncvisual_destroy(ncv);
avcodec_free_context(&codecctx); return NULL;
av_frame_free(&frame);
av_packet_free(&packet);
avformat_close_input(&ps);
return 0;
} }