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

📄 libffmpegplugin.cpp

📁 Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3.7平台上编译为嵌入式图形界面操作系统。
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/************************************************************************ Copyright (C) 2000-2002 Trolltech AS.  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.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include <qfileinfo.h>#include "libffmpegplugin.h"static const int AVSyncSlack = 200;LibFFMpegPlugin::LibFFMpegPlugin(){    scaleContextDepth = -1;    scaleContextInputWidth = -1;    scaleContextInputHeight = -1;    scaleContextPicture1Width = -1;    scaleContextPicture2Width = -1;    scaleContextOutputWidth = -1;    scaleContextOutputHeight = -1;    scaleContextLineStride = -1;    audioCodecContext = 0;    videoCodecContext = 0;    audioScaleContext = 0;    strInfo = "";    openFlag = FALSE;    streamingFlag = FALSE;    needPluginInit = TRUE;}LibFFMpegPlugin::~LibFFMpegPlugin(){    close();    flushAudioPackets();    flushVideoPackets();}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::isFileSupported( const QString& fileName ){    qDebug("checking if file is supported %s", fileName.latin1() );    QString ext2 = fileName.right(3).lower();    QString ext3 = fileName.right(4).lower();    QString ext4 = fileName.right(5).lower();    return  (		( ext3 == ".asf" ) ||		( ext3 == ".avi" ) ||		( ext3 == ".mov" ) ||		( ext3 == ".mp2" ) ||		( ext3 == ".mp3" ) ||		( ext4 == ".mpeg") ||		( ext3 == ".mpg" ) ||		//( ext3 == ".ogg" ) ||		( ext2 == ".rm" ) ||		//( ext3 == ".vob" ) || 		//( ext3 == ".wav" ) ||		( ext3 == ".wma" ) ||		( ext3 == ".wmf" ) ||		( ext3 == ".wmv" )	    );}void LibFFMpegPlugin::pluginInit(){    avcodec_init();    avcodec_register_all();    av_register_all();    needPluginInit = FALSE;}void LibFFMpegPlugin::fileInit(){    if ( needPluginInit )	pluginInit();    audioCodec = 0;    videoCodec = 0;    audioCodecContext = 0;    audioScaleContext = 0;    videoCodecContext = 0;    streamContext = 0;    frame = 0;    videoStream = -1;    audioStream = -1;    fileLength = 0;    skipNext = 0;    currentPacketTimeStamp = 0;    currentVideoTimeStamp = 0;    currentAudioTimeStamp = 0;    haveTotalTimeCache = FALSE;    totalTimeCache = TRUE;    droppedFrames = 0;    framesInLastPacket = 0;    streamingFlag = FALSE;    strInfo = "";    totalFrames = 0;    openFlag = TRUE;}bool LibFFMpegPlugin::open( const QString& fileName ){    qDebug("opening file %s", fileName.latin1() );    fileInit();    if ( !fileLength ) {	QFileInfo fi( fileName );	fileLength = fi.size();    }    // open the input file with generic libav function    if ( av_open_input_file(&streamContext, fileName.latin1(), NULL, 0, 0) < 0 ) {	strInfo = qApp->translate( "LibFFMpegPlugin", "Error: Could not open file, File: " ) + fileName;        qDebug( "%s", strInfo.latin1() );	return FALSE;    }    qDebug("opened file %s", fileName.latin1() );    // Decode first frames to get stream parameters (for some stream types like mpeg)    if ( av_find_stream_info(streamContext) < 0 ) {	qDebug("Error getting parameters for file %s", fileName.latin1() );	return FALSE;    }    qDebug("initing file %s", fileName.latin1() );     // update the current parameters so that they match the one of the input stream    for ( int i = 0; i < streamContext->nb_streams; i++ ) {	//printf( "searching: %i\n", i );        AVCodecContext *enc = &streamContext->streams[i]->codec;	enc->codec = avcodec_find_decoder( enc->codec_id );	//printf( "decoder found: %s\n", enc->codec->name );	if ( !enc->codec )	    qDebug("Unsupported codec for input stream");        else if ( avcodec_open( enc, enc->codec ) < 0 )            qDebug("Error while opening codec for input stream");	else {	    switch (enc->codec_type) {		case CODEC_TYPE_AUDIO:		    qDebug("setting audio stream with id: %i", i);		    audioStream = i;		    audioCodecContext = enc;		    break;		case CODEC_TYPE_VIDEO:		    qDebug("setting video stream with id: %i", i);		    videoStream = i;		    videoCodecContext = enc;		    break;		default:		    qDebug("unknown stream type");		    break;	    }	}    }    if ( audioCodecContext )        audioScaleContext = audio_resample_init( 2, audioCodecContext->channels, 44100, audioCodecContext->sample_rate );        // Try to determine the total play time if possible    if ( !lengthAvailable() || !tellAvailable() )	haveTotalTimeCache = FALSE;    else {	// Jump to near the end of the file	url_fseek( &streamContext->pb, length() - 100000, SEEK_SET );	AVPacket pkt;	pkt.pts = 0;	totalTimeCache = 0;	// Read packets till we get to the end to try and get the last timestamp available	while ( av_read_packet(streamContext, &pkt) >= 0 ) {	    if ( pkt.pts > totalTimeCache )		totalTimeCache = pkt.pts / 100;	    pkt.pts = 0;	    av_free_packet(&pkt);	}	// Jump back to the beginning so we are ready to decode	url_fseek( &streamContext->pb, 0, SEEK_SET );	haveTotalTimeCache = totalTimeCache > 1;	if ( !haveTotalTimeCache ) {	    // Calculate the play time of constant bit rate files	    int totalBitRate = 0;	    if ( audioStream != -1 && audioCodecContext ) 		totalBitRate += audioCodecContext->bit_rate;	    if ( videoStream != -1 && videoCodecContext ) 		totalBitRate += videoCodecContext->bit_rate;	    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.		totalTimeCache = ((long long)length() * 8000) / totalBitRate;		haveTotalTimeCache = TRUE;	    }	}    }    if ( videoCodecContext )	videoCodecContext->hurry_up = 0;    if ( videoCodecContext && videoCodecContext->frame_rate )	msecPerFrame = (1000 * FRAME_RATE_BASE) / videoCodecContext->frame_rate;    else	msecPerFrame = 1000 / 25;    qDebug("finished opening %s", fileName.latin1() );    return true;}const QString &LibFFMpegPlugin::fileInfo(){    if ( strInfo == "" ) {	if ( haveTotalTimeCache ) {	    int seconds = totalTimeCache / 1000;	    strInfo += qApp->translate( "LibFFMpegPlugin", "Play Time: " ) + QString::number( seconds / 60 ) + ":" +		 QString::number( (seconds % 60) / 10 ) + QString::number( (seconds % 60) % 10 ) + ",";	}	if ( audioCodecContext ) {	    strInfo += qApp->translate( "LibFFMpegPlugin", "Audio Tracks: 1," );	    if ( audioCodecContext->codec )		strInfo += qApp->translate( "LibFFMpegPlugin", "Audio Format: " ) +  audioCodecContext->codec->name + ",";	    strInfo += qApp->translate( "LibFFMpegPlugin", "Audio Bit Rate: " ) + QString::number( audioCodecContext->bit_rate ) + ",";	    strInfo += qApp->translate( "LibFFMpegPlugin", "Audio Channels: " ) + QString::number( audioCodecContext->channels ) + ",";	    strInfo += qApp->translate( "LibFFMpegPlugin", "Audio Frequency: " ) + QString::number( audioCodecContext->sample_rate ) + ",";	}	if ( videoCodecContext ) {	    strInfo += qApp->translate( "LibFFMpegPlugin", "Video Tracks: 1," );	    if ( videoCodecContext->codec )		strInfo += qApp->translate( "LibFFMpegPlugin", "Video Format: " ) + videoCodecContext->codec->name + ",";	    strInfo += qApp->translate( "LibFFMpegPlugin", "Video Bit Rate: " ) + QString::number( videoCodecContext->bit_rate ) + ",";	    strInfo += qApp->translate( "LibFFMpegPlugin", "Video Width: " ) + QString::number( videoCodecContext->width ) + ",";	    strInfo += qApp->translate( "LibFFMpegPlugin", "Video Height: " ) + QString::number( videoCodecContext->height ) + ",";	}    }    return strInfo;}static uchar bufferedSamples[AVCODEC_MAX_AUDIO_FRAME_SIZE * 16];static int bufferedSamplesCount = 0;bool LibFFMpegPlugin::close(){    if ( openFlag ) {	flushAudioPackets();	flushVideoPackets();	AutoLockUnlockMutex lock( &pluginMutex );	qDebug("close");	if ( audioScaleContext )	    audio_resample_close( audioScaleContext );	if ( audioCodecContext )            avcodec_close( audioCodecContext );	if ( videoCodecContext )            avcodec_close( videoCodecContext );	if ( streamContext )	    av_close_input_file( streamContext );	audioCodecContext = 0;	videoCodecContext = 0;	audioScaleContext = 0;	streamContext = 0;	fileLength = 0;	bufferedSamplesCount = 0;	openFlag = FALSE;	return TRUE;    }    return FALSE;}bool LibFFMpegPlugin::isOpen(){    return openFlag;}int LibFFMpegPlugin::audioStreams(){    return (audioCodecContext) ? 1 : 0;}int LibFFMpegPlugin::audioChannels( int ){    return 2;}int LibFFMpegPlugin::audioFrequency( int ){    return 44100;}int LibFFMpegPlugin::audioSamples( int ){    return -1;}bool LibFFMpegPlugin::audioSetSample( long, int ){    return FALSE;}long LibFFMpegPlugin::audioGetSample( int ){    return 0;}bool LibFFMpegPlugin::audioReadSamples( short *output, int channels, long samples, long& samplesRead, int ){    AutoLockUnlockMutex lock( &audioMutex );    if ( !audioCodecContext || !audioCodecContext->codec ) {	qDebug("No audio decoder for stream");	samplesRead = 0;	return FALSE;    }    if ( samples > AVCODEC_MAX_AUDIO_FRAME_SIZE ) {	qDebug("Decoder can not buffer that much data at a time!!!");	samples = AVCODEC_MAX_AUDIO_FRAME_SIZE;    }    uchar tmpSamples[AVCODEC_MAX_AUDIO_FRAME_SIZE * 8];    long long tmpSamplesRead = 0;    long long fact = audioCodecContext->sample_rate * 2 * audioCodecContext->channels;    long long bufferedSamplesCount_fact = bufferedSamplesCount * fact;    long long samples_fact = samples * fact; // Buffer ahead    long long tmpBufCount = bufferedSamplesCount_fact;    bool haveBothTimeStamps = ( currentVideoTimeStamp && currentAudioTimeStamp );    if ( !haveBothTimeStamps )	samples_fact += 9200 * fact; // With DivX AVI streams I have tested against, libavcodec doesn't	// return any time stamps and the audio needs to be slightly behind the video so buffering longer achieves this.    while ( tmpBufCount < samples_fact ) {	MediaPacket *pkt = getAnotherPacket( audioStream );	if ( !pkt ) {	    samplesRead = -1;	    return FALSE; // EOF	}	int len = pkt->pkt.size;	unsigned char *ptr = pkt->pkt.data;	int bytesRead = 0;	while ( len ) {	    int ret = 0;	    if ( pkt ) {		if ( ptr <  pkt->pkt.data ) {		    qDebug("inconsistancy error");

⌨️ 快捷键说明

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