⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libffmpegplugin.cpp

📁 Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3.10平台上编译为嵌入式图形界面操作系统。
💻 CPP
字号:
/************************************************************************ Copyright (C) 2000-2005 Trolltech AS and its licensors.** All rights reserved.**** This file is part of the Qtopia Environment.**** This file may be distributed and/or modified under the terms of the** GNU General Public License version 2 as published by the Free Software** Foundation and appearing in the file LICENSE.GPL included in the** packaging of this file.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.**** See http://www.trolltech.com/gpl/ for GPL licensing information.** See below for additional copyright and license information**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include <qfileinfo.h>#include "libffmpegplugin.h"LibFFMpegPlugin::LibFFMpegPlugin() : videoContext(&packetBuffer), audioContext(&packetBuffer){    FFAutoLockUnlockMutex lock(pluginMutex);    strInfo = "";    streamingFlag = FALSE;    needPluginInit = TRUE;}LibFFMpegPlugin::~LibFFMpegPlugin(){    // qDebug("LibFFMpegPlugin::~LibFFMpegPlugin()");    close();    // qDebug("LibFFMpegPlugin::~LibFFMpegPlugin() finished");}bool LibFFMpegPlugin::isFileSupported( const QString& fileName ){    qDebug("Checking if %s is supported", fileName.latin1() );    QString ext2 = fileName.right(3).lower();    QString ext3 = fileName.right(4).lower();    QString ext4 = fileName.right(5).lower();    if	( ( ext3 == ".asf" ) || ( ext3 == ".amr" ) || ( ext3 == ".avi" ) ||	//( ext3 == ".ogg" ) || ( ext3 == ".vob" ) || ( ext3 == ".wav" ) ||	  ( ext3 == ".mov" ) || ( ext3 == ".mp2" ) || ( ext3 == ".mp3" ) ||	  ( ext3 == ".mp4" ) || ( ext4 == ".mpeg") || ( ext3 == ".mpg" ) ||	  ( ext2 == ".rm"  ) || ( ext3 == ".wma" ) || ( ext3 == ".wmf" ) ||	  ( ext3 == ".wmv" ))	return true;    // Wav files need to be handled by the wav plugin    if ( ext3 == ".wav" )	return false;    bool okay = open( fileName );    close();    return okay;}bool LibFFMpegPlugin::open( const QString& fileName ){    if ( !init( fileName ) )	return false;    return true;}bool LibFFMpegPlugin::openURL( const QUrl& url, const QString& ){    if ( !init(url.toString(false, false)) )	return false;    FFAutoLockUnlockMutex lock(pluginMutex);    streamingFlag = true;    return true;}bool LibFFMpegPlugin::init( const QString& fileName ){    FFAutoLockUnlockMutex lock(pluginMutex);    qDebug("LibFFMpegPlugin::init()");    if ( needPluginInit ) {	avcodec_init();	avcodec_register_all();	av_register_all();	needPluginInit = false;    }    fileLength = 0;    totalTimeCache = 0;    haveTotalTimeCache = false;    streamingFlag = false;    strInfo = "";    savedSeekPos.assign(-1);    packetBuffer.init();    videoContext.fileInit();    audioContext.fileInit();    if (!packetBuffer.open(fileName))	return false;    audioContext.codecInit();    videoContext.codecInit();    // Get the file length    fileLength = packetBuffer.fileLength();    // Get the total bit rate    totalBitRate = packetBuffer.bitRate();    if ( !totalBitRate ) {	// Add together the audio and video bit rates	long audioBitRate = audioContext.bitRate();	long videoBitRate = videoContext.bitRate();	if ( audioStreams() && audioBitRate > 0 )	    totalBitRate += audioBitRate;	if ( videoStreams() && videoBitRate > 0 )	    totalBitRate += videoBitRate;    }    haveTotalBitRate = (bool)totalBitRate;    // Get the total time    totalTimeCache = packetBuffer.duration();    if ( !totalTimeCache ) {	if ( totalBitRate && fileLength ) {	    // The 8000 multiplier is because the rate is in bits per second and	    // there are 8 bits to a byte and we want the time in milliseconds.	    totalTimeCache = ((long long)fileLength * 8000) / totalBitRate;	}    }#if FIND_LAST_PACKET_TIMESTAMP_TO_WORK_OUT_PLAY_TIME    // Last resort attempt to determine the total play time    // Seeks towards the end of the file, reads packets looking for timestamps    if ( !totalTimeCache )	totalTimeCache = packetBuffer.getLastPacketTime();#endif    haveTotalTimeCache = (bool)totalTimeCache;    qDebug("  File length: %li bytes", fileLength);    qDebug("  Total time: %li ms", totalTimeCache);    qDebug("  Total bitrate: %li bits/sec", totalBitRate);    qDebug("LibFFMpegPlugin::init() finished");//    packetBuffer.start();    return true;}const QString &LibFFMpegPlugin::fileInfo(){    FFAutoLockUnlockMutex lock(pluginMutex);    if ( strInfo == "" ) {	if ( haveTotalTimeCache ) {	    int seconds = totalTimeCache / 1000;	    strInfo += qApp->translate( "LibFFMpegPlugin", "Length: " ) + QString::number( seconds / 60 ) + ":" +		 QString::number( (seconds % 60) / 10 ) + QString::number( (seconds % 60) % 10 ) + ",";	}	strInfo += audioContext.fileInfo();	strInfo += videoContext.fileInfo();    }    return strInfo;}bool LibFFMpegPlugin::close(){    qDebug("LibFFMpegPlugin::close()");    FFAutoLockUnlockMutex lock(pluginMutex);    flushBuffers();    if ( packetBuffer.isOpen() ) {	fileLength = 0;	audioContext.close();	videoContext.close();	packetBuffer.close();	return TRUE;    }    return FALSE;}bool LibFFMpegPlugin::audioReadSamples( short *output, int channels, long samples, long& samplesRead, int ){/*    qDebug("LibFFMpegPlugin::audioReadSamples()     decoded pts, video: %5li audio: %5li  faked pts, video: %5li audio: %5li",	    videoContext.absoluteTimeStamp(), audioContext.absoluteTimeStamp(), videoContext.timeStamp(), audioContext.timeStamp());*/    return (realSeek()) ? audioContext.audioReadSamples(output, channels, samples, samplesRead) : false;}bool LibFFMpegPlugin::videoReadScaledFrame( unsigned char **output_rows, int, int, int in_w, int in_h, int out_w, int out_h, ColorFormat fmt, int ){/*    qDebug("LibFFMpegPlugin::videoReadScaledFrame() decoded pts, video: %5li audio: %5li  faked pts, video: %5li audio: %5li",	    videoContext.absoluteTimeStamp(), audioContext.absoluteTimeStamp(), videoContext.timeStamp(), audioContext.timeStamp());*/    return (realSeek()) ? videoContext.videoReadScaledFrame(output_rows, in_w, in_h, out_w, out_h, fmt) : 1;}bool LibFFMpegPlugin::sync(){    if ( realSeek() && packetBuffer.isOpen() && audioStreams() && videoStreams() )        return videoContext.syncToTimeStamp(audioContext.timeStamp()); // relative time stamp    //qDebug("sync needs both audio and video contexts to sync together");    return false;}bool LibFFMpegPlugin::seek( long pos ){    qDebug("LibFFMpegPlugin::seek()");    FFAutoLockUnlockMutex lock(pluginMutex);    if ( pos > 1000 )	pos = pos - 1000;    else	pos = 0;    savedSeekPos.assign(pos);    qDebug("LibFFMpegPlugin::seek() finished");    return true;}//// Seek and realSeek are split in two because realSeek can take a reasonable// amount of CPU when both video and audio are involved.// The mediaplayer calls seek as the user moves the slider, and as they// move the slider it updates the UI with where in the file they are.// This is queried with a call to currentTime()//bool LibFFMpegPlugin::realSeek(){    // throw away any outstanding packets we aren't consuming    if ( !audioStreams() )	packetBuffer.flushAudioPackets();    if ( !videoStreams() )	packetBuffer.flushVideoPackets();    if ( savedSeekPos == -1 )	return true;    FFAutoLockUnlockMutex lock(pluginMutex);    long pos = (int)savedSeekPos;    savedSeekPos.assign(-1);        // Seek in to the file    if ( packetBuffer.seek(pos) ) {	if ( videoStreams() ) {	    videoContext.leadInVideo();	    if ( audioStreams() )		// Throw away audio packets till they are in time with the video packets		audioContext.syncToTimeStamp(videoContext.absoluteTimeStamp()); // absolute value	}	if ( audioStreams() ) {	    audioContext.leadInAudio();	    if ( videoStreams() )		videoContext.syncToTimeStamp(audioContext.absoluteTimeStamp());	}	return true;    }    // qDebug("LibFFMpegPlugin::realSeek() finished");    return false;}long LibFFMpegPlugin::tell(){    if (savedSeekPos != -1)	return (int)savedSeekPos;    return packetBuffer.pos();}bool LibFFMpegPlugin::currentTimeAvailable(){    // Use audio context first, using its lock    long audioTimeStamp = audioContext.absoluteTimeStamp();    if (audioTimeStamp != -1)	return true;    // Then seperately lock plugin without audio context locked    FFAutoLockUnlockMutex lock(pluginMutex);    return (totalBitRate || (fileLength && haveTotalTimeCache));}long LibFFMpegPlugin::currentTime(){    // qDebug("LibFFMpegPlugin::currentTime");    // Use audio context first, using its lock    long audioTimeStamp = audioContext.absoluteTimeStamp();    if ( audioTimeStamp != -1 ) {	if (savedSeekPos == -1) {	    // qDebug("LibFFMpegPlugin::currentTime end");	    return audioTimeStamp;	}    }    FFAutoLockUnlockMutex lock(pluginMutex);    if ( fileLength && haveTotalTimeCache ) {	// This method is generally more accurate, try it before using the bitrate method	return ((long long)totalTimeCache * tell()) / fileLength;    } else if ( totalBitRate ) {	// The 8000 multiplier is because the rate is in bits per second and	// there are 8 bits to a byte and we want the time in milliseconds.	return ((long long)8000 * tell()) / totalBitRate;    }    return -1;}//// Only calls thread safe functions//void LibFFMpegPlugin::flushBuffers(){    audioContext.flush();    videoContext.flush();    packetBuffer.flush();}//// Thread safe assuming QString and QUrl functions don't make use of static or global variables.// Also shouldn't be a problem as this function in reality is only called before decoding// starts always from the main thread//bool LibFFMpegPlugin::canStreamURL( const QUrl& url, const QString& ){    QString fileName = url.toString( true, false );    // Support file://    if ( fileName.left(7).lower() == "file://" )	return true;    // Support http://    if ( fileName.left(7).lower() == "http://" )	return true;    // Support rtsp://    if ( fileName.left(7).lower() == "rtsp://" )	return true;    // Does not support mms://    if ( fileName.left(6).lower() == "mms://" )	return false;    // All others assumed not supported    return false;}bool LibFFMpegPlugin::streamed(){    FFAutoLockUnlockMutex lock(pluginMutex);    return streamingFlag;}bool LibFFMpegPlugin::lengthAvailable(){    FFAutoLockUnlockMutex lock(pluginMutex);    return !streamingFlag;}long LibFFMpegPlugin::length(){    FFAutoLockUnlockMutex lock(pluginMutex);    return fileLength;}bool LibFFMpegPlugin::totalTimeAvailable(){    FFAutoLockUnlockMutex lock(pluginMutex);    return haveTotalTimeCache;}long LibFFMpegPlugin::totalTime(){    FFAutoLockUnlockMutex lock(pluginMutex);    return totalTimeCache;}bool LibFFMpegPlugin::seekAvailable(){    FFAutoLockUnlockMutex lock(pluginMutex);    return !streamingFlag;}bool LibFFMpegPlugin::tellAvailable(){    FFAutoLockUnlockMutex lock(pluginMutex);    return true;//!streamingFlag;}//// Clearly thread safe functions//const char *LibFFMpegPlugin::pluginName(){    return "LibFFMpegPlugin";}const char *LibFFMpegPlugin::pluginComment(){    return "This plugin uses ffmpeg, libavcodec, libav libraries written by Fabrice Bellard and others. "	   "The Qtopia plugin interface adaptor is created by Trolltech.";}double LibFFMpegPlugin::pluginVersion(){    return 1.0;}bool LibFFMpegPlugin::isOpen(){    return packetBuffer.isOpen();}int LibFFMpegPlugin::audioStreams(){    return audioContext.audioStreams();}int LibFFMpegPlugin::audioChannels(int stream){    return audioContext.audioChannels(stream);}int LibFFMpegPlugin::audioFrequency(int stream){    return audioContext.audioFrequency(stream);}int LibFFMpegPlugin::audioSamples( int ){    return -1;}bool LibFFMpegPlugin::audioSetSample( long, int ){    return false;}long LibFFMpegPlugin::audioGetSample( int ){    return 0;}int LibFFMpegPlugin::videoStreams(){    return videoContext.videoStreams();}int LibFFMpegPlugin::videoWidth(int stream){    return videoContext.videoWidth(stream);}int LibFFMpegPlugin::videoHeight(int stream){    return videoContext.videoHeight(stream);}double LibFFMpegPlugin::videoFrameRate(int stream){    return videoContext.videoFrameRate(stream);}int LibFFMpegPlugin::videoFrames( int ){    return -1;}bool LibFFMpegPlugin::videoSetFrame( long, int ){    return false;}long LibFFMpegPlugin::videoGetFrame( int ){    return -1;}bool LibFFMpegPlugin::videoReadFrame( unsigned char **, int, int, int, int, ColorFormat, int ){    return false;}bool LibFFMpegPlugin::videoReadYUVFrame( char *, char *, char *, int, int, int, int, int ){    return false;}double LibFFMpegPlugin::getTime(){    return -1;}bool LibFFMpegPlugin::setSMP( int ){    return false;}bool LibFFMpegPlugin::setMMX( bool ){    return false;}bool LibFFMpegPlugin::supportsAudio(){    return true;}bool LibFFMpegPlugin::supportsVideo(){    return true;}bool LibFFMpegPlugin::supportsYUV(){    return false;}bool LibFFMpegPlugin::supportsMMX(){    return false;}bool LibFFMpegPlugin::supportsSMP(){    return false;}bool LibFFMpegPlugin::supportsStereo(){    return true;}bool LibFFMpegPlugin::supportsScaling(){    return true;}long LibFFMpegPlugin::getPlayTime(){    return -1;}bool LibFFMpegPlugin::supportsStreaming(){    return true;}bool LibFFMpegPlugin::syncAvailable(){    return true;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -