Files » xine-plugin-0.9.4-grab.patch
| xineLib.c | ||
|---|---|---|
|
cXineLib::cXineLib(cPlugin *const plugin, const cXineSettings &settings, cMutex &osdMutex, cXineRemote *const remote)
|
||
|
: cThread()
|
||
|
, m_plugin(plugin)
|
||
|
, m_xine_version(0)
|
||
|
, m_settings(settings)
|
||
|
, m_osdFlushRequired(false)
|
||
|
, fd_fifo0_serv(-1)
|
||
| ... | ... | |
|
bool cXineLib::checkXineVersion()
|
||
|
{
|
||
|
int32_t version = 0;
|
||
|
execFuncGetVersion(version);
|
||
|
m_xine_version = 0;
|
||
|
execFuncGetVersion(m_xine_version);
|
||
|
if (MIN_XINE_VDR_VERSION <= version /* && version <= MAX_XINE_VDR_VERSION */)
|
||
|
if (MIN_XINE_VDR_VERSION <= m_xine_version /* && version <= MAX_XINE_VDR_VERSION */)
|
||
|
return true;
|
||
|
xfprintf(stderr, "vdr-xine: Client reports unsupported version %d => disconnecting!\n", version);
|
||
|
xfprintf(stderr, "vdr-xine: Client reports unsupported version %d => disconnecting!\n", m_xine_version);
|
||
|
disconnect();
|
||
|
return false;
|
||
| ... | ... | |
|
#ifndef PNMTOJPEG
|
||
|
#define PNMTOJPEG "pnmtojpeg"
|
||
|
#endif
|
||
|
|
||
|
#ifndef XINE_VERSION_CODE
|
||
|
#define XINE_VERSION_CODE XINE_MAJOR_VERSION*10000+XINE_MINOR_VERSION*100+XINE_SUB_VERSION
|
||
|
#endif
|
||
|
uchar *cXineLib::execFuncGrabImage(const char *FileName, int &Size, bool Jpeg, int Quality, int SizeX, int SizeY)
|
||
|
{
|
||
|
if (!isConnected())
|
||
| ... | ... | |
|
|
||
|
DLOG("cXineLib::execFuncGrabImage");
|
||
|
cMutexLock ioLock(&m_ioMutex);
|
||
|
|
||
|
int videoX = -1;
|
||
|
int videoY = -1;
|
||
|
int videoW = -1;
|
||
|
int videoH = -1;
|
||
|
int zoomX = 100;
|
||
|
int zoomY = 100;
|
||
|
execFuncVideoSize(videoX, videoY, videoW, videoH, zoomX, zoomY);
|
||
|
|
||
|
if (!isConnected())
|
||
|
return NULL;
|
||
|
|
||
|
data_grab_image_t data;
|
||
|
data.header.func = func_grab_image;
|
||
|
data.header.len = sizeof (data);
|
||
|
if (sizeof (data) == xwrite(fd_control, &data, sizeof (data)))
|
||
|
enum funcs grab_func;
|
||
|
#if XINE_VERSION_CODE >= 10201
|
||
|
if (m_xine_version >= 905)
|
||
|
{
|
||
|
result_union_t resultUnion;
|
||
|
|
||
|
off_t n = xread(fd_result, (char *)&resultUnion, sizeof (resultUnion.header));
|
||
|
if (n != sizeof (resultUnion.header))
|
||
|
data_grab_image_v2_t data;
|
||
|
data.header.func = func_grab_image_v2;
|
||
|
data.header.len = sizeof (data);
|
||
|
data.width = SizeX;
|
||
|
data.height = SizeY;
|
||
|
data.jpeg = Jpeg;
|
||
|
data.quality = Quality;
|
||
|
if (sizeof (data) != xwrite(fd_control, &data, sizeof (data)))
|
||
|
return NULL;
|
||
|
if (data.header.func != resultUnion.header.func)
|
||
|
return NULL;
|
||
|
|
||
|
result_grab_image_t *result = &resultUnion.grab_image;
|
||
|
|
||
|
n = xread(fd_result, (char *)result + sizeof (result->header), sizeof (*result) - sizeof (result->header));
|
||
|
if (n != sizeof (*result) - sizeof (result->header))
|
||
|
grab_func = func_grab_image_v2;
|
||
|
}
|
||
|
else
|
||
|
#endif
|
||
|
{
|
||
|
data_grab_image_t data;
|
||
|
data.header.func = func_grab_image;
|
||
|
data.header.len = sizeof (data);
|
||
|
if (sizeof (data) != xwrite(fd_control, &data, sizeof (data)))
|
||
|
return NULL;
|
||
|
grab_func = func_grab_image;
|
||
|
}
|
||
|
const size_t frameSize = result->header.len - sizeof (*result);
|
||
|
result_union_t resultUnion;
|
||
|
off_t n = xread(fd_result, (char *)&resultUnion, sizeof (resultUnion.header));
|
||
|
if (n != sizeof (resultUnion.header))
|
||
|
return NULL;
|
||
|
// ::fprintf(stderr, "frameSize: %d\n", frameSize);
|
||
|
|
||
|
if (frameSize <= 0)
|
||
|
return NULL;
|
||
|
|
||
|
uint8_t *img = (uint8_t *)::malloc(frameSize);
|
||
|
if (!img)
|
||
|
return NULL;
|
||
|
|
||
|
if (frameSize != (size_t)xread(fd_result, img, frameSize))
|
||
|
if (grab_func != resultUnion.header.func)
|
||
|
return NULL;
|
||
|
result_grab_image_t *result = &resultUnion.grab_image;
|
||
|
n = xread(fd_result, (char *)result + sizeof (result->header), sizeof (*result) - sizeof (result->header));
|
||
|
if (n != sizeof (*result) - sizeof (result->header))
|
||
|
return NULL;
|
||
|
const size_t frameSize = result->header.len - sizeof (*result);
|
||
|
if (frameSize <= 0)
|
||
|
return NULL;
|
||
|
uint8_t *img = (uint8_t *)::malloc(frameSize);
|
||
|
if (!img)
|
||
|
return NULL;
|
||
|
if (frameSize != (size_t)xread(fd_result, img, frameSize))
|
||
|
{
|
||
|
::free(img);
|
||
|
return NULL;
|
||
|
}
|
||
|
if (XINE_IMGFMT_YUY2 == result->format)
|
||
|
{
|
||
|
uint8_t *img2 = (uint8_t *)::malloc(frameSize);
|
||
|
if (!img2)
|
||
|
{
|
||
|
::free(img);
|
||
|
return NULL;
|
||
|
}
|
||
|
if (XINE_IMGFMT_YUY2 == result->format)
|
||
|
::memset(img2, 0x80, frameSize);
|
||
|
uint8_t *src = img;
|
||
|
uint8_t *dstY = img2;
|
||
|
uint8_t *dstU = dstY + result->height * result->width;
|
||
|
uint8_t *dstV = dstU + result->height * ((result->width + 1) / 2);
|
||
|
for (int y = 0; y < result->height; y++)
|
||
|
{
|
||
|
uint8_t *img2 = (uint8_t *)::malloc(frameSize);
|
||
|
if (!img2)
|
||
|
for (int x = 0; x < (result->width + 1) / 2; x++)
|
||
|
{
|
||
|
::free(img);
|
||
|
return NULL;
|
||
|
*dstY++ = *src++;
|
||
|
*dstU++ = *src++;
|
||
|
*dstY++ = *src++;
|
||
|
*dstV++ = *src++;
|
||
|
}
|
||
|
}
|
||
|
::memset(img2, 0x80, frameSize);
|
||
|
|
||
|
uint8_t *src = img;
|
||
|
uint8_t *dstY = img2;
|
||
|
uint8_t *dstU = dstY + result->height * result->width;
|
||
|
uint8_t *dstV = dstU + result->height * ((result->width + 1) / 2);
|
||
|
|
||
|
for (int y = 0; y < result->height; y++)
|
||
|
{
|
||
|
for (int x = 0; x < (result->width + 1) / 2; x++)
|
||
|
{
|
||
|
*dstY++ = *src++;
|
||
|
*dstU++ = *src++;
|
||
|
*dstY++ = *src++;
|
||
|
*dstV++ = *src++;
|
||
|
}
|
||
|
}
|
||
|
::free(img);
|
||
|
img = img2;
|
||
|
}
|
||
|
else if (XINE_IMGFMT_YV12 != result->format) /* xinelib already returns complete result */
|
||
|
{
|
||
|
Size = frameSize;
|
||
|
return (uchar *)img;
|
||
|
}
|
||
|
::free(img);
|
||
|
const char *grabName;
|
||
|
char *tempName = NULL;
|
||
|
if (FileName)
|
||
|
grabName = FileName;
|
||
|
else
|
||
|
{
|
||
|
char prefix[6];
|
||
|
::snprintf(prefix, 6, "%d", (int)::getpid());
|
||
|
tempName = ::tempnam(NULL, prefix);
|
||
|
grabName = tempName;
|
||
|
}
|
||
|
img = img2;
|
||
|
}
|
||
|
int videoX = result->crop_left;
|
||
|
int videoY = result->crop_top;
|
||
|
int videoW = result->width - result->crop_left - result->crop_right;
|
||
|
int videoH = result->height - result->crop_top - result->crop_bottom;
|
||
|
FILE *tmpFile = 0;
|
||
|
int outfd = -1;
|
||
|
int iRn;
|
||
|
int iRd;
|
||
|
if (FileName)
|
||
|
{
|
||
|
outfd = ::open(FileName, O_CREAT /* | O_EXCL */ | O_TRUNC | O_RDWR, 0644);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tmpFile = ::tmpfile();
|
||
|
if (tmpFile)
|
||
|
outfd = fileno(tmpFile);
|
||
|
}
|
||
|
if (videoW > videoH)
|
||
|
{
|
||
|
iRn = videoH;
|
||
|
iRd = (videoW * 20000 + result->ratio) / (2 * result->ratio);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
iRn = (videoH * 2 * result->ratio + 10000) / 20000;
|
||
|
iRd = videoW;
|
||
|
}
|
||
|
if (-1 == outfd)
|
||
|
{
|
||
|
if (tmpFile)
|
||
|
::fclose(tmpFile); // removes file, too
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/*
|
||
|
if (-1 == videoX || -1 == videoY || videoW <= 0 || videoH <= 0)
|
||
|
{
|
||
|
videoX = 0;
|
||
|
videoY = 0;
|
||
|
videoW = result->width;
|
||
|
videoH = result->height;
|
||
|
}
|
||
|
*/
|
||
|
videoX = result->crop_left;
|
||
|
videoY = result->crop_top;
|
||
|
videoW = result->width - result->crop_left - result->crop_right;
|
||
|
videoH = result->height - result->crop_top - result->crop_bottom;
|
||
|
int oRn = SizeY * (m_noSignalStream16x9 ? 16 : 4);
|
||
|
int oRd = SizeX * (m_noSignalStream16x9 ? 9 : 3);
|
||
|
int iRn;
|
||
|
int iRd;
|
||
|
const char *const chromass = (XINE_IMGFMT_YV12 == result->format) ? "420_MPEG2" : "422";
|
||
|
char *cmd = NULL;
|
||
|
if (videoW > videoH)
|
||
|
{
|
||
|
iRn = videoH;
|
||
|
iRd = (videoW * 20000 + result->ratio) / (2 * result->ratio);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
iRn = (videoH * 2 * result->ratio + 10000) / 20000;
|
||
|
iRd = videoW;
|
||
|
}
|
||
|
if (Jpeg)
|
||
|
{
|
||
|
::asprintf(&cmd, Y4MSCALER " -v 0 -I chromass=%s -I active=%dx%d+%d+%d -O chromass=444 -O size=%dx%d -O sar=%d:%d "
|
||
|
"| " Y4MTOPPM " -v 0 -L "
|
||
|
"| " PNMTOJPEG " -quality=%d "
|
||
|
">%s"
|
||
|
, chromass, videoW, videoH, videoX, videoY, SizeX, SizeY, oRn, oRd
|
||
|
, Quality
|
||
|
, grabName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
::asprintf(&cmd, Y4MSCALER " -v 0 -I chromass=%s -I active=%dx%d+%d+%d -O chromass=444 -O size=%dx%d -O sar=%d:%d "
|
||
|
"| " Y4MTOPPM " -v 0 -L "
|
||
|
">%s"
|
||
|
, chromass, videoW, videoH, videoX, videoY, SizeX, SizeY, oRn, oRd
|
||
|
, grabName);
|
||
|
}
|
||
|
int oRn = SizeY * (m_noSignalStream16x9 ? 16 : 4);
|
||
|
int oRd = SizeX * (m_noSignalStream16x9 ? 9 : 3);
|
||
|
xfprintf(stderr, "cmd: %s\n", cmd);
|
||
|
const char *const chromass = (XINE_IMGFMT_YV12 == result->format) ? "420_MPEG2" : "422";
|
||
|
char *cmd = 0;
|
||
|
|
||
|
if (Jpeg)
|
||
|
{
|
||
|
::asprintf(&cmd, Y4MSCALER " -I chromass=%s -I active=%dx%d+%d+%d -O chromass=444 -O size=%dx%d -O sar=%d:%d "
|
||
|
"| " Y4MTOPPM " -L "
|
||
|
"| " PNMTOJPEG " -quality=%d "
|
||
|
">&%d"
|
||
|
, chromass, videoW, videoH, videoX, videoY, SizeX, SizeY, oRn, oRd
|
||
|
, Quality
|
||
|
, outfd);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
::asprintf(&cmd, Y4MSCALER " -I chromass=%s -I active=%dx%d+%d+%d -O chromass=444 -O size=%dx%d -O sar=%d:%d "
|
||
|
"| " Y4MTOPPM " -L "
|
||
|
">&%d"
|
||
|
, chromass, videoW, videoH, videoX, videoY, SizeX, SizeY, oRn, oRd
|
||
|
, outfd);
|
||
|
}
|
||
|
|
||
|
// ::fprintf(stderr, "ratio: %d\n", result->ratio);
|
||
|
xfprintf(stderr, "cmd: %s\n", cmd);
|
||
|
|
||
|
FILE *f = ::popen(cmd, "w");
|
||
|
if (f)
|
||
|
{
|
||
|
::fprintf(f, "YUV4MPEG2 W%d H%d F%d:%d I%c A%d:%d\nFRAME\n"
|
||
|
, result->width, result->height
|
||
|
, 25, 1
|
||
|
, "ptb"[result->interlaced]
|
||
|
, iRn, iRd);
|
||
|
FILE *f = ::popen(cmd, "w");
|
||
|
if (f)
|
||
|
{
|
||
|
::fprintf(f, "YUV4MPEG2 W%d H%d F%d:%d I%c A%d:%d\nFRAME\n"
|
||
|
, result->width, result->height
|
||
|
, 25, 1
|
||
|
, "ptb"[result->interlaced]
|
||
|
, iRn, iRd);
|
||
|
if (frameSize == ::fwrite(img, 1, frameSize, f))
|
||
|
{
|
||
|
::pclose(f); // close the pipe here
|
||
|
::free(img);
|
||
|
img = NULL;
|
||
|
if (frameSize == ::fwrite(img, 1, frameSize, f))
|
||
|
if (tempName) // grab the image in one go
|
||
|
{
|
||
|
int fd = ::open(tempName, O_RDONLY);
|
||
|
if (fd != -1)
|
||
|
{
|
||
|
::pclose(f); // close the pipe here
|
||
|
::free(img);
|
||
|
img = NULL;
|
||
|
Size = (int) ::lseek (fd, 0, SEEK_END);
|
||
|
::lseek (fd, 0, SEEK_SET);
|
||
|
if (tmpFile) // grab the image in one go
|
||
|
if (Size != -1)
|
||
|
{
|
||
|
Size = (int) lseek (outfd, 0, SEEK_END);
|
||
|
lseek (outfd, 0, SEEK_SET);
|
||
|
if (Size != -1)
|
||
|
img = (uint8_t *)::malloc(Size);
|
||
|
if (img && Size != ::read(fd, img, Size))
|
||
|
{
|
||
|
img = (uint8_t *)::malloc(Size);
|
||
|
if (img && Size != ::read(outfd, img, Size))
|
||
|
{
|
||
|
::free(img);
|
||
|
img = NULL;
|
||
|
}
|
||
|
::free(img);
|
||
|
img = NULL;
|
||
|
}
|
||
|
}
|
||
|
else // file is persistent so don't care about it's content
|
||
|
{
|
||
|
Size = -1;
|
||
|
img = (uint8_t *)-1;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
::pclose(f);
|
||
|
::free(img);
|
||
|
img = NULL;
|
||
|
::close(fd);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
else // file is persistent so don't care about it's content
|
||
|
{
|
||
|
::free(img);
|
||
|
img = NULL;
|
||
|
Size = -1;
|
||
|
img = (uint8_t *)-1;
|
||
|
}
|
||
|
::free(cmd);
|
||
|
if (tmpFile)
|
||
|
::fclose(tmpFile); // removes file, too
|
||
|
else
|
||
|
::close(outfd);
|
||
|
return (uchar *)img;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
::pclose(f);
|
||
|
::free(img);
|
||
|
img = NULL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
::free(img);
|
||
|
img = NULL;
|
||
|
}
|
||
|
::free(cmd);
|
||
|
if (tempName)
|
||
|
{
|
||
|
::unlink(tempName);
|
||
|
::free(tempName);
|
||
|
}
|
||
|
return NULL;
|
||
|
return (uchar *)img;
|
||
|
}
|
||
|
|
||
|
bool cXineLib::execFuncGetVersion(int32_t &version)
|
||
| xineLib.h | ||
|---|---|---|
|
cMutex m_shutdownMutex;
|
||
|
cCondVar m_shutdownCondVar;
|
||
|
|
||
|
int32_t m_xine_version;
|
||
|
const cXineSettings &m_settings;
|
||
|
bool osdUpdateLocked(const char *const funcName);
|
||