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

📄 videocodeccontext.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 <qapplication.h>#include "videocodeccontext.h"VideoCodecContext::VideoCodecContext(MediaPacketBuffer *buffer){    FFAutoLockUnlockMutex videoLock(videoMutex);    packetBuffer = buffer;    videoScaleContext.init();    videoCodecContext = 0;    currentVideoPacket = 0;    resetTimeStamps();}VideoCodecContext::~VideoCodecContext(){    //qDebug("VideoCodecContext::~VideoCodecContext()");    close();    delete currentVideoPacket;    //qDebug("VideoCodecContext::~VideoCodecContext() done");}void VideoCodecContext::fileInit(){    FFAutoLockUnlockMutex videoLock(videoMutex);    resetTimeStamps();    videoCodec = 0;    videoCodecContext = 0;    frame = 0;    skipNext = 0;    droppedFrames = 0;    framesInLastPacket = 0;    totalFrames = 0;    totalVideoBytesRead = 0;    totalVideoFramesDecoded = 0;}void VideoCodecContext::codecInit(){    FFAutoLockUnlockMutex videoLock(videoMutex);    videoCodecContext = packetBuffer->videoContext();    if ( videoCodecContext )	videoCodecContext->hurry_up = 0;    FFAutoLockUnlockMutex timeStampLock(timeStampMutex);    //qDebug("videoCodecContext->frame_rate=%d/%d",videoCodecContext->frame_rate,videoCodecContext->frame_rate_base);    if ( videoCodecContext ) {	long rate = videoCodecContext->frame_rate_base;	frameRateNumerator = ( rate ) ? rate * 1000LL : 1000;	rate = videoCodecContext->frame_rate;	frameRateDenominator = ( rate ) ? rate : 25;    } else {	frameRateDenominator = 1;	frameRateNumerator = 1;    }}long VideoCodecContext::absoluteTimeStamp(){    FFAutoLockUnlockMutex timeStampLock(timeStampMutex);    return currentVideoTimeStamp + currentFrameOffsetFromTimeStamp * frameRateNumerator / frameRateDenominator;}long VideoCodecContext::timeStamp(){    FFAutoLockUnlockMutex timeStampLock(timeStampMutex);    if ( currentVideoTimeStamp == -1 )	return fakedVideoTimeStamp + fakedFrameOffsetFromTimeStamp * frameRateNumerator / frameRateDenominator;    return currentVideoTimeStamp + currentFrameOffsetFromTimeStamp * frameRateNumerator / frameRateDenominator;}void VideoCodecContext::close(){    FFAutoLockUnlockMutex videoLock(videoMutex);    if ( videoCodecContext )	avcodec_close( videoCodecContext );    videoCodecContext = 0;}int VideoCodecContext::decodeFrame(){    int gotPicture = 0;    while (!gotPicture) {	if ( !currentVideoPacket || videoPacketLen <= 0 ) {	    if ( currentVideoPacket )		framesInLastPacket = frameInPacket;	    delete currentVideoPacket;	    currentVideoPacket = packetBuffer->getAnotherVideoPacket();	    if ( !currentVideoPacket )		return 0; // EOF	    videoPacketPtr = currentVideoPacket->pkt.data;	    videoPacketLen = currentVideoPacket->pkt.size;	    frameInPacket = 0;	    if ( currentVideoPacket->msecOffset ) {		FFAutoLockUnlockMutex timeStampLock(timeStampMutex);		currentVideoTimeStamp = currentVideoPacket->msecOffset;		currentFrameOffsetFromTimeStamp = 0;	    }	}	int ret = avcodec_decode_video(videoCodecContext, &picture, &gotPicture, videoPacketPtr, videoPacketLen);	//sched_yield();	if ( ret >= 0 ) {	    totalVideoBytesRead += ret;	    videoPacketPtr += ret;	    videoPacketLen -= ret;	} else {	    qDebug("Error while decoding video stream");	    delete currentVideoPacket;	    currentVideoPacket = 0;	    return -1;	}	if ( gotPicture ) {#define NO_DEBUG#ifndef NO_DEBUG// Fake a slow device//usleep(30);#endif	    FFAutoLockUnlockMutex timeStampLock(timeStampMutex);	    totalVideoFramesDecoded++;	    frameInPacket++;	    if ( currentVideoTimeStamp != -1 )		currentFrameOffsetFromTimeStamp++;	    fakedFrameOffsetFromTimeStamp++;	}    }    return 1;}long VideoCodecContext::bitRate(){    FFAutoLockUnlockMutex videoLock(videoMutex);    if ( videoCodecContext ) {	if ( videoCodecContext->bit_rate )	    return videoCodecContext->bit_rate;	if ( totalVideoBytesRead > 100 ) {	    return (long)((double)totalVideoBytesRead * 8		    * videoCodecContext->frame_rate		    / ((double)totalVideoFramesDecoded * videoCodecContext->frame_rate_base));	}    }    return -1;}QString VideoCodecContext::fileInfo(){    FFAutoLockUnlockMutex videoLock(videoMutex);    QString videoInfo;    if ( videoCodecContext ) {	if ( videoCodecContext->codec )	    videoInfo += qApp->translate( "LibFFMpegPlugin", "Video: " ) + videoCodecContext->codec->name + ",";	videoInfo += qApp->translate( "LibFFMpegPlugin", "Rate: " ) + QString::number( videoCodecContext->bit_rate ) + ",";	videoInfo += qApp->translate( "LibFFMpegPlugin", "Width: " ) + QString::number( videoCodecContext->width ) + ",";	videoInfo += qApp->translate( "LibFFMpegPlugin", "Height: " ) + QString::number( videoCodecContext->height ) + ",";    }    return videoInfo;}int VideoCodecContext::videoStreams(){    FFAutoLockUnlockMutex lock(videoMutex);    return (videoCodecContext) ? 1 : 0;}int VideoCodecContext::videoWidth( int ){    FFAutoLockUnlockMutex lock(videoMutex);    return (videoCodecContext) ? videoCodecContext->width : 0;}int VideoCodecContext::videoHeight( int ){    FFAutoLockUnlockMutex lock(videoMutex);    return (videoCodecContext) ? videoCodecContext->height : 0;}double VideoCodecContext::videoFrameRate( int ){    FFAutoLockUnlockMutex lock(videoMutex);    return (videoCodecContext && videoCodecContext->frame_rate_base) ?            (double)videoCodecContext->frame_rate / videoCodecContext->frame_rate_base : 1.0;}bool VideoCodecContext::videoReadScaledFrame( unsigned char **output_rows, int in_w, int in_h, int out_w, int out_h, ColorFormat fmt ){    FFAutoLockUnlockMutex lock(videoMutex);    if ( !videoCodecContext || !videoCodecContext->codec ) {	qDebug("No video decoder for stream");	return 1;    }    static int skipCount = 0;    if ( skipNext ) {	skipNext--;	skipCount++;	if ( skipCount > 100 ) // EOF or we are decoding way too slow... give up	    return 1;	qDebug("skip next frame");	return 0;    }    skipCount = 0;    int ret = decodeFrame();    // qDebug("decoded frame");    if ( ret < 0 )	return 0;    if ( ret == 0 )	return 1;    frame = videoCodecContext->frame_number;    // qDebug("got picture: %i", frame );    int lineStride = (uchar*)output_rows[1] - (uchar*)output_rows[0];    // qDebug("scale config");    if (!videoScaleContext.configure(in_w, in_h, out_w, out_h, &picture, lineStride, videoCodecContext->pix_fmt, fmt))	return 1;    // qDebug("scale convert");    videoScaleContext.convert((uint8_t*)output_rows[0], &picture);    // qDebug("VideoCodecContext::videoReadScaledFrame() finished");    return 0;}void VideoCodecContext::flush(){    qDebug("VideoCodecContext::flush()");    FFAutoLockUnlockMutex videoLock(videoMutex);    if ( videoCodecContext )	avcodec_flush_buffers( videoCodecContext );    delete currentVideoPacket;    currentVideoPacket = 0;    qDebug("VideoCodecContext::flush() finished");}bool VideoCodecContext::syncToTimeStamp( long audioTS ){    FFAutoLockUnlockMutex videoLock(videoMutex);    int maxFrames = 10;        // Case where we are syncing after seeking, we should make efforts to get it right    if ( audioTS == -1 || timeStamp() == -1 )	maxFrames = 50; // 2 seconds    // Try to consume up the waiting video packets so we get back in sync with the audio    while ( maxFrames ) {	long videoTS = timeStamp();	if ( audioTS != -1 && videoTS != -1 ) {	    const int AVSyncSlack = 100;    // 100 ms slack	    long timeStampDiff = audioTS - videoTS;	    //qDebug("timeStampDiff: %li", timeStampDiff);	    if ( timeStampDiff > -AVSyncSlack && timeStampDiff < AVSyncSlack ) // Audio is ahead of the video		return true;	    if ( timeStampDiff < -AVSyncSlack ) {  // Video is ahead of the audio		qDebug("slow down video, timeStampDiff: %li", timeStampDiff);		skipNext++;		return true;	    }	} else {	    if ( absoluteTimeStamp() == -1 ) {		FFAutoLockUnlockMutex timeStampLock(timeStampMutex);		fakedVideoTimeStamp = audioTS;		fakedFrameOffsetFromTimeStamp = 0;	    }	    const int AVSizeSlack = 50;   // 50 bytes slack	    long fileOffsetDiff = packetBuffer->distanceBetweenAudioAndVideo() + 500; // offset a bit to compensate for buffered audio	    // qDebug("fileOffsetDiff: %li", fileOffsetDiff);	    if ( fileOffsetDiff > -AVSizeSlack && fileOffsetDiff < AVSizeSlack ) // Audio is ahead of the video		return true;	    if ( fileOffsetDiff < -AVSizeSlack ) { // Video is ahead of the audio		qDebug("slow down video, fileOffsetDiff: %li", fileOffsetDiff);		skipNext++;		return true;	    } else {		qDebug("decode more video, fileOffsetDiff: %li", fileOffsetDiff);	    }	}	// when set to 1 during decoding, b frames will be skiped when	// set to 2 idct/dequant will be skipped too	int oldHurryUp = videoCodecContext->hurry_up;	videoCodecContext->hurry_up = 1;	int ret = decodeFrame();	videoCodecContext->hurry_up = oldHurryUp;	if ( ret == 0 )	    return false;	if ( ret > 0 ) {	    droppedFrames++;	    maxFrames--;	    qDebug("frames dropped: %i", droppedFrames);	}    }    return true;}void VideoCodecContext::resetTimeStamps(){    FFAutoLockUnlockMutex timeStampLock(timeStampMutex);    delete currentVideoPacket;    currentVideoPacket = 0;    currentVideoTimeStamp = -1;    currentFrameOffsetFromTimeStamp = 0;    fakedVideoTimeStamp = 0;    fakedFrameOffsetFromTimeStamp = 0;}void VideoCodecContext::leadInVideo(){    qDebug("VideoCodecContext::leadInVideo()");    FFAutoLockUnlockMutex videoLock(videoMutex);    if ( videoCodecContext )	avcodec_flush_buffers( videoCodecContext );    resetTimeStamps();    // Sync up the input with the packets so    // we are ready to get the next video frame    // We have to sync through a keyframe, but not    // all codecs have keyframes or some have keyframes    // which are far apart depending on the encoder which created the file.    // So instead of hoping to find a keyframe, we decode 25 frames so we    // are reasonably confident we have enough picture complete by then    // to resume decoding from.    int framesToDecode = 25;    // XXX clear picture to black perhaps    while ( framesToDecode > 0 ) {	int ret = decodeFrame();	if ( ret == 0 )	    break; // EOF	if ( ret > 0 )	    framesToDecode--;    }    qDebug("VideoCodecContext::leadInVideo() finished");}

⌨️ 快捷键说明

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