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

📄 mediapacketbuffer.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 "mediapacketbuffer.h"#define PACKET_BUFFER_SIZE    500MediaPacketBuffer::MediaPacketBuffer() : avFormatMutex(), bufferMutex(){    setJoin(false);    FFAutoLockUnlockMutex streamLock(avFormatMutex);    FFAutoLockUnlockMutex bufferLock(bufferMutex);    avFormatContext = 0;    openFlag.assign(0);    pthread_create(&threadId, 0, (void *(*)(void *))MediaPacketBuffer::startThreadLoop, this);}MediaPacketBuffer::~MediaPacketBuffer(){    // qDebug("MediaPacketBuffer::~MediaPacketBuffer()");    join();    // qDebug("MediaPacketBuffer::~MediaPacketBuffer() finished");}void *MediaPacketBuffer::startThreadLoop(void *arg){    MediaPacketBuffer *context = (MediaPacketBuffer *)arg;    qDebug("media packet buffer thread started");    while ( !context->isJoin() ) {	// qDebug("media packet buffer waiting for file open");	context->bufferMutex.wait(); // EOF or stopped, wait until we are signaled again (another file opened or seeked)	qDebug("media packet buffer thread resumed");	while ( context->isOpen() ) {	    // qDebug("buffering packets");	    context->startBufferingPackets();	    context->bufferMutex.timedWait(500000); // Buffer has been filled, wait 500ms for buffer to get used a bit	    // qDebug("media packet buffer waiting for packets to be used");	}	qDebug("media packet buffer thread paused");    }    sched_yield(); // So we can wait for the pthread_join()    qDebug("media packet buffer thread ended");    return 0;}bool MediaPacketBuffer::open(const QString &fileName){    FFAutoLockUnlockMutex streamLock(avFormatMutex);    FFAutoLockUnlockMutex bufferLock(bufferMutex);    // open the input file with generic libav function    if ( av_open_input_file(&avFormatContext, QFile::encodeName(fileName).data(), NULL, 0, 0) < 0 ) {	// strInfo = qApp->translate( "LibFFMpegPlugin", "Error: Could not open stream: " ) + fileName;	qDebug("  Error opening %s", fileName.latin1() );	avFormatContext = 0;	openFlag.assign(0);	return false;    }    qDebug("  Opened %s", fileName.latin1() );    // Decode first frames to get stream parameters (for some stream types like mpeg)    if ( !avFormatContext || av_find_stream_info(avFormatContext) < 0 ) {	qDebug("  Error getting parameters for %s", fileName.latin1() );	if ( avFormatContext )	    av_close_input_file( avFormatContext );	avFormatContext = 0;	openFlag.assign(0);	return false;    }    audioCodecContext = 0;    videoCodecContext = 0;    // update the current parameters so that they match the one of the input stream    for ( int i = 0; i < avFormatContext->nb_streams; i++ ) {	AVCodecContext *enc = &avFormatContext->streams[i]->codec;	AVCodec *c = avcodec_find_decoder( enc->codec_id );	if ( !c ) {	    qDebug("  Unsupported codec for stream[%i], with codec id %i", i, enc->codec_id);	} else if ( avcodec_open( enc, c ) < 0 ) {	    qDebug("  Error opening codec for stream[%i], with codec id %i, codec: %s", i, enc->codec_id, c->name);	} else {	    switch (enc->codec_type) {		case CODEC_TYPE_AUDIO:		    qDebug("  Found audio stream[%i], with codec id %2i, codec: %s", i, enc->codec_id, c->name);		    audioStream.assign(i);		    audioCodecContext = enc;		    break;		case CODEC_TYPE_VIDEO:		    qDebug("  Found video stream[%i], with codec id %2i, codec: %s", i, enc->codec_id, c->name);		    videoStream.assign(i);		    videoCodecContext = enc;		    break;		default:		    qDebug("  Found unknown stream type, stream[%i], with codec id %2i, codec: %s", i, enc->codec_id, c->name);		    break;	    }	}    }    openFlag.assign(1);    return true;}void MediaPacketBuffer::start(){    bufferMutex.signal();    bufferMutex.signal();}MediaPacket *MediaPacketBuffer::getPacket(){    FFAutoLockUnlockMutex streamLock(avFormatMutex);    // read a packet from input    AVPacket avPkt;    int readFailures = 0;    // Wait for file to be opened and successful read    while (!avFormatContext || av_read_packet(avFormatContext, &avPkt) < 0) {	if ( avFormatContext && url_feof( &avFormatContext->pb ) )	    return 0; // EOF	readFailures++;	if ( readFailures > 20 ) {	    qDebug("too many read failures, assuming EOF");	    return 0; // EOF, clearly we can't get any more packets out, and we aren't getting an eof, something wrong	}	avFormatMutex.unlock();	avFormatMutex.timedWait(100000); // wait a moment, this could be streamed data which takes time to read	avFormatMutex.lock();    }    MediaPacket *pkt = new MediaPacket(avPkt);    pkt->fileOffset = url_ftell( &avFormatContext->pb );    // convert pts (presentation timestamp) to milliseconds    if ((unsigned long long)avPkt.pts != AV_NOPTS_VALUE && avFormatContext->pts_den)	pkt->msecOffset = avPkt.pts * 1000 * avFormatContext->pts_num / avFormatContext->pts_den;    else        pkt->msecOffset = 0;    return pkt;}bool MediaPacketBuffer::startBufferingPackets(){    int bufferedPackets = waitingAudioPackets.count() + waitingVideoPackets.count();    while ( isOpen() && bufferedPackets <= PACKET_BUFFER_SIZE ) {	MediaPacket *pkt = getPacket();	if ( pkt ) {	    if ( pkt->pkt.stream_index == (int)audioStream ) {		waitingAudioPackets.append( pkt );	    } else if ( pkt->pkt.stream_index == (int)videoStream ) {		waitingVideoPackets.append( pkt );	    }	} else {	    FFAutoLockUnlockMutex streamLock(avFormatMutex);	    MediaPacket *pkt1 = new MediaPacket();	    MediaPacket *pkt2 = new MediaPacket();	    waitingAudioPackets.append(pkt1);	    waitingVideoPackets.append(pkt2);	    qDebug("media packet buffering stopped, EOF");	    return false;	}	bufferedPackets = waitingAudioPackets.count() + waitingVideoPackets.count();    }    // qDebug("media packet buffers refilled");    avFormatMutex.signal();    return isOpen();}MediaPacket *MediaPacketBuffer::getAnotherVideoPacket(){    MediaPacket *pkt = 0;    while ( !pkt && (int)videoStream != -1 ) {	pkt = waitingVideoPackets.next();	if ( pkt ) {	    if ( pkt->eof ) {		qDebug("Video EOF");		delete pkt;		return 0;	    }	    return pkt;	}	if ( waitingAudioPackets.count() >= PACKET_BUFFER_SIZE )	    waitingAudioPackets.clear();	bufferMutex.signal(); // restart buffering thread	qDebug("Video packet buffer empty");	avFormatMutex.timedWait(10000); // wait a moment for more packets to get buffered    }    qDebug("No video stream");    return 0;}MediaPacket *MediaPacketBuffer::getAnotherAudioPacket(){    MediaPacket *pkt = 0;    while ( !pkt && (int)audioStream != -1 ) {	pkt = waitingAudioPackets.next();	if ( pkt ) {	    if ( pkt->eof ) {		qDebug("Audio EOF");		delete pkt;		return 0;	    }	    return pkt;	}	if ( waitingVideoPackets.count() >= PACKET_BUFFER_SIZE ) // There might be video packets encoded with a video codec we	    waitingVideoPackets.clear();			 // don't support and therefore the packets aren't getting consumed	bufferMutex.signal(); // restart buffering thread	qDebug("Audio packet buffer empty");	avFormatMutex.timedWait(10000); // wait a moment for more packets to get buffered    }    qDebug("No audio stream");    return 0;}

⌨️ 快捷键说明

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