diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | e2de64d6f1beb9e492daf5b886e19933c1fa41dd (patch) | |
tree | 9047cf9e6b5c43878d5bf82660adae77ceee097a /xine_artsplugin/tools | |
download | tdemultimedia-e2de64d6f1beb9e492daf5b886e19933c1fa41dd.tar.gz tdemultimedia-e2de64d6f1beb9e492daf5b886e19933c1fa41dd.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdemultimedia@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'xine_artsplugin/tools')
-rw-r--r-- | xine_artsplugin/tools/Makefile.am | 1 | ||||
-rw-r--r-- | xine_artsplugin/tools/thumbnail/Makefile.am | 24 | ||||
-rw-r--r-- | xine_artsplugin/tools/thumbnail/sprocket-large.png | bin | 0 -> 1033 bytes | |||
-rw-r--r-- | xine_artsplugin/tools/thumbnail/sprocket-medium.png | bin | 0 -> 649 bytes | |||
-rw-r--r-- | xine_artsplugin/tools/thumbnail/sprocket-small.png | bin | 0 -> 357 bytes | |||
-rw-r--r-- | xine_artsplugin/tools/thumbnail/videocreator.cpp | 376 | ||||
-rw-r--r-- | xine_artsplugin/tools/thumbnail/videocreator.h | 40 | ||||
-rw-r--r-- | xine_artsplugin/tools/thumbnail/videoscaler.cpp | 258 | ||||
-rw-r--r-- | xine_artsplugin/tools/thumbnail/videoscaler.h | 24 | ||||
-rw-r--r-- | xine_artsplugin/tools/thumbnail/videothumbnail.desktop | 71 |
10 files changed, 794 insertions, 0 deletions
diff --git a/xine_artsplugin/tools/Makefile.am b/xine_artsplugin/tools/Makefile.am new file mode 100644 index 00000000..1ed9efda --- /dev/null +++ b/xine_artsplugin/tools/Makefile.am @@ -0,0 +1 @@ +SUBDIRS=thumbnail diff --git a/xine_artsplugin/tools/thumbnail/Makefile.am b/xine_artsplugin/tools/thumbnail/Makefile.am new file mode 100644 index 00000000..40358fda --- /dev/null +++ b/xine_artsplugin/tools/thumbnail/Makefile.am @@ -0,0 +1,24 @@ +## $Id$ +## Makefile.am of kdemultimedia/tools/thumbnail + +INCLUDES = -I$(kde_includes)/arts $(all_includes) $(XINE_CFLAGS) + +AM_CFLAGS = -U__STRICT_ANSI__ + +METASOURCES = AUTO + +kde_module_LTLIBRARIES = videothumbnail.la + +videothumbnail_la_SOURCES = videocreator.cpp videoscaler.cpp +videothumbnail_la_LIBADD = $(XINE_LIBS) $(LIB_KDECORE) +videothumbnail_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) -pthread + +noinst_HEADERS = videocreator.h + +xineartsplugin_tools_videothumbnail_DATA = sprocket-small.png sprocket-medium.png sprocket-large.png + +xineartsplugin_tools_videothumbnaildir = $(kde_datadir)/videothumbnail + +services_DATA = videothumbnail.desktop + +servicesdir = $(kde_servicesdir) diff --git a/xine_artsplugin/tools/thumbnail/sprocket-large.png b/xine_artsplugin/tools/thumbnail/sprocket-large.png Binary files differnew file mode 100644 index 00000000..6c0e65a9 --- /dev/null +++ b/xine_artsplugin/tools/thumbnail/sprocket-large.png diff --git a/xine_artsplugin/tools/thumbnail/sprocket-medium.png b/xine_artsplugin/tools/thumbnail/sprocket-medium.png Binary files differnew file mode 100644 index 00000000..8868e660 --- /dev/null +++ b/xine_artsplugin/tools/thumbnail/sprocket-medium.png diff --git a/xine_artsplugin/tools/thumbnail/sprocket-small.png b/xine_artsplugin/tools/thumbnail/sprocket-small.png Binary files differnew file mode 100644 index 00000000..62fa3fd7 --- /dev/null +++ b/xine_artsplugin/tools/thumbnail/sprocket-small.png diff --git a/xine_artsplugin/tools/thumbnail/videocreator.cpp b/xine_artsplugin/tools/thumbnail/videocreator.cpp new file mode 100644 index 00000000..94e87b48 --- /dev/null +++ b/xine_artsplugin/tools/thumbnail/videocreator.cpp @@ -0,0 +1,376 @@ +/* This file is part of the KDE libraries + Copyright (C) 2002 Simon MacMullen + Copyright (C) 2003 Ewald Snel <ewald@rambo.its.tudelft.nl> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +// $Id$ + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <pthread.h> +#include <sys/time.h> + +#include <qpixmap.h> +#include <qdialog.h> +#include <qfile.h> +#include <qimage.h> +#include <qpainter.h> +#include <qpaintdevice.h> + +#include <iostream> + +#include <kstandarddirs.h> +#include <kapplication.h> + +#define XINE_ENABLE_EXPERIMENTAL_FEATURES 1 + +#include <xine.h> + +#include "videocreator.h" +#include "videoscaler.h" + +#define TIMEOUT 15 // 15 seconds +#define MAX_ATTEMPTS 25 + + +// Global xine pointer +static xine_t *xine_shared = NULL; +static pthread_mutex_t xine_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t xine_cond = PTHREAD_COND_INITIALIZER; +static int xineRefCount = 0; + +static void xine_init_routine() +{ + char cfgFileName[272]; + + xine_shared = (xine_t *)xine_new(); + + snprintf( cfgFileName, 272, "%s/.xine/config", getenv( "HOME" ) ); + + xine_config_load( xine_shared, (const char *)cfgFileName ); + + xine_init( xine_shared ); +} + +static void *xine_timeout_routine( void * ) +{ + pthread_mutex_lock( &xine_mutex ); + + while (xine_shared != 0) + { + if (xineRefCount == 0) + { + struct timespec ts; + struct timeval tv; + + gettimeofday( &tv, 0 ); + + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; + ts.tv_sec += TIMEOUT; + + if (pthread_cond_timedwait( &xine_cond, &xine_mutex, &ts ) != 0 && + xineRefCount == 0) + { + xine_exit( xine_shared ); + xine_shared = NULL; + break; + } + } + else + { + pthread_cond_wait( &xine_cond, &xine_mutex ); + } + } + pthread_mutex_unlock( &xine_mutex ); + + return NULL; +} + +static xine_t *xine_shared_init() +{ + pthread_mutex_lock( &xine_mutex ); + + ++xineRefCount; + + if (xine_shared == 0) + { + pthread_t thread; + + xine_init_routine(); + + if (pthread_create( &thread, NULL, xine_timeout_routine, NULL ) == 0) + { + pthread_detach( thread ); + } + } + else + { + pthread_cond_signal( &xine_cond ); + } + pthread_mutex_unlock( &xine_mutex ); + + return xine_shared; +} + +static void xine_shared_exit( xine_t * ) +{ + pthread_mutex_lock( &xine_mutex ); + + if (--xineRefCount == 0) + { + pthread_cond_signal( &xine_cond ); + } + pthread_mutex_unlock( &xine_mutex ); +} + +static QImage createThumbnail( xine_video_frame_t *frame, int width, int height ) +{ + unsigned char *base[3]; + unsigned int pitches[3]; + + if ((frame->aspect_ratio * height) > width) + height = (int)(.5 + (width / frame->aspect_ratio)); + else + width = (int)(.5 + (height * frame->aspect_ratio)); + + QImage image( width, height, 32 ); + + if (frame->colorspace == XINE_IMGFMT_YV12) + { + int y_size, uv_size; + + pitches[0] = (frame->width + 7) & ~0x7; + pitches[1] = (((frame->width + 1) / 2) + 7) & ~0x7; + pitches[2] = pitches[1]; + + y_size = pitches[0] * frame->height; + uv_size = pitches[1] * ((frame->height + 1) / 2); + + base[0] = frame->data; + base[1] = base[0] + y_size + uv_size; + base[2] = base[0] + y_size; + + scaleYuvToRgb32( frame->width, frame->height, base, pitches, + width, height, (unsigned int *)image.bits(), + image.bytesPerLine() ); + } + else if (frame->colorspace == XINE_IMGFMT_YUY2) + { + pitches[0] = 2*((frame->width + 3) & ~0x3); + base[0] = frame->data; + + scaleYuy2ToRgb32( frame->width, frame->height, base[0], pitches[0], + width, height, (unsigned int *)image.bits(), + image.bytesPerLine() ); + } + return image; +} + +// Return the variance of the brightness of the pixels +static double imageVariance( unsigned char *pixels, int pitch, + int width, int height, int step ) +{ + double sigmaX = 0; + double sigmaXSquared = 0; + + for (int y=0; y < height ; y++) + { + unsigned int uSigmaX = 0; + unsigned int uSigmaXSquared = 0; + + for (int x=0, n=(width * step); x < n ; x+=step) + { + int gray = pixels[x]; + + uSigmaX += gray; + uSigmaXSquared += gray * gray; + } + + sigmaX += uSigmaX; + sigmaXSquared += uSigmaXSquared; + + pixels += pitch; + } + + unsigned int total = height * width; + + return sqrt( sigmaXSquared / total - (sigmaX / total) * (sigmaX / total) ); +} + +static bool findBestFrame( xine_video_port_t *vo_port, xine_video_frame_t *frame ) +{ + xine_video_frame_t frames[2], *bestFrame = NULL; + double variance, bestVariance = 0; + + for (int i=0, n=0; i < MAX_ATTEMPTS; i++) + { + xine_video_frame_t *cFrame = &frames[n]; + + // Try to read next frame + if (!xine_get_next_video_frame( vo_port, cFrame )) + { + break; + } + + variance = imageVariance( cFrame->data, ((cFrame->width + 7) & ~0x7), + cFrame->width, cFrame->height, + (cFrame->colorspace == XINE_IMGFMT_YV12) ? 1 : 2 ); + + // Compare current frame to best frame + if (bestFrame == NULL || variance > bestVariance) + { + if (bestFrame != NULL) + { + xine_free_video_frame( vo_port, bestFrame ); + } + + bestFrame = cFrame; + bestVariance = variance; + + n = (1 - n); + } + else + { + xine_free_video_frame( vo_port, cFrame ); + } + + // Stop searching if current frame is interesting enough + if (variance > 40.0) + { + break; + } + } + + // This should be the best frame to create a thumbnail from + if (bestFrame != NULL) + { + *frame = *bestFrame; + } + return (bestFrame != NULL); +} + + +extern "C" +{ + ThumbCreator *new_creator() + { + return new VideoCreator; + } +} + +VideoCreator::VideoCreator() +{ +} + +VideoCreator::~VideoCreator() +{ +} + +bool VideoCreator::create(const QString &path, int width, int height, QImage &img) +{ + if (m_sprocketSmall.isNull()) + { + QString pixmap = locate( "data", "videothumbnail/sprocket-small.png" ); + m_sprocketSmall = QPixmap(pixmap); + pixmap = locate( "data", "videothumbnail/sprocket-medium.png" ); + m_sprocketMedium = QPixmap(pixmap); + pixmap = locate( "data", "videothumbnail/sprocket-large.png" ); + m_sprocketLarge = QPixmap(pixmap); + } + + // The long term plan is to seek to frame 1, create thumbnail, see if is is + // interesting enough, if not seek to frame 2, then 4, then 8, etc. + // "Interesting enough" means the variance of the pixel brightness is high. This + // is because many videos fade up from black and a black rectangle is boring. + // + // But for the time being we can't seek so we just let it play for one second + // then take whatever we find. + + xine_t *xine = xine_shared_init(); + xine_audio_port_t *ao_port = xine_new_framegrab_audio_port( xine ); + xine_video_port_t *vo_port = xine_new_framegrab_video_port( xine ); + xine_stream_t *stream = xine_stream_new( xine, ao_port, vo_port ); + bool success = false; + + if (xine_open( stream, QFile::encodeName ( path ).data() )) + { + xine_video_frame_t frame; + int length; + + // Find 'best' (or at least any) frame + if (!xine_get_pos_length( stream, NULL, NULL, &length ) || length > 5000) + { + if (xine_play( stream, 0, 4000 )) + { + success = findBestFrame( vo_port, &frame ); + } + } + if (!success) + { + // Some codecs can't seek to start, but close/open works + xine_close( stream ); + xine_open( stream, path.ascii() ); + + if (xine_play( stream, 0, 0 )) + { + success = findBestFrame( vo_port, &frame ); + } + } + + // Create thumbnail image + if (success) + { + QPixmap pix( createThumbnail( &frame, width, height ) ); + QPainter painter( &pix ); + QPixmap sprocket; + + if (pix.height() < 60) + sprocket = m_sprocketSmall; + else if (pix.height() < 90) + sprocket = m_sprocketMedium; + else + sprocket = m_sprocketLarge; + + for (int y = 0; y < pix.height() + sprocket.height(); y += sprocket.height()) { + painter.drawPixmap( 0, y, sprocket ); + } + + img = pix.convertToImage(); + + xine_free_video_frame( vo_port, &frame ); + } + + xine_stop( stream ); + } + + xine_dispose( stream ); + xine_close_audio_driver( xine, ao_port ); + xine_close_video_driver( xine, vo_port ); + xine_shared_exit( xine ); + + return (success); +} + +ThumbCreator::Flags VideoCreator::flags() const +{ + return (ThumbCreator::Flags) (DrawFrame); +} + +#include "videocreator.moc" diff --git a/xine_artsplugin/tools/thumbnail/videocreator.h b/xine_artsplugin/tools/thumbnail/videocreator.h new file mode 100644 index 00000000..bd16e6e2 --- /dev/null +++ b/xine_artsplugin/tools/thumbnail/videocreator.h @@ -0,0 +1,40 @@ +/* This file is part of the KDE libraries + Copyright (C) 2002 Simon MacMullen + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef _VIDEOCREATOR_H_ +#define _VIDEOCREATOR_H_ "$Id$" + +#include <kio/thumbcreator.h> + +class VideoCreator : public QObject, public ThumbCreator +{ + Q_OBJECT +public: + VideoCreator(); + virtual ~VideoCreator(); + virtual bool create(const QString &path, int width, int height, QImage &img); + virtual Flags flags() const; + +private: + QPixmap m_sprocketSmall; + QPixmap m_sprocketMedium; + QPixmap m_sprocketLarge; +}; + +#endif diff --git a/xine_artsplugin/tools/thumbnail/videoscaler.cpp b/xine_artsplugin/tools/thumbnail/videoscaler.cpp new file mode 100644 index 00000000..2b4b49ad --- /dev/null +++ b/xine_artsplugin/tools/thumbnail/videoscaler.cpp @@ -0,0 +1,258 @@ +/* + This file is part of KDE/aRts - xine integration + Copyright (C) 2003 Ewald Snel <ewald@rambo.its.tudelft.nl> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + inspired by code from the xine project + + Copyright (C) 2003 the xine project +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <pthread.h> + +#include <config.h> + +#ifdef HAVE_ALLOCA_H +#include <alloca.h> +#endif + +#include "videoscaler.h" + +#define THUMBNAIL_BRIGHTNESS +32 +#define THUMBNAIL_CONTRAST 128 +#define THUMBNAIL_SATURATION 128 + + +// Colorspace conversion tables +static int tableLY[256]; +static int tableRV[256], tableBU[256], tableGU[256], tableGV[256]; +static int clipR[2240], clipG[2240], clipB[2240]; + +static pthread_once_t once_control = PTHREAD_ONCE_INIT; + + +static void init_once_routine() +{ + int cly = ( 76309 * THUMBNAIL_CONTRAST + 64) / 128; + int crv = (104597 * THUMBNAIL_SATURATION + 64) / 128; + int cbu = (132201 * THUMBNAIL_SATURATION + 64) / 128; + int cgu = ( 25675 * THUMBNAIL_SATURATION + 64) / 128; + int cgv = ( 53279 * THUMBNAIL_SATURATION + 64) / 128; + int i; + + for (i=0; i < 256; i++) + { + tableLY[i] = cly * (i + THUMBNAIL_BRIGHTNESS - 16) + (864 << 16) + 32768; + tableRV[i] = crv * (i - 128); + tableBU[i] = cbu * (i - 128); + tableGU[i] = cgu * (i - 128); + tableGV[i] = cgv * (i - 128); + } + for (i=0; i < 2240; i++) + { + int c = (i < 864) ? 0 : ((i > 1119) ? 255 : (i - 864)); + + clipR[i] = c << 16; + clipG[i] = c << 8; + clipB[i] = c; + } +} + +static void yuvToRgb32( unsigned char *bufy, unsigned char *bufu, unsigned char *bufv, + unsigned int *pixels, int width ) +{ + for (int i=0; i < width; i++) + { + int l = tableLY[bufy[i]]; + + pixels[i] = clipR[(l + tableRV[bufv[i]]) >> 16] | + clipG[(l - tableGU[bufu[i]] - tableGV[bufv[i]]) >> 16] | + clipB[(l + tableBU[bufu[i]]) >> 16]; + } +} + +static inline void scaleLine( unsigned char *src[2], int width, + unsigned char *dst, int scaledWidth, + int scale, int weight, int step, int offset ) +{ + int a, b, c, d; + int x = (scale / 2) - 32768; + unsigned char *p0 = (src[0] + offset); + unsigned char *p1 = (src[1] + offset); + + weight >>= 8; + + if (scaledWidth > width) + { + /* Trailing pixels, no horizontal filtering */ + c = scaledWidth - (((width << 16) - 32768 - (scale / 2)) / scale); + a = p0[(step * width) - step]; + b = p1[(step * width) - step]; + a += (128 + (b - a) * weight) >> 8; + scaledWidth -= c; + memset( &dst[scaledWidth], a, c ); + + /* Leading pixels, no horizontal filtering */ + c = (32767 + (scale / 2)) / scale; + a = p0[0]; + b = p1[0]; + a += (128 + (b - a) * weight) >> 8; + scaledWidth -= c; + memset( dst, a, c ); + + /* Adjust source and destination */ + dst += c; + x += (c * scale); + } + + for (int i=0; i < scaledWidth; i++) + { + int xhi = (step == 1) ? (x >> 16) + : ((step == 2) ? (x >> 15) & ~0x1 + : (x >> 14) & ~0x3); + int xlo = (x & 0xFFFF) >> 8; + + /* Four nearest points for bilinear filtering */ + a = p0[xhi]; + b = p0[xhi + step]; + c = p1[xhi];\ + d = p1[xhi + step]; + + /* Interpolate horizontally */ + a = (256 * a) + (b - a) * xlo; + c = (256 * c) + (d - c) * xlo; + + /* Interpolate vertically and store bilinear filtered sample */ + *(dst++) = ((256 * a) + (c - a) * weight + 32768) >> 16; + + x += scale; + } +} + +void scaleYuvToRgb32( int width, int height, + unsigned char *base[3], unsigned int pitches[3], + int scaledWidth, int scaledHeight, + unsigned int *pixels, unsigned int bytesPerLine ) +{ + int chromaWidth = (width + 1) / 2; + int chromaHeight = (height + 1) / 2; + int scaleX = (width << 16) / scaledWidth; + int scaleY = (height << 16) / scaledHeight; + int scaleCX = (scaleX / 2); + int y = (scaleY / 2) - 32768; + + // Temporary line buffers (stack) + unsigned char *bufy = (unsigned char *)alloca( scaledWidth ); + unsigned char *bufu = (unsigned char *)alloca( scaledWidth ); + unsigned char *bufv = (unsigned char *)alloca( scaledWidth ); + + pthread_once( &once_control, init_once_routine ); + + for (int i=0; i < scaledHeight; i++) + { + unsigned char *twoy[2], *twou[2], *twov[2]; + int y2 = (y / 2) - 32768; + + // Calculate luminance scanlines for bilinear filtered scaling + if (y < 0) + { + twoy[0] = twoy[1] = base[0]; + } + else if (y >= ((height - 1) << 16)) + { + twoy[0] = twoy[1] = base[0] + (height - 1) * pitches[0]; + } + else + { + twoy[0] = base[0] + (y >> 16) * pitches[0]; + twoy[1] = twoy[0] + pitches[0]; + } + + // Calculate chrominance scanlines for bilinear filtered scaling + if (y2 < 0) + { + twou[0] = twou[1] = base[1]; + twov[0] = twov[1] = base[2]; + } + else if (y2 >= ((chromaHeight - 1) << 16)) + { + twou[0] = twou[1] = base[1] + (chromaHeight - 1) * pitches[1]; + twov[0] = twov[1] = base[2] + (chromaHeight - 1) * pitches[2]; + } + else + { + twou[0] = base[1] + (y2 >> 16) * pitches[1]; + twov[0] = base[2] + (y2 >> 16) * pitches[2]; + twou[1] = twou[0] + pitches[1]; + twov[1] = twov[0] + pitches[2]; + } + + // Bilinear filtered scaling + scaleLine( twoy, width, bufy, scaledWidth, scaleX, (y & 0xFFFF), 1, 0 ); + scaleLine( twou, chromaWidth, bufu, scaledWidth, scaleCX, (y2 & 0xFFFF), 1, 0 ); + scaleLine( twov, chromaWidth, bufv, scaledWidth, scaleCX, (y2 & 0xFFFF), 1, 0 ); + + // YUV to RGB32 comnversion + yuvToRgb32( bufy, bufu, bufv, pixels, scaledWidth ); + + pixels = (unsigned int *)(((char *)pixels) + bytesPerLine); + y += scaleY; + } +} + +void scaleYuy2ToRgb32( int width, int height, + unsigned char *base, unsigned int pitch, + int scaledWidth, int scaledHeight, + unsigned int *pixels, unsigned int bytesPerLine ) +{ + int chromaWidth = (width + 1) / 2; + int scaleX = (width << 16) / scaledWidth; + int scaleY = (height << 16) / scaledHeight; + int scaleCX = (scaleX / 2); + int y = (scaleY / 2) - 32768; + + // Temporary line buffers (stack) + unsigned char *bufy = (unsigned char *)alloca( scaledWidth ); + unsigned char *bufu = (unsigned char *)alloca( scaledWidth ); + unsigned char *bufv = (unsigned char *)alloca( scaledWidth ); + + pthread_once( &once_control, init_once_routine ); + + for (int i=0; i < scaledHeight; i++) + { + unsigned char *two[2]; + + // Calculate scanlines for bilinear filtered scaling + if (y < 0) + { + two[0] = two[1] = base; + } + else if (y >= ((height - 1) << 16)) + { + two[0] = two[1] = base + (height - 1) * pitch; + } + else + { + two[0] = base + (y >> 16) * pitch; + two[1] = two[0] + pitch; + } + + // Bilinear filtered scaling + scaleLine( two, width, bufy, scaledWidth, scaleX, (y & 0xFFFF), 2, 0 ); + scaleLine( two, chromaWidth, bufu, scaledWidth, scaleCX, (y & 0xFFFF), 4, 1 ); + scaleLine( two, chromaWidth, bufv, scaledWidth, scaleCX, (y & 0xFFFF), 4, 3 ); + + // YUV to RGB32 comnversion + yuvToRgb32( bufy, bufu, bufv, pixels, scaledWidth ); + + pixels = (unsigned int *)(((char *)pixels) + bytesPerLine); + y += scaleY; + } +} diff --git a/xine_artsplugin/tools/thumbnail/videoscaler.h b/xine_artsplugin/tools/thumbnail/videoscaler.h new file mode 100644 index 00000000..fd4d51db --- /dev/null +++ b/xine_artsplugin/tools/thumbnail/videoscaler.h @@ -0,0 +1,24 @@ +/* + This file is part of KDE/aRts - xine integration + Copyright (C) 2003 Ewald Snel <ewald@rambo.its.tudelft.nl> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +#ifndef __VIDEOSCALER_H +#define __VIDEOSCALER_H + +void scaleYuvToRgb32( int width, int height, + unsigned char *base[3], unsigned int pitches[3], + int scaledWidth, int scaledHeight, + unsigned int *pixels, unsigned int bytesPerLine ); + +void scaleYuy2ToRgb32( int width, int height, + unsigned char *base, unsigned int pitch, + int scaledWidth, int scaledHeight, + unsigned int *pixels, unsigned int bytesPerLine ); + +#endif diff --git a/xine_artsplugin/tools/thumbnail/videothumbnail.desktop b/xine_artsplugin/tools/thumbnail/videothumbnail.desktop new file mode 100644 index 00000000..e437b2a3 --- /dev/null +++ b/xine_artsplugin/tools/thumbnail/videothumbnail.desktop @@ -0,0 +1,71 @@ +[Desktop Entry] +Type=Service +Name=Video Files +Name[af]=Video Lêers +Name[ar]=ملفات مرئيات +Name[bg]=Видео файлове +Name[bn]=ভিডিও ফাইল +Name[br]=Restroù Video +Name[bs]=Video datoteke +Name[ca]=Fitxers de vídeo +Name[cs]=Video soubory +Name[cy]=Ffeiliau Fideo +Name[da]=Videofiler +Name[de]=Video-Dateien +Name[el]=Αρχεία βίντεο +Name[eo]=Vidaj dosieroj +Name[es]=Archivos de vídeo +Name[et]=Videofailid +Name[eu]=Bideo fitxategiak +Name[fa]=پروندههای ویدیویی +Name[fi]=Videotiedostot +Name[fr]=Fichiers vidéo +Name[ga]=Comhaid Fhíse +Name[gl]=Ficheiros de Video +Name[he]=קבצי וידאו +Name[hi]=वीडियो फ़ाइलें +Name[hr]=Video datoteke +Name[hu]=Videófájlok +Name[is]=Kvikmyndaskrár +Name[it]=File Video +Name[ja]=ビデオファイル +Name[kk]=Бейне файлдар +Name[km]=ឯកសារវីដេអូ +Name[ko]=비디오 파일 +Name[lt]=Video bylos +Name[mk]=Видео датотеки +Name[nb]=Videofiler +Name[nds]=Videodateien +Name[ne]=भिडियो फाइल +Name[nl]=Videobestanden +Name[nn]=Videofiler +Name[pa]=ਵੀਡਿਓ ਫਾਇਲਾਂ +Name[pl]=Pliki wideo +Name[pt]=Ficheiros de Vídeo +Name[pt_BR]=Arquivos de vídeo +Name[ro]=Fişiere video +Name[ru]=Видеофайлы +Name[sk]=Video súbory +Name[sl]=Video datoteke +Name[sr]=Видео фајлови +Name[sr@Latn]=Video fajlovi +Name[sv]=Videofiler +Name[ta]=படக்காட்சி கோப்புகள் +Name[tg]=Файлҳои Видео +Name[th]=แฟ้มวิดีโอ +Name[tr]=Video Dosyaları +Name[uk]=Відеофайли +Name[uz]=Video fayllar +Name[uz@cyrillic]=Видео файллар +Name[ven]=Dzifaela dza Video +Name[wa]=Fitchîs videyo +Name[xh]=Iifayile ze Video +Name[zh_CN]=视频文件 +Name[zh_HK]=視訊檔案 +Name[zh_TW]=視訊檔案 +Name[zu]=Amafayela Evidiyo +ServiceTypes=ThumbCreator +MimeTypes=video/*,application/vnd.ms-asf,application/vnd.rn-realmedia +X-KDE-Library=videothumbnail +CacheThumbnail=true +IgnoreMaximumSize=true |