diff --git a/retroshare-gui/src/util/filefunctions.cpp b/retroshare-gui/src/util/filefunctions.cpp deleted file mode 100644 index f309ccb20..000000000 --- a/retroshare-gui/src/util/filefunctions.cpp +++ /dev/null @@ -1,373 +0,0 @@ -/**************************************************************** - * This file is distributed under the following license: - * - * Copyright (c) 2006 Raul E. - * Copyright (c) 2010 Christopher Evi-Parker - * - * 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. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - *************************************************************************/ - - -#include "filefunctions.h" - -QString filefunctions::cfilename=NULL; -QTreeWidget *filefunctions::treeObj=NULL; -QStringList filefunctions::tempimages; -QString filefunctions::codec=NULL; -int filefunctions::length=0; -int filefunctions::fwidth=0; -int filefunctions::fheight=0; - -filefunctions::filefunctions(){ - -// clear tempfiles -for ( int i=0; isave(&buffer, "PNG"); -} -bool filefunctions::saveimage(const QByteArray &ba , const QString &filename){ -bool correct=true; -QFile image(filename); -if(!image.open(QIODevice::WriteOnly) ) -return false; - -if(image.write(ba)==-1) -correct=false; - -image.close(); -return correct; -} -void filefunctions::getFramesTime(){ -xine_play(stream,0,0); -codec=xine_get_meta_info(stream, XINE_META_INFO_VIDEOCODEC); - -const uint32_t chunk= (30) * 1000; // mseconds - - -// Progress Dialog -QString progresdialogtext =QApplication::translate("xine","Generating Thumbnails...",0,QApplication::UnicodeUTF8); -QString cancelbuttontext=QApplication::translate("xine","&Cancel",0,QApplication::UnicodeUTF8); - -progress = new QProgressDialog(progresdialogtext , cancelbuttontext , 0, length,0,Qt::WindowSystemMenuHint); - - -for (int32_t frame=chunk ; framesetValue(frame); -qApp->processEvents(); -if(progress->wasCanceled()) - break; -} -progress->setValue(length); -delete progress; -} -void filefunctions::getFrames(){ -xine_play(stream,0,0); -codec=xine_get_meta_info(stream, XINE_META_INFO_VIDEOCODEC); - -int frame = 20; - -xine_play(stream,0,frame); // 1 frame 2 mseconds -SaveFrame(frame); - -} - -void filefunctions::yuy2Toyv12 (uint8_t *y, uint8_t *u, uint8_t *v, uint8_t *input, int width, int height){ - - int i, j, w2; - - w2 = width / 2; - - for (i = 0; i < height; i += 2){ - for (j = 0; j < w2; j++){ - /* - * packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] - */ - *(y++) = *(input++); - *(u++) = *(input++); - *(y++) = *(input++); - *(v++) = *(input++); - } - - /* - * down sampling - */ - - for (j = 0; j < w2; j++){ - /* - * skip every second line for U and V - */ - *(y++) = *(input++); - input++; - *(y++) = *(input++); - input++; - } - } -} -uchar * filefunctions::yv12ToRgb (uint8_t *src_y, uint8_t *src_u, uint8_t *src_v, int width, int height){ - /* - * Create rgb data from yv12 - */ - -#define clip_8_bit(val) \ -{ \ - if (val < 0) \ - val = 0; \ - else \ - if (val > 255) val = 255; \ -} - - int i, j; - - int y, u, v; - int r, g, b; - - int sub_i_uv; - int sub_j_uv; - - int uv_width, uv_height; - - uchar *rgb; - - uv_width = width / 2; - uv_height = height / 2; - - rgb = new uchar[(width * height * 4)]; //qt needs a 32bit align - if (!rgb) //qDebug ("Not enough memory!"); - return NULL; - - - for (i = 0; i < height; ++i){ - /* - * calculate u & v rows - */ - sub_i_uv = ((i * uv_height) / height); - - for (j = 0; j < width; ++j){ - /* - * calculate u & v columns - */ - sub_j_uv = ((j * uv_width) / width); - - /*************************************************** - * - * Colour conversion from - * http://www.inforamp.net/~poynton/notes/colour_and_gamma/ColorFAQ.html#RTFToC30 - * - * Thanks to Billy Biggs - * for the pointer and the following conversion. - * - * R' = [ 1.1644 0 1.5960 ] ([ Y' ] [ 16 ]) - * G' = [ 1.1644 -0.3918 -0.8130 ] * ([ Cb ] - [ 128 ]) - * B' = [ 1.1644 2.0172 0 ] ([ Cr ] [ 128 ]) - * - * Where in xine the above values are represented as - * - * Y' == image->y - * Cb == image->u - * Cr == image->v - * - ***************************************************/ - - y = src_y[(i * width) + j] - 16; - u = src_u[(sub_i_uv * uv_width) + sub_j_uv] - 128; - v = src_v[(sub_i_uv * uv_width) + sub_j_uv] - 128; - - r = (int)((1.1644 * (double)y) + (1.5960 * (double)v)); - g = (int)((1.1644 * (double)y) - (0.3918 * (double)u) - (0.8130 * (double)v)); - b = (int)((1.1644 * (double)y) + (2.0172 * (double)u)); - - clip_8_bit (r); - clip_8_bit (g); - clip_8_bit (b); - - rgb[(i * width + j) * 4 + 0] = b; - rgb[(i * width + j) * 4 + 1] = g; - rgb[(i * width + j) * 4 + 2] = r; - rgb[(i * width + j) * 4 + 3] = 0; - - } - } - - return rgb; -} -void filefunctions::SaveFrame(int pos){ - - uint8_t *yuv = NULL, *y = NULL, *u = NULL, *v =NULL ; - - int width, height, ratio, format; - - // double desired_ratio, image_ratio; - - if (!xine_get_current_frame(stream, &width, &height, &ratio, &format, NULL)) - return; - - yuv = new uint8_t[((width+8) * (height+1) * 2)]; - if (yuv == NULL){ - qWarning("Not enough memory to make screenshot!"); - return; - } - - xine_get_current_frame(stream, &width, &height, &ratio, &format, yuv); - fwidth=width; - fheight=height; - - /* - * convert to yv12 if necessary - */ - switch (format){ - case XINE_IMGFMT_YUY2: - { - uint8_t *yuy2 = yuv; - - yuv = new uint8_t[(width * height * 2)]; - if (yuv == NULL){ - qWarning("Not enough memory to make screenshot!"); - return; - } - y = yuv; - u = yuv + width * height; - v = yuv + width * height * 5 / 4; - - yuy2Toyv12 (y, u, v, yuy2, width, height); - - delete [] yuy2; - //free (yuy2); - } - break; - case XINE_IMGFMT_YV12: - y = yuv; - u = yuv + width * height; - v = yuv + width * height * 5 / 4; - - break; - default: - { - qWarning("Screenshot: Format %s not supported!",(char *) &format); - delete [] yuv; - return; - } -} -uchar* rgb32BitData = yv12ToRgb (y, u, v, width, height); -delete [] yuv; -saveRGBImage(rgb32BitData,pos,width,height); -} -QTime filefunctions::postime(const int itime){ - QTime time(0,0,0); - time=time.addMSecs(itime); - return time; -} -QString filefunctions::getXineError(int errorCode){ -QString error; -switch (errorCode){ - case XINE_ERROR_NO_INPUT_PLUGIN: - case XINE_ERROR_NO_DEMUX_PLUGIN: { - error = QApplication::translate("xine","No plugin found to handle this resource",0,QApplication::UnicodeUTF8); - break; - } - case XINE_ERROR_DEMUX_FAILED: { - error = QApplication::translate("xine","Resource seems to be broken",0,QApplication::UnicodeUTF8); - break; - } - case XINE_ERROR_MALFORMED_MRL: { - error = QApplication::translate("xine","Requested resource does not exist",0,QApplication::UnicodeUTF8); - break; - } - case XINE_ERROR_INPUT_FAILED: { - error = QApplication::translate("xine","Resource can not be opened",0,QApplication::UnicodeUTF8); - break; - } - default: { - error = QApplication::translate("xine","Unknown error",0,QApplication::UnicodeUTF8); - break; - } - } -return error; -} diff --git a/retroshare-gui/src/util/filefunctions.h b/retroshare-gui/src/util/filefunctions.h deleted file mode 100644 index 9b97dce08..000000000 --- a/retroshare-gui/src/util/filefunctions.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef FILEFUNCTIONS_H -#define FILEFUNCTIONS_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -class filefunctions{ - -private: -xine_t *xine; -xine_stream_t *stream; -xine_video_port_t *vo_port; -xine_audio_port_t *ao_port; -xine_event_queue_t *event_queue; -char *vo_driver; -char *ao_driver; - -QString tempdir; - -static QString codec; -static int length; // length of the stream -static int fwidth; -static int fheight; -void saveRGBImage(uchar *,int,int,int); -QString getXineError(int); -QProgressDialog *progress; -void savebuffer(QByteArray &, QImage *); -bool saveimage(const QByteArray & , const QString &); - -public: -filefunctions(); -~filefunctions(); -static QString cfilename; -static QTreeWidget *treeObj; -static QStringList tempimages; -QImage* currImage; - -static QString getCodec(); -static QString getImageWidth(); -static QString getImageHeight(); -static int getLength(); - -void open(); -void getFrames(); -void getFramesTime(); - -void yuy2Toyv12 (uint8_t *, uint8_t *, uint8_t *, uint8_t *, int , int ); -uchar * yv12ToRgb (uint8_t *, uint8_t *, uint8_t *, int , int ); -void SaveFrame(int); -QTime postime(const int); - -}; -#endif diff --git a/retroshare-gui/src/util/framecatcher.cpp b/retroshare-gui/src/util/framecatcher.cpp new file mode 100644 index 000000000..0c14b3130 --- /dev/null +++ b/retroshare-gui/src/util/framecatcher.cpp @@ -0,0 +1,336 @@ +/**************************************************************** + * This file is distributed under the following license: + * + * Copyright (c) 2006 Raul E. + * Copyright (c) 2010 Chris Evi-Parker + * + * 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. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + *************************************************************************/ + + +#include "framecatcher.h" + +#include + +framecatcher::framecatcher(): xine(NULL), stream(NULL), vo_port(NULL){ + + // start up drivers + std::string vo_driver = "auto"; + xine= xine_new(); + xine_init(xine); + + if((vo_port=xine_open_video_driver(xine,vo_driver.c_str(),XINE_VISUAL_TYPE_NONE, NULL))==NULL) + std::cerr << "framecatcher::framecatcher() " << "ERROR OPENING VIDEO DRIVER"; + +} + +framecatcher::~framecatcher(){ + + if(stream != NULL){ + close(); + } + + xine_close_video_driver(xine,vo_port); + +} + +std::string framecatcher::getCodec(){ + return codec; +} + +int framecatcher::getLength(){ + return length; +} + +int framecatcher::open(const std::string& fileName){ + + int errorCode = 0; + + + /* ensure resources used previous stream have been released */ + if(stream != NULL) + close(); + + + stream = xine_stream_new(xine,NULL,vo_port); + + if(stream == NULL) + return 0; + + + // open stream + if(!xine_open(stream,fileName.c_str())){ + errorCode= xine_get_error(stream); + return errorCode; + } + + // get length of video file stream is attached to + if(!xine_get_pos_length(stream,0,0,&length)){ + errorCode = xine_get_error(stream); + return errorCode; + } + + xine_play(stream,0,0); + const char* temp_codec=xine_get_meta_info(stream, XINE_META_INFO_VIDEOCODEC); + + if(temp_codec == NULL) + return 0; + + codec = temp_codec; + return 1; +} + +void framecatcher::close(){ + + if(stream != NULL){ + + xine_close(stream); + xine_dispose(stream); + stream = NULL; + } + +} + + +int framecatcher::getRGBImage(int frame, unsigned char*& rgb32BitData, int& width, int& height){ + + if(stream == NULL) + return 0; + + int errCode = 0; + xine_play(stream,0,0); + xine_play(stream,0,frame); // 1 frame 2 mseconds + + uint8_t *yuv = NULL, *y = NULL, *u = NULL, *v =NULL ; + int ratio = 0, format = 0; + + if (!xine_get_current_frame(stream, &width, &height, &ratio, &format, NULL)){ + errCode= xine_get_error(stream); + return errCode; + } + + yuv = new uint8_t[((width+8) * (height+1) * 2)]; + if (yuv == NULL){ + std::cerr << "Out of Memory!"; + return 0; + } + + if (!xine_get_current_frame(stream, &width, &height, &ratio, &format, yuv)){ + errCode= xine_get_error(stream); + + if(yuv != NULL) + delete[] yuv; + + return errCode; + } + + /* + * convert to yv12 if necessary + */ + switch (format){ + case XINE_IMGFMT_YUY2: + { + uint8_t *yuy2 = yuv; + + yuv = new uint8_t[(width * height * 2)]; + if (yuv == NULL){ + std::cerr << "Not enough memory to make screenshot!" << std::endl; + return 0; + } + + y = yuv; + u = yuv + width * height; + v = yuv + width * height * 5 / 4; + + yuy2Toyv12 (y, u, v, yuy2, width, height); + + delete [] yuy2; + } + break; + case XINE_IMGFMT_YV12: + y = yuv; + u = yuv + width * height; + v = yuv + width * height * 5 / 4; + + break; + default: + { + std::cerr << "Format Not Supported" << std::endl; + + if(yuv != NULL) + delete [] yuv; + + return 0; + } + } + + rgb32BitData = yv12ToRgb (y, u, v, width, height); + delete [] yuv; + return 1; +} + + + + +void framecatcher::yuy2Toyv12 (uint8_t *y, uint8_t *u, uint8_t *v, uint8_t *input, int width, int height){ + + int i, j, w2; + + w2 = width / 2; + + for (i = 0; i < height; i += 2){ + for (j = 0; j < w2; j++){ + /* + * packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] + */ + *(y++) = *(input++); + *(u++) = *(input++); + *(y++) = *(input++); + *(v++) = *(input++); + } + + /* + * down sampling + */ + + for (j = 0; j < w2; j++){ + /* + * skip every second line for U and V + */ + *(y++) = *(input++); + input++; + *(y++) = *(input++); + input++; + } + } +} + +unsigned char * framecatcher::yv12ToRgb (uint8_t *src_y, uint8_t *src_u, uint8_t *src_v, int width, int height){ + /* + * Create rgb data from yv12 + */ + +#define clip_8_bit(val) \ +{ \ + if (val < 0) \ + val = 0; \ + else \ + if (val > 255) val = 255; \ +} + + int i, j; + + int y, u, v; + int r, g, b; + + int sub_i_uv; + int sub_j_uv; + + int uv_width, uv_height; + + unsigned char *rgb; + + uv_width = width / 2; + uv_height = height / 2; + + rgb = new unsigned char[(width * height * 4)]; //qt needs a 32bit align + if (!rgb) //qDebug ("Not enough memory!"); + return NULL; + + + for (i = 0; i < height; ++i){ + /* + * calculate u & v rows + */ + sub_i_uv = ((i * uv_height) / height); + + for (j = 0; j < width; ++j){ + /* + * calculate u & v columns + */ + sub_j_uv = ((j * uv_width) / width); + + /*************************************************** + * + * Colour conversion from + * http://www.inforamp.net/~poynton/notes/colour_and_gamma/ColorFAQ.html#RTFToC30 + * + * Thanks to Billy Biggs + * for the pointer and the following conversion. + * + * R' = [ 1.1644 0 1.5960 ] ([ Y' ] [ 16 ]) + * G' = [ 1.1644 -0.3918 -0.8130 ] * ([ Cb ] - [ 128 ]) + * B' = [ 1.1644 2.0172 0 ] ([ Cr ] [ 128 ]) + * + * Where in xine the above values are represented as + * + * Y' == image->y + * Cb == image->u + * Cr == image->v + * + ***************************************************/ + + y = src_y[(i * width) + j] - 16; + u = src_u[(sub_i_uv * uv_width) + sub_j_uv] - 128; + v = src_v[(sub_i_uv * uv_width) + sub_j_uv] - 128; + + r = (int)((1.1644 * (double)y) + (1.5960 * (double)v)); + g = (int)((1.1644 * (double)y) - (0.3918 * (double)u) - (0.8130 * (double)v)); + b = (int)((1.1644 * (double)y) + (2.0172 * (double)u)); + + clip_8_bit (r); + clip_8_bit (g); + clip_8_bit (b); + + rgb[(i * width + j) * 4 + 0] = b; + rgb[(i * width + j) * 4 + 1] = g; + rgb[(i * width + j) * 4 + 2] = r; + rgb[(i * width + j) * 4 + 3] = 0; + + } + } + + return rgb; +} + +void framecatcher::getXineError(int errorCode, std::string& errorStr){ + + switch (errorCode){ + case XINE_ERROR_NO_INPUT_PLUGIN: + case XINE_ERROR_NO_DEMUX_PLUGIN: { + errorStr = "No plugin found to handle this resource"; + break; + } + case XINE_ERROR_DEMUX_FAILED: { + errorStr = "Resource seems to be broken"; + break; + } + case XINE_ERROR_MALFORMED_MRL: { + errorStr = "Requested resource does not exist"; + break; + } + case XINE_ERROR_INPUT_FAILED: { + errorStr = "Resource can not be opened"; + break; + } + default: { + errorStr = "Unknown error"; + break; + } + } + + return; +} diff --git a/retroshare-gui/src/util/framecatcher.h b/retroshare-gui/src/util/framecatcher.h new file mode 100644 index 000000000..9bb6e2a80 --- /dev/null +++ b/retroshare-gui/src/util/framecatcher.h @@ -0,0 +1,80 @@ +#ifndef FILEFUNCTIONS_H +#define FILEFUNCTIONS_H + +#include +#include + +#include + + +/*! + * This can be used to retrieve image frames at a specified + * time from video files using the xine library + * + * In the original implementation this class derived from, attributes were declared static, + * Possibly a good reason, as using seperate instances + * of framecatcher can cause a crash if the xine stream is not correctly closed + */ +class framecatcher{ + +public: + + /*! + * video drivers/ports are started up + */ + framecatcher(); + + /*! + * video drivers/ports closed, + * current stream is closed if open + */ + ~framecatcher(); + + std::string getCodec(); + + int getLength(); + + /*! + * + * @param frame time in msecs you want frame to be taken + * @param rgb32BitData 32 bit aligned rgb image format + * @param width of the image data returned + * @param height of the image data returned + */ + int getRGBImage(int frame, unsigned char*& rgb32BitData, int& width, int& height); + + /*! + * attaches a xine stream to the file, + * if valid user can then request image frames using RGBImage + * please ensure you close this stream before establishing a new one! + * Not doing may lead to a seg fault, even if you are using a new instance of framecatcher + * @see getRGBImage + * @see close + */ + int open(const std::string& file); + + /*! + * closes and disposes current xine stream if open + */ + void close(); + +private: + + xine_t *xine; + static xine_stream_t *stream; + xine_video_port_t *vo_port; + std::string vo_driver; + + + int length; // length of the stream + + void getXineError(int errCode, std::string& errStr); + + void yuy2Toyv12 (uint8_t *, uint8_t *, uint8_t *, uint8_t *, int , int ); + unsigned char * yv12ToRgb (uint8_t *, uint8_t *, uint8_t *, int , int ); + + +}; + + +#endif