hide ffmpeg ncvisual definition

This commit is contained in:
nick black 2020-04-23 08:13:32 -04:00 committed by Nick Black
parent ddfa62db70
commit 5bae4f93b8
4 changed files with 169 additions and 136 deletions

90
src/lib/blit.c Normal file
View File

@ -0,0 +1,90 @@
#include "internal.h"
// alpha comes to us 0--255, but we have only 3 alpha values to map them to.
// settled on experimentally.
static inline bool
ffmpeg_trans_p(bool bgr, unsigned char alpha){
if(!bgr && alpha < 192){
return true;
}
return false;
}
// RGBA/BGRx blitter. For incoming BGRx (no transparency), bgr == true.
static inline int
tria_blit(ncplane* nc, int placey, int placex, int linesize, const void* data,
int begy, int begx, int leny, int lenx, bool bgr){
const int bpp = 32;
const int rpos = bgr ? 2 : 0;
const int bpos = bgr ? 0 : 2;
int dimy, dimx, x, y;
int visy = begy;
int total = 0; // number of cells written
ncplane_dim_yx(nc, &dimy, &dimx);
// FIXME not going to necessarily be safe on all architectures hrmmm
const unsigned char* dat = data;
for(y = placey ; visy < (begy + leny) && y < dimy ; ++y, visy += 2){
if(ncplane_cursor_move_yx(nc, y, placex)){
return -1;
}
int visx = begx;
for(x = placex ; visx < (begx + lenx) && x < dimx ; ++x, ++visx){
const unsigned char* rgbbase_up = dat + (linesize * visy) + (visx * bpp / CHAR_BIT);
const unsigned char* rgbbase_down = dat + (linesize * (visy + 1)) + (visx * bpp / CHAR_BIT);
//fprintf(stderr, "[%04d/%04d] bpp: %d lsize: %d %02x %02x %02x %02x\n", y, x, bpp, linesize, rgbbase_up[0], rgbbase_up[1], rgbbase_up[2], rgbbase_up[3]);
cell* c = ncplane_cell_ref_yx(nc, y, x);
// use the default for the background, as that's the only way it's
// effective in that case anyway
c->channels = 0;
c->attrword = 0;
if(ffmpeg_trans_p(bgr, rgbbase_up[3]) || ffmpeg_trans_p(bgr, rgbbase_down[3])){
cell_set_bg_alpha(c, CELL_ALPHA_TRANSPARENT);
if(ffmpeg_trans_p(bgr, rgbbase_up[3]) && ffmpeg_trans_p(bgr, rgbbase_down[3])){
cell_set_fg_alpha(c, CELL_ALPHA_TRANSPARENT);
}else if(ffmpeg_trans_p(bgr, rgbbase_up[3])){ // down has the color
if(cell_load(nc, c, "\u2584") <= 0){ // lower half block
return -1;
}
cell_set_fg_rgb(c, rgbbase_down[rpos], rgbbase_down[1], rgbbase_down[bpos]);
}else{ // up has the color
if(cell_load(nc, c, "\u2580") <= 0){ // upper half block
return -1;
}
cell_set_fg_rgb(c, rgbbase_up[rpos], rgbbase_up[1], rgbbase_up[bpos]);
}
}else{
if(memcmp(rgbbase_up, rgbbase_down, 3) == 0){
cell_set_fg_rgb(c, rgbbase_down[rpos], rgbbase_down[1], rgbbase_down[bpos]);
cell_set_bg_rgb(c, rgbbase_down[rpos], rgbbase_down[1], rgbbase_down[bpos]);
if(cell_load(nc, c, " ") <= 0){ // only need the background
return -1;
}
}else{
cell_set_fg_rgb(c, rgbbase_up[rpos], rgbbase_up[1], rgbbase_up[bpos]);
cell_set_bg_rgb(c, rgbbase_down[rpos], rgbbase_down[1], rgbbase_down[bpos]);
if(cell_load(nc, c, "\u2580") <= 0){ // upper half block
return -1;
}
}
}
++total;
}
}
return total;
}
// Blit a flat array 'data' of BGRx 32-bit values to the ncplane 'nc', offset
// from the upper left by 'placey' and 'placex'. Each row ought occupy
// 'linesize' bytes (this might be greater than lenx * 4 due to padding). A
// subregion of the input can be specified with 'begy'x'begx' and 'leny'x'lenx'.
int ncblit_bgrx(ncplane* nc, int placey, int placex, int linesize,
const void* data, int begy, int begx, int leny, int lenx){
return tria_blit(nc, placey, placex, linesize, data,
begy, begx, leny, lenx, true);
}
int ncblit_rgba(ncplane* nc, int placey, int placex, int linesize,
const void* data, int begy, int begx, int leny, int lenx){
return tria_blit(nc, placey, placex, linesize, data,
begy, begx, leny, lenx, false);
}

View File

