From 656c2d85c0e480a708cd218df614f8c126b10bed Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 26 May 2013 20:50:58 +0200 Subject: [PATCH 1/5] generic-pc/video: reuse swscale context Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/40d1bb8b632d1a455a48f8917238cf7bcb3023a0 Author: Stefan Seyfried Date: 2013-05-26 (Sun, 26 May 2013) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- generic-pc/video.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/generic-pc/video.cpp b/generic-pc/video.cpp index bcce38a..e541ac7 100644 --- a/generic-pc/video.cpp +++ b/generic-pc/video.cpp @@ -394,6 +394,7 @@ void cVideo::run(void) AVFrame *frame, *rgbframe; uint8_t *inbuf = (uint8_t *)av_malloc(INBUF_SIZE); AVPacket avpkt; + struct SwsContext *convert = NULL; time_t warn_r = 0; /* last read error */ time_t warn_d = 0; /* last decode error */ @@ -475,9 +476,10 @@ void cVideo::run(void) lt_info("%s: WARN: pkt->size %d != len %d\n", __func__, avpkt.size, len); if (got_frame) { unsigned int need = avpicture_get_size(PIX_FMT_RGB32, c->width, c->height); - struct SwsContext *convert = sws_getContext(c->width, c->height, c->pix_fmt, - c->width, c->height, PIX_FMT_RGB32, - SWS_BICUBIC, 0, 0, 0); + convert = sws_getCachedContext(convert, + c->width, c->height, c->pix_fmt, + c->width, c->height, PIX_FMT_RGB32, + SWS_BICUBIC, 0, 0, 0); if (!convert) lt_info("%s: ERROR setting up SWS context\n", __func__); else { @@ -489,7 +491,6 @@ void cVideo::run(void) c->width, c->height); sws_scale(convert, frame->data, frame->linesize, 0, c->height, rgbframe->data, rgbframe->linesize); - sws_freeContext(convert); if (dec_w != c->width || dec_h != c->height) { lt_info("%s: pic changed %dx%d -> %dx%d\n", __func__, dec_w, dec_h, c->width, c->height); @@ -523,6 +524,7 @@ void cVideo::run(void) } av_free_packet(&avpkt); } + sws_freeContext(convert); out2: avcodec_close(c); avcodec_free_frame(&frame); From 53bdc369603cd356ce579962cc53296aaeeba31d Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 26 May 2013 20:52:43 +0200 Subject: [PATCH 2/5] generic-pc/video: implement getScreenImage (experimental) Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/adb6db1bebad89f77a0ab48683048f81221ca67e Author: Stefan Seyfried Date: 2013-05-26 (Sun, 26 May 2013) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- generic-pc/video.cpp | 105 +++++++++++++++++++++++++++++++++++++++++ generic-pc/video_lib.h | 1 + 2 files changed, 106 insertions(+) diff --git a/generic-pc/video.cpp b/generic-pc/video.cpp index e541ac7..341f6e9 100644 --- a/generic-pc/video.cpp +++ b/generic-pc/video.cpp @@ -44,6 +44,7 @@ extern "C" { #include "lt_debug.h" #define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, this, args) #define lt_info(args...) _lt_info(TRIPLE_DEBUG_VIDEO, this, args) +#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_VIDEO, NULL, args) cVideo *videoDecoder = NULL; extern cDemux *videoDemux; @@ -540,3 +541,107 @@ void cVideo::run(void) buf_out = 0; lt_info("======================== end decoder thread ================================\n"); } + +static bool swscale(unsigned char *src, unsigned char *dst, int sw, int sh, int dw, int dh) +{ + bool ret = false; + struct SwsContext *scale = NULL; + AVFrame *sframe, *dframe; + scale = sws_getCachedContext(scale, sw, sh, PIX_FMT_RGB32, dw, dh, PIX_FMT_RGB32, SWS_BICUBIC, 0, 0, 0); + if (!scale) { + lt_info_c("%s: ERROR setting up SWS context\n", __func__); + return false; + } + sframe = avcodec_alloc_frame(); + dframe = avcodec_alloc_frame(); + if (!sframe || !dframe) { + lt_info_c("%s: could not alloc sframe (%p) or dframe (%p)\n", __func__, sframe, dframe); + goto out; + } + avpicture_fill((AVPicture *)sframe, &(src[0]), PIX_FMT_RGB32, sw, sh); + avpicture_fill((AVPicture *)dframe, &(dst[0]), PIX_FMT_RGB32, dw, dh); + sws_scale(scale, sframe->data, sframe->linesize, 0, sh, dframe->data, dframe->linesize); + out: + avcodec_free_frame(&sframe); + avcodec_free_frame(&dframe); + sws_freeContext(scale); + return ret; +} + +bool cVideo::GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video, bool get_osd, bool scale_to_video) +{ + lt_info("%s: data 0x%p xres %d yres %d vid %d osd %d scale %d\n", + __func__, data, xres, yres, get_video, get_osd, scale_to_video); + SWFramebuffer video; + std::vector *osd = NULL; + std::vector s_osd; /* scaled OSD */ + int vid_w = 0, vid_h = 0; + int osd_w = glfb->getOSDWidth(); + int osd_h = glfb->getOSDHeight(); + xres = osd_w; + yres = osd_h; + if (get_video) { + buf_m.lock(); + video = buffers[buf_out]; + buf_m.unlock(); + vid_w = video.width(); + vid_h = video.height(); + if (scale_to_video || !get_osd) { + xres = vid_w; + yres = vid_h; + AVRational a = video.AR(); + /* TODO: this does not consider display_aspect and display_crop */ + if (a.num > 0 && a.den > 0) + xres = vid_w * a.num / a.den; + } + } + if (get_osd) + osd = glfb->getOSDBuffer(); + unsigned int need = avpicture_get_size(PIX_FMT_RGB32, xres, yres); + data = (unsigned char *)realloc(data, need); /* will be freed by caller */ + if (data == NULL) /* out of memory? */ + return false; + + if (get_video) { + if (vid_w != xres || vid_h != yres) /* scale video into data... */ + swscale(&video[0], data, vid_w, vid_h, xres, yres); + else /* get_video and no fancy scaling needed */ + memcpy(data, &video[0], xres * yres * sizeof(uint32_t)); + } + + if (get_osd && (osd_w != xres || osd_h != yres)) { + /* rescale osd */ + s_osd.resize(need); + swscale(&(*osd)[0], &s_osd[0], osd_w, osd_h, xres, yres); + osd = &s_osd; + } + + if (get_video && get_osd) { + /* alpha blend osd onto data (video). TODO: maybe libavcodec can do this? */ + uint32_t *d = (uint32_t *)data; + uint32_t *pixpos = (uint32_t *)&(*osd)[0]; + for (int count = 0; count < yres; count++) { + for (int count2 = 0; count2 < xres; count2++ ) { + uint32_t pix = *pixpos; + if ((pix & 0xff000000) == 0xff000000) + *d = pix; + else { + uint8_t *in = (uint8_t *)(pixpos); + uint8_t *out = (uint8_t *)d; + int a = in[3]; /* TODO: big/little endian? */ + *out = (*out + ((*in - *out) * a) / 256); + in++; out++; + *out = (*out + ((*in - *out) * a) / 256); + in++; out++; + *out = (*out + ((*in - *out) * a) / 256); + } + d++; + pixpos++; + } + } + } + else if (get_osd) /* only get_osd, data is not yet populated */ + memcpy(data, &(*osd)[0], xres * yres * sizeof(uint32_t)); + + return true; +} diff --git a/generic-pc/video_lib.h b/generic-pc/video_lib.h index 493b8a4..55a0d8d 100644 --- a/generic-pc/video_lib.h +++ b/generic-pc/video_lib.h @@ -190,6 +190,7 @@ class cVideo : public OpenThreads::Thread int CloseVBI(void) { return 0; }; int StartVBI(unsigned short) { return 0; }; int StopVBI(void) { return 0; }; + bool GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video = true, bool get_osd = false, bool scale_to_video = false); SWFramebuffer *getDecBuf(void); private: void run(); From 11b3872cefe28a6e65f634643923f9ae41fae4a8 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Mon, 27 May 2013 00:45:42 +0200 Subject: [PATCH 3/5] generic/glfb: add a few keys to F5-F8 Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/9593fe09cfb8fa4be7bc67e6b49f935e625673f4 Author: Stefan Seyfried Date: 2013-05-27 (Mon, 27 May 2013) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- generic-pc/glfb.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/generic-pc/glfb.cpp b/generic-pc/glfb.cpp index 399d486..c5a0cc0 100644 --- a/generic-pc/glfb.cpp +++ b/generic-pc/glfb.cpp @@ -121,6 +121,11 @@ void GLFramebuffer::initKeys() mSpecialMap[GLUT_KEY_F3] = KEY_YELLOW; mSpecialMap[GLUT_KEY_F4] = KEY_BLUE; + mSpecialMap[GLUT_KEY_F5] = KEY_WWW; + mSpecialMap[GLUT_KEY_F6] = KEY_SUBTITLE; + mSpecialMap[GLUT_KEY_F7] = KEY_MOVE; + mSpecialMap[GLUT_KEY_F8] = KEY_SLEEP; + mSpecialMap[GLUT_KEY_PAGE_UP] = KEY_PAGEUP; mSpecialMap[GLUT_KEY_PAGE_DOWN] = KEY_PAGEDOWN; From 955d4d651bd274a2a4b3ca049a12240f357c30ff Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Mon, 27 May 2013 00:47:35 +0200 Subject: [PATCH 4/5] generic-pc: add Pig function to cVideo / GLFB Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/05ac1163127e28b115b9dbeab2eed830c72ae5ae Author: Stefan Seyfried Date: 2013-05-27 (Mon, 27 May 2013) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- generic-pc/glfb.cpp | 27 ++++++++++++++++++++++++++- generic-pc/video.cpp | 7 ++++++- generic-pc/video_lib.h | 8 +++++++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/generic-pc/glfb.cpp b/generic-pc/glfb.cpp index c5a0cc0..2db24d8 100644 --- a/generic-pc/glfb.cpp +++ b/generic-pc/glfb.cpp @@ -417,7 +417,7 @@ void GLFramebuffer::render() glBindTexture(GL_TEXTURE_2D, mState.displaytex); drawSquare(zoom, xscale); glBindTexture(GL_TEXTURE_2D, mState.osdtex); - drawSquare(1.0); + drawSquare(1.0, -100); glFlush(); glutSwapBuffers(); @@ -472,6 +472,31 @@ void GLFramebuffer::drawSquare(float size, float x_factor) 0.0, 1.0, 1.0, 1.0, }; + if (x_factor > -99.0) { /* x_factor == -100 => OSD */ + if (videoDecoder && + videoDecoder->pig_x > 0 && videoDecoder->pig_y > 0 && + videoDecoder->pig_w > 0 && videoDecoder->pig_h > 0) { + /* these calculations even consider cropping and panscan mode + * maybe this could be done with some clever opengl tricks? */ + double w2 = (double)mState.width * 0.5l; + double h2 = (double)mState.height * 0.5l; + double x = (double)(videoDecoder->pig_x - w2) / w2 / x_factor / size; + double y = (double)(h2 - videoDecoder->pig_y) / h2 / size; + double w = (double)videoDecoder->pig_w / w2; + double h = (double)videoDecoder->pig_h / h2; + x += ((1.0l - x_factor * size) / 2.0l) * w / x_factor / size; + y += ((size - 1.0l) / 2.0l) * h / size; + vertices[0] = x + w; /* top right x */ + vertices[1] = y; /* top right y */ + vertices[2] = x; /* top left x */ + vertices[3] = y; /* top left y */ + vertices[4] = x; /* bottom left x */ + vertices[5] = y - h; /* bottom left y */ + vertices[6] = vertices[0]; /* bottom right x */ + vertices[7] = vertices[5]; /* bottom right y */ + } + } else + x_factor = 1.0; /* OSD */ glPushMatrix(); glScalef(size * x_factor, size, size); diff --git a/generic-pc/video.cpp b/generic-pc/video.cpp index 341f6e9..5c4616f 100644 --- a/generic-pc/video.cpp +++ b/generic-pc/video.cpp @@ -78,6 +78,7 @@ cVideo::cVideo(int, void *, void *) buf_num = 0; buf_in = 0; buf_out = 0; + pig_x = pig_y = pig_w = pig_h = 0; display_aspect = DISPLAY_AR_16_9; display_crop = DISPLAY_AR_MODE_LETTERBOX; v_format = VIDEO_FORMAT_MPEG2; @@ -325,8 +326,12 @@ int cVideo::getBlank(void) return 0; } -void cVideo::Pig(int, int, int, int, int, int) +void cVideo::Pig(int x, int y, int w, int h, int, int) { + pig_x = x; + pig_y = y; + pig_w = w; + pig_h = h; } void cVideo::getPictureInfo(int &width, int &height, int &rate) diff --git a/generic-pc/video_lib.h b/generic-pc/video_lib.h index 55a0d8d..36f9892 100644 --- a/generic-pc/video_lib.h +++ b/generic-pc/video_lib.h @@ -121,7 +121,8 @@ typedef enum #define VDEC_MAXBUFS 0x30 class cVideo : public OpenThreads::Thread { - public: + friend class GLFramebuffer; + private: /* called from GL thread */ class SWFramebuffer : public std::vector { @@ -142,6 +143,7 @@ class cVideo : public OpenThreads::Thread AVRational mAR; }; int buf_in, buf_out, buf_num; + public: /* constructor & destructor */ cVideo(int mode, void *, void *); ~cVideo(void); @@ -205,6 +207,10 @@ class cVideo : public OpenThreads::Thread DISPLAY_AR display_aspect; DISPLAY_AR_MODE display_crop; int output_h; + int pig_x; + int pig_y; + int pig_w; + int pig_h; }; #endif From 9db763cac76c2e9a67e8c12db060fccf83084035 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Mon, 27 May 2013 13:51:09 +0200 Subject: [PATCH 5/5] configure: specify the needed ffmpeg versions Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/7b32a966358d1b8dca4423ea55f97cb91fa0042a Author: Stefan Seyfried Date: 2013-05-27 (Mon, 27 May 2013) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- configure.ac | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index b8a2911..163d9ea 100644 --- a/configure.ac +++ b/configure.ac @@ -24,10 +24,11 @@ if test x"$BOXTYPE" = x"tripledragon"; then fi if test x$BOXTYPE = xgeneric; then - TUXBOX_APPS_LIB_PKGCONFIG(AVFORMAT,libavformat) - TUXBOX_APPS_LIB_PKGCONFIG(AVCODEC,libavcodec) - TUXBOX_APPS_LIB_PKGCONFIG(AVUTIL,libavutil) - TUXBOX_APPS_LIB_PKGCONFIG(SWSCALE,libswscale) + PKG_CHECK_MODULES([AVFORMAT], [libavformat >= 53.21.1]) + PKG_CHECK_MODULES([AVCODEC], [libavcodec >= 54.28.0]) + # don't know which version is exactly needed here... + PKG_CHECK_MODULES([AVUTIL], [libavutil]) + PKG_CHECK_MODULES([SWSCALE], [libswscale]) fi AC_OUTPUT([ Makefile