mirror of
https://github.com/tuxbox-neutrino/libstb-hal.git
synced 2025-08-26 23:13:16 +02:00
libtriple: implement ShowPicture() in cVideo
this needs the ffmpeg binary with support for mjpeg decoder and mpeg2video encoder to recode the jpgs to m2v
This commit is contained in:
@@ -28,6 +28,8 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
//#include <zapit/zapit.h>
|
//#include <zapit/zapit.h>
|
||||||
#include <zapit/debug.h>
|
#include <zapit/debug.h>
|
||||||
//#include <zapit/settings.h>
|
//#include <zapit/settings.h>
|
||||||
@@ -41,7 +43,16 @@
|
|||||||
cVideo * videoDecoder = NULL;
|
cVideo * videoDecoder = NULL;
|
||||||
int system_rev = 0;
|
int system_rev = 0;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* this would be necessary for the DirectFB implementation of ShowPicture */
|
||||||
|
#include <directfb.h>
|
||||||
|
#include <tdgfx/stb04gfx.h>
|
||||||
|
extern IDirectFB *dfb;
|
||||||
|
extern IDirectFBSurface *dfbdest;
|
||||||
|
#endif
|
||||||
|
|
||||||
extern struct Ssettings settings;
|
extern struct Ssettings settings;
|
||||||
|
static pthread_mutex_t stillp_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
cVideo::cVideo(int, void *, void *)
|
cVideo::cVideo(int, void *, void *)
|
||||||
{
|
{
|
||||||
@@ -263,14 +274,17 @@ int cVideo::Stop(bool blank)
|
|||||||
|
|
||||||
int cVideo::setBlank(int)
|
int cVideo::setBlank(int)
|
||||||
{
|
{
|
||||||
|
lt_debug("cVideo::setBlank\n");
|
||||||
/* The TripleDragon has no VIDEO_SET_BLANK ioctl.
|
/* The TripleDragon has no VIDEO_SET_BLANK ioctl.
|
||||||
instead, you write a black still-MPEG Iframe into the decoder.
|
instead, you write a black still-MPEG Iframe into the decoder.
|
||||||
The original software uses different files for 4:3 and 16:9 and
|
The original software uses different files for 4:3 and 16:9 and
|
||||||
for PAL and NTSC. I optimized that a little bit
|
for PAL and NTSC. I optimized that a little bit
|
||||||
*/
|
*/
|
||||||
int index = 0; /* default PAL */
|
int index = 0; /* default PAL */
|
||||||
|
int ret = 0;
|
||||||
VIDEOINFO v;
|
VIDEOINFO v;
|
||||||
BUFINFO buf;
|
BUFINFO buf;
|
||||||
|
pthread_mutex_lock(&stillp_mutex);
|
||||||
memset(&v, 0, sizeof(v));
|
memset(&v, 0, sizeof(v));
|
||||||
quiet_fop(ioctl, MPEG_VID_GET_V_INFO, &v);
|
quiet_fop(ioctl, MPEG_VID_GET_V_INFO, &v);
|
||||||
|
|
||||||
@@ -281,8 +295,10 @@ int cVideo::setBlank(int)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (blank_data[index] == NULL) /* no MPEG found */
|
if (blank_data[index] == NULL) /* no MPEG found */
|
||||||
return -1;
|
{
|
||||||
|
ret = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
/* hack: this might work only on those two still-MPEG files!
|
/* hack: this might work only on those two still-MPEG files!
|
||||||
I diff'ed the 4:3 and the 16:9 still mpeg from the original
|
I diff'ed the 4:3 and the 16:9 still mpeg from the original
|
||||||
soft and spotted the single bit difference, so there is no
|
soft and spotted the single bit difference, so there is no
|
||||||
@@ -299,7 +315,10 @@ int cVideo::setBlank(int)
|
|||||||
buf.ulLen = blank_size[index];
|
buf.ulLen = blank_size[index];
|
||||||
buf.ulStartAdrOff = (int)blank_data[index];
|
buf.ulStartAdrOff = (int)blank_data[index];
|
||||||
fop(ioctl, MPEG_VID_STILLP_WRITE, &buf);
|
fop(ioctl, MPEG_VID_STILLP_WRITE, &buf);
|
||||||
return fop(ioctl, MPEG_VID_SELECT_SOURCE, VID_SOURCE_DEMUX);
|
ret = fop(ioctl, MPEG_VID_SELECT_SOURCE, VID_SOURCE_DEMUX);
|
||||||
|
out:
|
||||||
|
pthread_mutex_unlock(&stillp_mutex);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cVideo::SetVideoSystem(int video_system, bool remember)
|
int cVideo::SetVideoSystem(int video_system, bool remember)
|
||||||
@@ -335,7 +354,88 @@ void cVideo::SetVideoMode(analog_mode_t mode)
|
|||||||
|
|
||||||
void cVideo::ShowPicture(const char * fname)
|
void cVideo::ShowPicture(const char * fname)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "cVideo::ShowPicture: %s\n", fname);
|
lt_debug("cVideo::ShowPicture: %s\n", fname);
|
||||||
|
char destname[512];
|
||||||
|
char cmd[512];
|
||||||
|
char *p;
|
||||||
|
void *data;
|
||||||
|
int mfd;
|
||||||
|
struct stat st;
|
||||||
|
strcpy(destname, "/var/cache");
|
||||||
|
mkdir(destname, 0755);
|
||||||
|
/* the cache filename is (example for /share/tuxbox/neutrino/icons/radiomode.jpg):
|
||||||
|
/var/cache/share.tuxbox.neutrino.icons.radiomode.jpg.m2v
|
||||||
|
build that filename first...
|
||||||
|
TODO: this could cause name clashes, use a hashing function instead... */
|
||||||
|
strcat(destname, fname);
|
||||||
|
p = &destname[strlen("/var/cache/")];
|
||||||
|
while ((p = strchr(p, '/')) != NULL)
|
||||||
|
*p = '.';
|
||||||
|
strcat(destname, ".m2v");
|
||||||
|
/* ...then check if it exists already...
|
||||||
|
TODO: check if the cache file is older than the jpeg file... */
|
||||||
|
if (access(destname, R_OK))
|
||||||
|
{
|
||||||
|
/* it does not exist, so call ffmpeg to create it... */
|
||||||
|
sprintf(cmd, "ffmpeg -y -f mjpeg -i '%s' -s 704x576 '%s' </dev/null",
|
||||||
|
fname, destname);
|
||||||
|
system(cmd); /* TODO: use libavcodec to directly convert it */
|
||||||
|
}
|
||||||
|
/* the mutex is a workaround: setBlank is apparently called from
|
||||||
|
a differnt thread and takes slightly longer, so that the decoder
|
||||||
|
was blanked immediately after displaying the image, which is not
|
||||||
|
what we want. the mutex ensures proper ordering. */
|
||||||
|
pthread_mutex_lock(&stillp_mutex);
|
||||||
|
mfd = open(destname, O_RDONLY);
|
||||||
|
if (mfd < 0)
|
||||||
|
{
|
||||||
|
WARN("cannot open %s: %m", destname);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (fstat(mfd, &st) != -1 && st.st_size > 0)
|
||||||
|
{
|
||||||
|
data = malloc(st.st_size);
|
||||||
|
if (! data)
|
||||||
|
ERROR("cannot malloc memory");
|
||||||
|
else if (read(mfd, data, st.st_size) != st.st_size)
|
||||||
|
ERROR("short read");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BUFINFO buf;
|
||||||
|
buf.ulLen = st.st_size;
|
||||||
|
buf.ulStartAdrOff = (int)data;
|
||||||
|
Stop(false);
|
||||||
|
fop(ioctl, MPEG_VID_STILLP_WRITE, &buf);
|
||||||
|
}
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
close(mfd);
|
||||||
|
out:
|
||||||
|
pthread_mutex_unlock(&stillp_mutex);
|
||||||
|
return;
|
||||||
|
#if 0
|
||||||
|
/* DirectFB based picviewer: works, but is slow and the infobar
|
||||||
|
draws in the same plane */
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
if (!fname)
|
||||||
|
return;
|
||||||
|
|
||||||
|
IDirectFBImageProvider *provider;
|
||||||
|
DFBResult err = dfb->CreateImageProvider(dfb, fname, &provider);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "cVideo::ShowPicture: CreateImageProvider error!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DFBSurfaceDescription desc;
|
||||||
|
provider->GetSurfaceDescription (provider, &desc);
|
||||||
|
width = desc.width;
|
||||||
|
height = desc.height;
|
||||||
|
provider->RenderTo(provider, dfbdest, NULL);
|
||||||
|
provider->Release(provider);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void cVideo::StopPicture()
|
void cVideo::StopPicture()
|
||||||
|
Reference in New Issue
Block a user