@ -80,34 +80,6 @@ typedef struct ncplane {
bool scrolling; // is scrolling enabled? always disabled by default
} ncplane;
typedef struct ncvisual {
struct AVFormatContext* fmtctx;
struct AVCodecContext* codecctx; // video codec context
struct AVCodecContext* subtcodecctx; // subtitle codec context
struct AVFrame* frame;
struct AVFrame* oframe;
struct AVCodec* codec;
struct AVCodecParameters* cparams;
struct AVCodec* subtcodec;
struct AVPacket* packet;
struct SwsContext* swsctx;
int packet_outstanding;
int dstwidth, dstheight;
int stream_index; // match against this following av_read_frame()
int sub_stream_index; // subtitle stream index, can be < 0 if no subtitles
float timescale; // scale frame duration by this value
ncplane* ncp;
// if we're creating the plane based off the first frame's dimensions, these
// describe where the plane ought be placed, and how it ought be sized. this
// path sets ncobj. ncvisual_destroy() ought in that case kill the ncplane.
int placex, placey;
ncscale_e style; // none, scale, or stretch
struct notcurses* ncobj; // set iff this ncvisual "owns" its ncplane
#ifdef USE_FFMPEG
AVSubtitle subtitle;
#endif
} ncvisual;
// current presentation state of the terminal. it is carried across render
// instances. initialize everything to 0 on a terminal reset / startup.
typedef struct renderstate {

View File

@ -2,99 +2,38 @@
#include "version.h"
#include "internal.h"
typedef struct ncvisual {
struct AVFormatContext* fmtctx;
struct AVCodecContext* codecctx; // video codec context
struct AVCodecContext* subtcodecctx; // subtitle codec context
struct AVFrame* frame;
struct AVFrame* oframe;
struct AVCodec* codec;
struct AVCodecParameters* cparams;
struct AVCodec* subtcodec;
struct AVPacket* packet;
struct SwsContext* swsctx;
int packet_outstanding;
int dstwidth, dstheight;
int stream_index; // match against this following av_read_frame()
int sub_stream_index; // subtitle stream index, can be < 0 if no subtitles
float timescale; // scale frame duration by this value
ncplane* ncp;
// if we're creating the plane based off the first frame's dimensions, these
// describe where the plane ought be placed, and how it ought be sized. this
// path sets ncobj. ncvisual_destroy() ought in that case kill the ncplane.
int placex, placey;
ncscale_e style; // none, scale, or stretch
struct notcurses* ncobj; // set iff this ncvisual "owns" its ncplane
#ifdef USE_FFMPEG
AVSubtitle subtitle;
#endif
} ncvisual;
ncplane* ncvisual_plane(ncvisual* ncv){
return ncv->ncp;
}
// alpha comes to us 0--255, but we have only 3 alpha values to map them to.
// settled on experimentally.
static inline bool
ffmpeg_trans_p(bool bgr, unsigned char alpha){
if(!bgr && alpha < 192){
return true;
}
return false;
}
// RGBA/BGRx blitter. For incoming BGRx (no transparency), bgr == true.
static inline int
tria_blit(ncplane* nc, int placey, int placex, int linesize, const void* data,
int begy, int begx, int leny, int lenx, bool bgr){
const int bpp = 32;
const int rpos = bgr ? 2 : 0;
const int bpos = bgr ? 0 : 2;
int dimy, dimx, x, y;
int visy = begy;
int total = 0; // number of cells written
ncplane_dim_yx(nc, &dimy, &dimx);
// FIXME not going to necessarily be safe on all architectures hrmmm
const unsigned char* dat = data;
for(y = placey ; visy < (begy + leny) && y < dimy ; ++y, visy += 2){
if(ncplane_cursor_move_yx(nc, y, placex)){
return -1;
}
int visx = begx;
for(x = placex ; visx < (begx + lenx) && x < dimx ; ++x, ++visx){
const unsigned char* rgbbase_up = dat + (linesize * visy) + (visx * bpp / CHAR_BIT);
const unsigned char* rgbbase_down = dat + (linesize * (visy + 1)) + (visx * bpp / CHAR_BIT);
//fprintf(stderr, "[%04d/%04d] bpp: %d lsize: %d %02x %02x %02x %02x\n", y, x, bpp, linesize, rgbbase_up[0], rgbbase_up[1], rgbbase_up[2], rgbbase_up[3]);
cell* c = ncplane_cell_ref_yx(nc, y, x);
// use the default for the background, as that's the only way it's
// effective in that case anyway
c->channels = 0;
c->attrword = 0;
if(ffmpeg_trans_p(bgr, rgbbase_up[3]) || ffmpeg_trans_p(bgr, rgbbase_down[3])){
cell_set_bg_alpha(c, CELL_ALPHA_TRANSPARENT);
if(ffmpeg_trans_p(bgr, rgbbase_up[3]) && ffmpeg_trans_p(bgr, rgbbase_down[3])){
cell_set_fg_alpha(c, CELL_ALPHA_TRANSPARENT);
}else if(ffmpeg_trans_p(bgr, rgbbase_up[3])){ // down has the color
if(cell_load(nc, c, "\u2584") <= 0){ // lower half block
return -1;
}
cell_set_fg_rgb(c, rgbbase_down[rpos], rgbbase_down[1], rgbbase_down[bpos]);
}else{ // up has the color
if(cell_load(nc, c, "\u2580") <= 0){ // upper half block
return -1;
}
cell_set_fg_rgb(c, rgbbase_up[rpos], rgbbase_up[1], rgbbase_up[bpos]);
}
}else{
if(memcmp(rgbbase_up, rgbbase_down, 3) == 0){
cell_set_fg_rgb(c, rgbbase_down[rpos], rgbbase_down[1], rgbbase_down[bpos]);
cell_set_bg_rgb(c, rgbbase_down[rpos], rgbbase_down[1], rgbbase_down[bpos]);
if(cell_load(nc, c, " ") <= 0){ // only need the background
return -1;
}
}else{
cell_set_fg_rgb(c, rgbbase_up[rpos], rgbbase_up[1], rgbbase_up[bpos]);
cell_set_bg_rgb(c, rgbbase_down[rpos], rgbbase_down[1], rgbbase_down[bpos]);
if(cell_load(nc, c, "\u2580") <= 0){ // upper half block
return -1;
}
}
}
++total;
}
}
return total;
}
// Blit a flat array 'data' of BGRx 32-bit values to the ncplane 'nc', offset
// from the upper left by 'placey' and 'placex'. Each row ought occupy
// 'linesize' bytes (this might be greater than lenx * 4 due to padding). A
// subregion of the input can be specified with 'begy'x'begx' and 'leny'x'lenx'.
int ncblit_bgrx(ncplane* nc, int placey, int placex, int linesize,
const void* data, int begy, int begx, int leny, int lenx){
return tria_blit(nc, placey, placex, linesize, data,
begy, begx, leny, lenx, true);
}
int ncblit_rgba(ncplane* nc, int placey, int placex, int linesize,
const void* data, int begy, int begx, int leny, int lenx){
return tria_blit(nc, placey, placex, linesize, data,
begy, begx, leny, lenx, false);
}
void ncvisual_destroy(ncvisual* ncv){
if(ncv){
#ifdef USE_FFMPEG

View File

@ -1,8 +1,58 @@
#include "internal.h"
#ifdef USE_OIIO
#include <OpenImageIO/imageio.h>
typedef struct ncvisual {
struct AVFormatContext* fmtctx;
struct AVCodecContext* codecctx; // video codec context
struct AVCodecContext* subtcodecctx; // subtitle codec context
struct AVFrame* frame;
struct AVFrame* oframe;
struct AVCodec* codec;
struct AVCodecParameters* cparams;
struct AVCodec* subtcodec;
struct AVPacket* packet;
struct SwsContext* swsctx;
int packet_outstanding;
int dstwidth, dstheight;
int stream_index; // match against this following av_read_frame()
int sub_stream_index; // subtitle stream index, can be < 0 if no subtitles
float timescale; // scale frame duration by this value
ncplane* ncp;
// if we're creating the plane based off the first frame's dimensions, these
// describe where the plane ought be placed, and how it ought be sized. this
// path sets ncobj. ncvisual_destroy() ought in that case kill the ncplane.
int placex, placey;
ncscale_e style; // none, scale, or stretch
struct notcurses* ncobj; // set iff this ncvisual "owns" its ncplane
#ifdef USE_FFMPEG
AVSubtitle subtitle;
#endif
} ncvisual;
bool notcurses_canopen(const notcurses* nc __attribute__ ((unused))){
return false;
return true;
}
ncvisual* ncplane_visual_open(ncplane* nc, const char* filename, int* averr){
auto in = OIIO::ImageInput::open(filename);
if(!in){
return nullptr;
}
(void)nc;
(void)averr;
return NULL;
}
ncvisual* ncvisual_open_plane(notcurses* nc, const char* filename,
int* averr, int y, int x, ncscale_e style){
(void)nc;
(void)filename;
(void)averr;
(void)y;
(void)x;
(void)style;
return NULL;
}
struct AVFrame* ncvisual_decode(ncvisual* nc, int* averr){
@ -31,24 +81,6 @@ int ncvisual_stream(struct notcurses* nc, struct ncvisual* ncv, int* averr,
return -1;
}
ncvisual* ncplane_visual_open(ncplane* nc, const char* filename, int* averr){
(void)nc;
(void)filename;
(void)averr;
return NULL;
}
ncvisual* ncvisual_open_plane(notcurses* nc, const char* filename,
int* averr, int y, int x, ncscale_e style){
(void)nc;
(void)filename;
(void)averr;
(void)y;
(void)x;
(void)style;
return NULL;
}
char* ncvisual_subtitle(const ncvisual* ncv){
(void)ncv;
return NULL;