Remove AVFrame from API #532

This commit is contained in:
nick black 2020-04-24 02:23:06 -04:00 committed by Nick Black
parent 21822f98e7
commit 0b4ada19b1
18 changed files with 74 additions and 88 deletions

View File

@ -62,9 +62,9 @@ namespace ncpp
return visual;
}
AVFrame* decode (nc_err_e* ncerr) const noexcept
nc_err_e decode () const noexcept
{
return ncvisual_decode (visual, ncerr);
return ncvisual_decode (visual);
}
bool render (int begy, int begx, int leny, int lenx) const NOEXCEPT_MAYBE

View File

@ -14,6 +14,8 @@ typedef enum {
NCERR_SUCCESS = 0,
NCERR_NOMEM = ENOMEM,
NCERR_EOF = 0x20464f45, // matches AVERROR_EOF
NCERR_DECODE,
NCERR_UNIMPLEMENTED,
} nc_err_e;
static inline const char*
@ -22,6 +24,8 @@ nc_strerror(nc_err_e ncerr){
case NCERR_SUCCESS: return "success";
case NCERR_NOMEM: return strerror(ENOMEM);
case NCERR_EOF: return "end of file";
case NCERR_DECODE: return "error decoding";
case NCERR_UNIMPLEMENTED: return "feature not available";
};
return "unknown error";
}

View File

@ -2050,12 +2050,9 @@ API struct ncplane* ncvisual_plane(struct ncvisual* ncv);
// can be neither decoded nor rendered any further.
API void ncvisual_destroy(struct ncvisual* ncv);
// extract the next frame from an ncvisual. returns NULL on end of file,
// writing NCERR_EOF to 'ncerr'. returns NULL on a decoding or allocation
// error, writing the cause to 'ncerr'. this frame is invalidated by a
// subsequent call to ncvisual_decode(), and should not be freed by the caller.
struct AVFrame;
API struct AVFrame* ncvisual_decode(struct ncvisual* nc, nc_err_e* ncerr);
// extract the next frame from an ncvisual. returns NCERR_EOF on end of file,
// and NCERR_SUCCESS on success, otherwise some other NCERR.
API nc_err_e ncvisual_decode(struct ncvisual* nc);
// Render the decoded frame to the associated ncplane. The frame will be scaled
// to the size of the ncplane per the ncscale_e style. A subregion of the

View File

@ -267,6 +267,8 @@ typedef enum {
NCERR_SUCCESS,
NCERR_NOMEM,
NCERR_EOF,
NCERR_DECODE,
NCERR_UNIMPLEMENTED,
} nc_err_e;
struct ncvisual* ncplane_visual_open(struct ncplane* nc, const char* file, nc_err_e* err);
typedef enum {
@ -277,7 +279,7 @@ typedef enum {
struct ncvisual* ncvisual_open_plane(struct notcurses* nc, const char* file, nc_err_e* err, int y, int x, ncscale_e style);
struct ncplane* ncvisual_plane(struct ncvisual* ncv);
void ncvisual_destroy(struct ncvisual* ncv);
struct AVFrame* ncvisual_decode(struct ncvisual* nc, nc_err_e* err);
nc_err_e ncvisual_decode(struct ncvisual* nc);
int ncvisual_render(const struct ncvisual* ncv, int begy, int begx, int leny, int lenx);
char* ncvisual_subtitle(const struct ncvisual* ncv);
typedef int (*streamcb)(struct notcurses* nc, struct ncvisual* ncv, void*);

View File

@ -24,7 +24,7 @@ chunli_draw(struct notcurses* nc, const char* ext, int count, const cell* b){
if(chuns[i].ncv == NULL){
return -1;
}
if(ncvisual_decode(chuns[i].ncv, &err) == NULL){
if((err = ncvisual_decode(chuns[i].ncv)) != NCERR_SUCCESS){
return -1;
}
if(ncvisual_render(chuns[i].ncv, 0, 0, -1, -1) <= 0){
@ -72,7 +72,7 @@ int chunli_demo(struct notcurses* nc){
break;
}
free(path);
if(ncvisual_decode(ncv, &err) == NULL){
if((err = ncvisual_decode(ncv)) != NCERR_SUCCESS){
return -1;
}
struct ncplane* ncp = ncvisual_plane(ncv);

View File

@ -31,7 +31,7 @@ outzoomed_map(struct notcurses* nc, const char* map){
if(ncv == NULL){
return -1;
}
if(ncvisual_decode(ncv, &ncerr) == NULL){
if((ncerr = ncvisual_decode(ncv)) != NCERR_SUCCESS){
return -1;
}
if(ncvisual_render(ncv, 0, 0, -1, -1) <= 0){
@ -54,8 +54,7 @@ zoom_map(struct notcurses* nc, const char* map){
if(ncv == NULL){
return NULL;
}
struct AVFrame* frame;
if((frame = ncvisual_decode(ncv, &ncerr)) == NULL){
if((ncerr = ncvisual_decode(ncv)) != NCERR_SUCCESS){
ncvisual_destroy(ncv);
return NULL;
}
@ -92,7 +91,7 @@ zoom_map(struct notcurses* nc, const char* map){
ncplane_destroy(zncp);
return NULL;
}
if(ncvisual_decode(zncv, &ncerr) == NULL){
if((ncerr = ncvisual_decode(zncv)) != NCERR_SUCCESS){
ncvisual_destroy(zncv);
ncplane_destroy(zncp);
return NULL;

View File

@ -184,7 +184,7 @@ int fallin_demo(struct notcurses* nc){
if(ncv == NULL){
return -1;
}
if(ncvisual_decode(ncv, &err) == NULL){
if((err = ncvisual_decode(ncv)) == NCERR_SUCCESS){
ncvisual_destroy(ncv);
return -1;
}
@ -192,8 +192,7 @@ int fallin_demo(struct notcurses* nc){
ncvisual_destroy(ncv);
return -1;
}
assert(ncvisual_decode(ncv, &err) == NULL);
assert(NCERR_EOF == err);
assert(ncvisual_decode(ncv) == NCERR_EOF);
ncvisual_destroy(ncv);
#endif
#endif

View File

@ -155,16 +155,13 @@ int luigi_demo(struct notcurses* nc){
if(nv == NULL){
return -1;
}
if(ncvisual_decode(nv, &ncerr) == NULL){
if((ncerr = ncvisual_decode(nv)) != NCERR_SUCCESS){
return -1;
}
if(ncvisual_render(nv, 0, 0, -1, -1) <= 0){
return -1;
}
assert(ncvisual_decode(nv, &ncerr) == NULL);
#ifdef USE_FFMPEG
assert(NCERR_EOF == ncerr);
#endif
assert(NCERR_EOF == ncvisual_decode(nv));
// he should be walking on the platform ~4/5 of the way down
const int height = 32;
int yoff = rows * 4 / 5 - height + 1; // tuned
@ -195,7 +192,7 @@ int luigi_demo(struct notcurses* nc){
if(wmncv == NULL){
return -1;
}
if(ncvisual_decode(wmncv, &ncerr) == NULL){
if((ncerr = ncvisual_decode(wmncv)) != NCERR_SUCCESS){
ncvisual_destroy(wmncv);
return -1;
}

View File

@ -133,7 +133,7 @@ int outro(struct notcurses* nc){
if(chncv == NULL){
return -1;
}
if(ncvisual_decode(chncv, &err) == NULL){
if((err = ncvisual_decode(chncv)) != NCERR_SUCCESS){
ncvisual_destroy(chncv);
return -1;
}

View File

@ -32,8 +32,8 @@ int qrcode_demo(struct notcurses* nc){
}
DEMO_RENDER(nc);
}
#else
DEMO_RENDER(nc);
#endif
ncplane_erase(n);
DEMO_RENDER(nc);
return 0;
}

View File

@ -92,13 +92,13 @@ int view_demo(struct notcurses* nc){
return -1;
}
free(pic);
if(ncvisual_decode(ncv, &err) == NULL){
if((err = ncvisual_decode(ncv)) != NCERR_SUCCESS){
ncvisual_destroy(ncv);
ncvisual_destroy(ncv2);
ncplane_destroy(dsplane);
return -1;
}
if(ncvisual_decode(ncv2, &err) == NULL){
if((err = ncvisual_decode(ncv2)) != NCERR_SUCCESS){
ncvisual_destroy(ncv);
ncvisual_destroy(ncv2);
ncplane_destroy(dsplane);

View File

@ -167,7 +167,7 @@ averr2ncerr(int averr){
return -averr;
}
AVFrame* ncvisual_decode(ncvisual* nc, nc_err_e* ncerr){
nc_err_e ncvisual_decode(ncvisual* nc){
bool have_frame = false;
bool unref = false;
av_freep(&nc->oframe->data[0]);
@ -184,22 +184,21 @@ AVFrame* ncvisual_decode(ncvisual* nc, nc_err_e* ncerr){
/*if(averr != AVERROR_EOF){
fprintf(stderr, "Error reading frame info (%s)\n", av_err2str(*averr));
}*/
*ncerr = averr2ncerr(averr);
return NULL;
return averr2ncerr(averr);
}
unref = true;
if(nc->packet->stream_index == nc->sub_stream_index){
int result = 0, ret;
ret = avcodec_decode_subtitle2(nc->subtcodecctx, &nc->subtitle, &result, nc->packet);
if(ret >= 0 && result){
// FIXME?
}
}
}while(nc->packet->stream_index != nc->stream_index);
++nc->packet_outstanding;
*ncerr = avcodec_send_packet(nc->codecctx, nc->packet);
if(*ncerr < 0){
if(avcodec_send_packet(nc->codecctx, nc->packet) < 0){
//fprintf(stderr, "Error processing AVPacket (%s)\n", av_err2str(*ncerr));
return ncvisual_decode(nc, ncerr);
return ncvisual_decode(nc);
}
--nc->packet_outstanding;
av_packet_unref(nc->packet);
@ -210,7 +209,7 @@ AVFrame* ncvisual_decode(ncvisual* nc, nc_err_e* ncerr){
have_frame = false;
}else if(averr < 0){
//fprintf(stderr, "Error decoding AVPacket (%s)\n", av_err2str(averr));
return NULL;
return averr2ncerr(averr);
}
}while(!have_frame);
//print_frame_summary(nc->codecctx, nc->frame);
@ -223,7 +222,7 @@ AVFrame* ncvisual_decode(ncvisual* nc, nc_err_e* ncerr){
}else{ // FIXME differentiate between scale/stretch
notcurses_term_dim_yx(nc->ncobj, &rows, &cols);
if(nc->placey >= rows || nc->placex >= cols){
return NULL;
return NCERR_DECODE;
}
rows -= nc->placey;
cols -= nc->placex;
@ -234,8 +233,7 @@ AVFrame* ncvisual_decode(ncvisual* nc, nc_err_e* ncerr){
nc->placey = 0;
nc->placex = 0;
if(nc->ncp == NULL){
*ncerr = NCERR_NOMEM;
return NULL;
return NCERR_NOMEM;
}
}else{ // check for resize
ncplane_dim_yx(nc->ncp, &rows, &cols);
@ -258,7 +256,7 @@ AVFrame* ncvisual_decode(ncvisual* nc, nc_err_e* ncerr){
NULL, NULL, NULL);
if(nc->swsctx == NULL){
//fprintf(stderr, "Error retrieving swsctx\n");
return NULL;
return NCERR_DECODE;
}
memcpy(nc->oframe, nc->frame, sizeof(*nc->oframe));
nc->oframe->format = targformat;
@ -269,19 +267,19 @@ AVFrame* ncvisual_decode(ncvisual* nc, nc_err_e* ncerr){
nc->oframe->format, IMGALLOCALIGN);
if(size < 0){
//fprintf(stderr, "Error allocating visual data (%s)\n", av_err2str(size));
return NULL;
return NCERR_NOMEM;
}
int height = sws_scale(nc->swsctx, (const uint8_t* const*)nc->frame->data,
nc->frame->linesize, 0,
nc->frame->height, nc->oframe->data, nc->oframe->linesize);
if(height < 0){
//fprintf(stderr, "Error applying scaling (%s)\n", av_err2str(height));
return NULL;
return NCERR_NOMEM;
}
//print_frame_summary(nc->codecctx, nc->oframe);
#undef IMGALLOCALIGN
av_frame_unref(nc->frame);
return nc->oframe;
return NCERR_SUCCESS;
}
static ncvisual*
@ -456,7 +454,6 @@ int ncvisual_stream(notcurses* nc, ncvisual* ncv, nc_err_e* ncerr,
float timescale, streamcb streamer, void* curry){
int frame = 1;
ncv->timescale = timescale;
AVFrame* avf;
struct timespec begin; // time we started
clock_gettime(CLOCK_MONOTONIC, &begin);
uint64_t nsbegin = timespec_to_ns(&begin);
@ -464,11 +461,11 @@ int ncvisual_stream(notcurses* nc, ncvisual* ncv, nc_err_e* ncerr,
// each frame has a pkt_duration in milliseconds. keep the aggregate, in case
// we don't have PTS available.
uint64_t sum_duration = 0;
while( (avf = ncvisual_decode(ncv, ncerr)) ){
while(ncvisual_decode(ncv) == NCERR_SUCCESS){
// codecctx seems to be off by a factor of 2 regularly. instead, go with
// the time_base from the avformatctx.
double tbase = av_q2d(ncv->fmtctx->streams[ncv->stream_index]->time_base);
int64_t ts = avf->best_effort_timestamp;
int64_t ts = ncv->oframe->best_effort_timestamp;
if(frame == 1 && ts){
usets = true;
}
@ -486,7 +483,7 @@ int ncvisual_stream(notcurses* nc, ncvisual* ncv, nc_err_e* ncerr,
clock_gettime(CLOCK_MONOTONIC, &now);
uint64_t nsnow = timespec_to_ns(&now);
struct timespec interval;
uint64_t duration = avf->pkt_duration * tbase * NANOSECS_IN_SEC;
uint64_t duration = ncv->oframe->pkt_duration * tbase * NANOSECS_IN_SEC;
//fprintf(stderr, "use: %u dur: %ju ts: %ju cctx: %f fctx: %f\n", usets, duration, ts, av_q2d(ncv->codecctx->time_base), av_q2d(ncv->fmtctx->streams[ncv->stream_index]->time_base));
sum_duration += (duration * ncv->timescale);
double schedns = nsbegin;
@ -520,10 +517,9 @@ bool notcurses_canopen(const notcurses* nc __attribute__ ((unused))){
return false;
}
struct AVFrame* ncvisual_decode(ncvisual* nc, nc_err_e* ncerr){
nc_err_e ncvisual_decode(ncvisual* nc){
(void)nc;
(void)ncerr;
return NULL;
return NCERR_UNIMPLEMENTED;
}
int ncvisual_render(const ncvisual* ncv, int begy, int begx, int leny, int lenx){

View File

@ -75,10 +75,9 @@ ncvisual* ncvisual_open_plane(notcurses* nc, const char* filename,
return ncv;
}
struct AVFrame* ncvisual_decode(ncvisual* nc, nc_err_e* ncerr){
(void)nc;
(void)ncerr;
return nullptr;
nc_err_e ncvisual_decode(ncvisual* nc){
(void)nc; // FIXME
return NCERR_DECODE;
}
int ncvisual_render(const ncvisual* ncv, int begy, int begx, int leny, int lenx){

View File

@ -88,7 +88,7 @@ int main(void){
if(!ncv){
goto err;
}
if(!ncvisual_decode(ncv, &err)){
if((err = ncvisual_decode(ncv)) != NCERR_SUCCESS){
goto err;
}
if(ncvisual_render(ncv, 0, 0, -1, -1) <= 0){

View File

@ -87,7 +87,7 @@ int main(void){
if(!ncv){
goto err;
}
if(!ncvisual_decode(ncv, &err)){
if((err = ncvisual_decode(ncv)) != NCERR_SUCCESS){
goto err;
}
if(ncvisual_render(ncv, 0, 0, -1, -1) <= 0){

View File

@ -22,7 +22,7 @@ int main(int argc, char** argv){
if(!ncv){
goto err;
}
if(!ncvisual_decode(ncv, &ncerr)){
if((ncerr = ncvisual_decode(ncv)) != NCERR_SUCCESS){
goto err;
}
if(ncvisual_render(ncv, 0, 0, -1, -1) <= 0){

View File

@ -6,7 +6,7 @@ void DrawBackground(const std::string& s) { // drawn to the standard plane
}catch(std::exception& e){
throw TetrisNotcursesErr("visual(): " + s + ": " + e.what());
}
if(!backg_->decode(&err)){
if(backg_->decode() != NCERR_SUCCESS){
throw TetrisNotcursesErr("decode(): " + s);
}
if(backg_->render(0, 0, -1, -1) <= 0){

View File

@ -29,21 +29,19 @@ TEST_CASE("Multimedia") {
}
SUBCASE("LoadImageCreatePlane") {
nc_err_e ncerr;
nc_err_e ncerr = NCERR_SUCCESS;
int dimy, dimx;
ncplane_dim_yx(ncp_, &dimy, &dimx);
auto ncv = ncvisual_open_plane(nc_, find_data("changes.jpg"), &ncerr, 0, 0, NCSCALE_STRETCH);
REQUIRE(ncv);
REQUIRE(0 == ncerr);
auto frame = ncvisual_decode(ncv, &ncerr);
REQUIRE(frame);
REQUIRE(0 == ncerr);
CHECK(dimy * 2 == frame->height);
CHECK(dimx == frame->width);
REQUIRE(NCERR_SUCCESS == ncerr);
ncerr = ncvisual_decode(ncv);
REQUIRE(NCERR_SUCCESS == ncerr);
/*CHECK(dimy * 2 == frame->height);
CHECK(dimx == frame->width); FIXME */
CHECK(0 < ncvisual_render(ncv, 0, 0, -1, -1));
CHECK(0 == notcurses_render(nc_));
frame = ncvisual_decode(ncv, &ncerr);
REQUIRE_EQ(nullptr, frame);
ncerr = ncvisual_decode(ncv);
CHECK(NCERR_EOF == ncerr);
ncvisual_destroy(ncv);
}
@ -54,16 +52,14 @@ TEST_CASE("Multimedia") {
ncplane_dim_yx(ncp_, &dimy, &dimx);
auto ncv = ncplane_visual_open(ncp_, find_data("changes.jpg"), &ncerr);
REQUIRE(ncv);
REQUIRE(NCERR_SUCCESS == ncerr);
auto frame = ncvisual_decode(ncv, &ncerr);
REQUIRE(frame);
REQUIRE(0 == ncerr);
CHECK(dimy * 2 == frame->height);
CHECK(dimx == frame->width);
ncerr = ncvisual_decode(ncv);
REQUIRE(NCERR_SUCCESS == ncerr);
/*CHECK(dimy * 2 == frame->height);
CHECK(dimx == frame->width); FIXME */
CHECK(0 < ncvisual_render(ncv, 0, 0, -1, -1));
CHECK(0 == notcurses_render(nc_));
frame = ncvisual_decode(ncv, &ncerr);
REQUIRE_EQ(nullptr, frame);
ncerr = ncvisual_decode(ncv);
CHECK(NCERR_EOF == ncerr);
ncvisual_destroy(ncv);
}
@ -75,11 +71,10 @@ TEST_CASE("Multimedia") {
auto ncv = ncplane_visual_open(ncp_, find_data("changes.jpg"), &ncerr);
REQUIRE(ncv);
REQUIRE(NCERR_SUCCESS == ncerr);
auto frame = ncvisual_decode(ncv, &ncerr);
REQUIRE(frame);
ncerr = ncvisual_decode(ncv);
REQUIRE(NCERR_SUCCESS == ncerr);
CHECK(dimy * 2 == frame->height);
CHECK(dimx == frame->width);
/*CHECK(dimy * 2 == frame->height);
CHECK(dimx == frame->width); FIXME */
CHECK(0 < ncvisual_render(ncv, 0, 0, -1, -1));
void* needle = malloc(1);
REQUIRE(nullptr != needle);
@ -103,14 +98,13 @@ TEST_CASE("Multimedia") {
REQUIRE(ncv);
CHECK(NCERR_SUCCESS == ncerr);
for(;;){ // run at the highest speed we can
auto frame = ncvisual_decode(ncv, &ncerr);
if(!frame){
CHECK(NCERR_EOF == ncerr);
ncerr = ncvisual_decode(ncv);
if(NCERR_EOF == ncerr){
break;
}
CHECK(0 == ncerr);
CHECK(dimy * 2 == frame->height);
CHECK(dimx == frame->width);
CHECK(NCERR_SUCCESS == ncerr);
/*CHECK(dimy * 2 == frame->height);
CHECK(dimx == frame->width); FIXME */
CHECK(0 < ncvisual_render(ncv, 0, 0, -1, -1));
CHECK(0 == notcurses_render(nc_));
}
@ -124,11 +118,10 @@ TEST_CASE("Multimedia") {
auto ncv = ncvisual_open_plane(nc_, find_data("notcursesI.avi"), &ncerr, 0, 0, NCSCALE_STRETCH);
REQUIRE(ncv);
CHECK(NCERR_SUCCESS == ncerr);
auto frame = ncvisual_decode(ncv, &ncerr);
REQUIRE_NE(nullptr, frame);
ncerr = ncvisual_decode(ncv);
CHECK(NCERR_SUCCESS == ncerr);
CHECK(dimy * 2 == frame->height);
CHECK(dimx == frame->width);
/*CHECK(dimy * 2 == frame->height);
CHECK(dimx == frame->width); FIXME */
CHECK(0 < ncvisual_render(ncv, 0, 0, -1, -1));
CHECK(0 == notcurses_render(nc_));
ncvisual_destroy(ncv);