📄 vidrend.cpp
字号:
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
/****************************************************************************
* Debug Settings
*/
// #define ENABLE_TRACE
// #define ENABLE_SYNC_TRACE
// #define ENABLE_SCHED_TRACE
// #define ENABLE_FETCH_TRACE
// #define ENABLE_INPUT_TRACE
/****************************************************************************
* Operational Compile-time Settings
*/
// #define SYNC_RESIZE_OK
// #define SYNC_VS_SWITCHING
// #define REBUFFER_ON_VIDEO
#define SET_NONZERO_VIEWFRAME_ONLY
#define RESIZE_AFTER_SITE_ATTACHED
#define DO_ABSOLUTE_TIMING
#ifdef HELIX_FEATURE_VIDREND_SYNCSMOOTHING
#define SYNC_SMOOTHING
#define SYNC_PRE_SMOOTHING
#endif // HELIX_FEATURE_VIDREND_SYNCSMOOTHING
#define DEFAULT_VS2_TARGETRECT
#define MAX_ULONG32_AS_DOUBLE ((double) ((ULONG32) 0xFFFFFFFF))
#define MAX_LONG32_AS_DOUBLE ((double) ((LONG32) 0x7FFFFFFF))
#define MIN_LONG32_AS_DOUBLE ((double) ((LONG32) 0x80000000))
#if defined(_MACINTOSH) || defined(_MAC_UNIX)
#define OSGRANULE_BOOSTING_ENABLED FALSE
#else // _MACINTOSH
#define OSGRANULE_BOOSTING_ENABLED TRUE
#endif // _MACINTOSH
/****************************************************************************
* Debug Macros
*/
#ifdef ENABLE_TRACE
#define HX_TRACE_THINGY(x, m, l) \
{ \
FILE* f1; \
f1 = ::fopen(x, "a+"); \
(f1)?(::fprintf(f1, "%ld - %s = %ld \n", HX_GET_BETTERTICKCOUNT(), m, l), ::fclose(f1)):(0);\
}
#else // ENABLE_TRACE
#define HX_TRACE_THINGY(x, m, l)
#endif // ENABLE_TRACE
/****************************************************************************
* Defines
*/
#define BASE_VIDEO_RENDERER_NAME "Basic Video"
#define NAME_STATS_EXT ".name"
#define C4CC_STATS_EXT ".CodecFourCC"
#if defined(HELIX_FEATURE_VIDREND_NO_DEFAULT_WINDOW_SIZE)
#define DEFAULT_WIN_SIZE_X 0
#define DEFAULT_WIN_SIZE_Y 0
#else
#define DEFAULT_WIN_SIZE_X 160
#define DEFAULT_WIN_SIZE_Y 120
#endif
#define SYNC_INTERVAL 20 // in milliseconds
#define EARLY_FRAME_TOL 3 // in milliseconds
#define LATE_FRAME_TOL 30 // in milliseconds
#define NO_FRAMES_POLLING_INTERVAL 20 // in milliseconds
#define MAX_SLEEP_TIME 132 // in milliseconds
#define BLT_PACKET_QUEUE_SIZE 3 // in packets
#define SYNC_GOAL_SMOOTHING_DEPTH 30 // number of samples
#define SPEEDUP_GOAL_SMOOTHING_DEPTH 8 // number of samples
#define MAX_BAD_SAMPLE_INTERVAL 1000 // in milliseconds
#define VIDEO_STAT_INTERVAL 1000 // in milliseconds
#define VIDEO_STAT_INTERVAL_COUNT 2 // number of intervals to average over
#define MAX_OPTIMIZED_VIDEO_LEAD 200 // in milliseconds
#define DEFAULT_HARDWARE_BUFFER_COUNT 4
#define AUDIO_SKEW_POWER 4 // Maximum Audio Speedup Slope as
// 1/(2^AUDIO_SKEW_POWER)
#define MIN_BAD_PERSISTENCE_COUNT 0 // Minimum number of consecutive
// bad sync samples for the
// resync probation period to start
#define MIN_GOOD_PERSISTENCE_COUNT 0 // Minimum number of consecutive
// good sync samples for the
// resync probation period to be
// cancelled
#define MAX_BLT_LOOPS 3
#define BLT_RELIEF_DELAY 1 // in milliseconds
// Absolute timing settings
#define N_STABILIZATION_ITERATIONS 5
#define MAX_ALLOWED_TIMING_ERROR 2
#define SMALLEST_TIMABLE_PERIOD 2
// Default Decoding Priority
#ifdef _WIN32
#ifdef HELIX_FEATURE_VIDREND_BOOSTDECODE_ON_STARTUP
// on ce we need to get this started quickly, otherwise the initial packets expire
// we set the priority so we can check in onpace to reset only once
#define DFLT_DECODE_PRIORITY THREAD_PRIORITY_HIGHEST
#define DFLT_PRESENT_PRIORITY THREAD_PRIORITY_ABOVE_NORMAL
#else
#define DFLT_DECODE_PRIORITY THREAD_PRIORITY_BELOW_NORMAL
#define DFLT_PRESENT_PRIORITY THREAD_PRIORITY_ABOVE_NORMAL
#endif // HELIX_FEATURE_VIDREND_BOOSTDECODE_ON_STARTUP
#else // _WIN32
#define DFLT_DECODE_PRIORITY 0
#define DFLT_PRESENT_PRIORITY 0
#endif // _WIN32
// Lowest acceptable version numbers
#define STREAM_MAJOR_VERSION 0
#define STREAM_MINOR_VERSION 0
#define CONTENT_MAJOR_VERSION 0
#define CONTENT_MINOR_VERSION 0
#define DECODER_INTERVAL 5
#define BLTR_INTERVAL 5
#ifdef _WIN32
#define GETBITMAPCOLOR(x) GetBitmapColor( (LPBITMAPINFO)(x) )
#else // _WIN32
#define GETBITMAPCOLOR(x) GetBitmapColor( (HXBitmapInfo*)(x))
#endif // _WIN32
/****************************************************************************
* Includes
*/
#include "hlxclib/stdio.h"
#include "vidrend.ver"
#include "hxtypes.h"
#ifdef _WINDOWS
#include <windows.h>
#endif
#if defined(_UNIX) && !defined(_MAC_UNIX)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#ifndef QWS
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#endif /* QWS */
#endif
#include "hxwintyp.h"
#include "hxcom.h"
#include "hxcomm.h"
#include "hxthread.h"
// for sync
#include "hxengin.h"
#include "hxprefs.h"
#include "hxtick.h"
#include "timeval.h"
#include "hxevent.h"
#include "hxvsurf.h"
#include "ihxpckts.h"
#include "hxfiles.h"
#include "hxcore.h"
#include "hxerror.h"
#include "hxrendr.h"
#include "addupcol.h"
// #include "hxhyper.h"
#include "hxplugn.h"
#include "hxwin.h"
// #include "hxasm.h"
#include "hxmon.h"
#include "hxbuffer.h" // for CHXBuffer
#include "hxassert.h" // for HX_ASSERT()
#include "hxheap.h" // for heap checking
#include "hxslist.h" // CHXSimpleList
#include "chxbufpl.h"
#include "sdpchunk.h"
#include "vidrend.h"
#include "cpacemkr.h"
#include "hxver.h"
#if defined(_WINDOWS) && !defined(WIN32_PLATFORM_PSPC)
#include "ddraw.h"
#endif /* defined(_WINDOWS) && !defined(WIN32_PLATFORM_PSPC) */
// #include "coloracc.h"
#include "colormap.h"
#include "chxxtype.h" // For CHXxSize
#if defined(HELIX_FEATURE_PREFERENCES)
#include "hxprefs.h"
#include "hxprefutil.h"
#endif /* HELIX_FEATURE_PREFERENCES */
/****************************************************************************
* Debug
*/
#ifdef ENABLE_SYNC_TRACE
#define MAX_SYNC_TRACE_ENTRIES 10000
ULONG32 ulSyncTraceIdx = 0;
ULONG32 syncTraceArray[MAX_SYNC_TRACE_ENTRIES][3];
void DumpSyncEntries(void)
{
FILE* pFile = NULL;
ULONG32 ulIdx;
if (ulSyncTraceIdx > 0)
{
pFile = fopen("\\helix\\sync.txt", "wb");
}
if (pFile)
{
for (ulIdx = 0; ulIdx < ulSyncTraceIdx; ulIdx++)
{
fprintf(pFile, "%u\t%u\t%u\n", syncTraceArray[ulIdx][0],
syncTraceArray[ulIdx][1],
syncTraceArray[ulIdx][2]);
}
fclose(pFile);
}
ulSyncTraceIdx = 0;
}
#endif // ENABLE_SYNC_TRACE
#ifdef ENABLE_SCHED_TRACE
#define MAX_SCHED_TRACE_ENTRIES 10000
ULONG32 ulSchedTraceIdx = 0;
LONG32 schedTraceArray[MAX_SCHED_TRACE_ENTRIES];
void DumpSchedEntries(void)
{
FILE* pFile = NULL;
ULONG32 ulIdx;
if (ulSchedTraceIdx > 0)
{
pFile = fopen("\\helix\\sched.txt", "wb");
}
if (pFile)
{
for (ulIdx = 0; ulIdx < ulSchedTraceIdx; ulIdx++)
{
fprintf(pFile, "%d\n", schedTraceArray[ulIdx]);
}
fclose(pFile);
}
ulSchedTraceIdx = 0;
}
#endif // ENABLE_SCHED_TRACE
#ifdef ENABLE_FETCH_TRACE
#define MAX_FETCH_TRACE_ENTRIES 10000
ULONG32 ulFetchTraceIdx = 0;
LONG32 fetchTraceArray[MAX_FETCH_TRACE_ENTRIES];
void DumpFetchEntries(void)
{
FILE* pFile = NULL;
ULONG32 ulIdx;
if (ulFetchTraceIdx > 0)
{
pFile = fopen("\\helix\\fetch.txt", "wb");
}
if (pFile)
{
for (ulIdx = 0; ulIdx < ulFetchTraceIdx; ulIdx++)
{
fprintf(pFile, "%d\n", fetchTraceArray[ulIdx]);
}
fclose(pFile);
}
ulFetchTraceIdx = 0;
}
#endif // ENABLE_FETCH_TRACE
#ifdef ENABLE_INPUT_TRACE
#define MAX_INPUT_TRACE_ENTRIES 10000
ULONG32 ulInputTraceIdx = 0;
LONG32 inputTraceArray[MAX_INPUT_TRACE_ENTRIES];
void DumpInputEntries(void)
{
FILE* pFile = NULL;
ULONG32 ulIdx;
if (ulInputTraceIdx > 0)
{
pFile = fopen("\\helix\\input.txt", "wb");
}
if (pFile)
{
for (ulIdx = 0; ulIdx < ulInputTraceIdx; ulIdx++)
{
fprintf(pFile, "%d\n", inputTraceArray[ulIdx]);
}
fclose(pFile);
}
ulInputTraceIdx = 0;
}
#endif // ENABLE_INPUT_TRACE
/****************************************************************************
* Constants
*/
const char* const CVideoRenderer::zm_pDescription = "RealNetworks Video Renderer Plugin";
const char* const CVideoRenderer::zm_pCopyright = HXVER_COPYRIGHT;
const char* const CVideoRenderer::zm_pMoreInfoURL = HXVER_MOREINFO;
const char* const CVideoRenderer::zm_pStreamMimeTypes[] =
{
NULL
};
/************************************************************************
* CVideoRenderer
*/
/************************************************************************
* Constructor/Destructor
*/
CVideoRenderer::CVideoRenderer(void)
: m_lRefCount(0)
, m_pContext(NULL)
, m_pStream(NULL)
, m_pHeader(NULL)
, m_pMutex(NULL)
, m_pBltMutex(NULL)
, m_pVSMutex(NULL)
, m_pDecoderPump(NULL)
, m_pBltrPump(NULL)
, m_ulDecoderPacemakerId(0)
, m_ulBltrPacemakerId(0)
, m_pDecoderVideoFormat(NULL)
, m_pBltrVideoFormat(NULL)
, m_pBackChannel(0)
, m_pCommonClassFactory(0)
, m_ulRegistryID(0)
, m_pVideoStats(NULL)
, m_pMISUS(NULL)
, m_pMISUSSite(NULL)
, m_ulEarlyFrameTol(EARLY_FRAME_TOL)
, m_ulLateFrameTol(LATE_FRAME_TOL)
, m_ulNoFramesPollingInterval(NO_FRAMES_POLLING_INTERVAL)
, m_ulMaxSleepTime(MAX_SLEEP_TIME)
, m_ulBltPacketQueueSize(BLT_PACKET_QUEUE_SIZE)
, m_ulSyncGoalSmoothingDepth(SYNC_GOAL_SMOOTHING_DEPTH)
, m_ulSpeedupGoalSmoothingDepth(SPEEDUP_GOAL_SMOOTHING_DEPTH)
, m_ulMaxBadSeqSamples(0)
, m_lTimeLineOffset(0)
, m_lDecodePriority(DFLT_DECODE_PRIORITY)
, m_ulStreamBaseTime(0)
, m_ulBaseTime(0)
, m_ulTimeNormalizationOffset(0)
, m_bBitmapSet(FALSE)
, m_bFrameSizeInitialized(FALSE)
, m_bWinSizeFixed(FALSE)
, m_bOSGranuleBoost(OSGRANULE_BOOSTING_ENABLED)
, m_bOSGranuleBoostVS2(OSGRANULE_BOOSTING_ENABLED)
, m_bOptimizedBlt(FALSE)
, m_bUseVideoSurface2(FALSE)
#if defined(_WINDOWS) && defined(HELIX_FEATURE_VIDREND_OPTIMIZEDVIDEO)
, m_bTryVideoSurface2(TRUE)
#else // _WINDOWS
, m_bTryVideoSurface2(FALSE)
#endif // _WINDOWS
, m_bVideoSurface2Transition(FALSE)
, m_bVideoSurface1Requested(FALSE)
, m_bVideoSurfaceInitialized(FALSE)
, m_bVideoSurfaceReinitRequested(FALSE)
, m_bPresentInProgress(FALSE)
, m_bVS2BufferUnavailableOnLastBlt(FALSE)
, m_ulHWBufCount(DEFAULT_HARDWARE_BUFFER_COUNT)
, m_ulConfigHWBufCount(DEFAULT_HARDWARE_BUFFER_COUNT)
, m_pClipRect(NULL)
, m_pPreferences(NULL)
, m_pRegistry(NULL)
, m_pScheduler(NULL)
, m_pOptimizedScheduler(NULL)
, m_bPendingCallback(FALSE)
, m_bSchedulerStartRequested(FALSE)
, m_hPendingHandle(0)
, m_ulCallbackCounter(0)
, m_bDecoderRunning(FALSE)
, m_bSiteAttached(FALSE)
, m_PlayState(Stopped)
, m_ulBytesToBuffer(0)
, m_ulAvgBitRate(0)
, m_ulPreroll(0)
, m_ulBufferingStartTime(0)
, m_ulBufferingStopTime(0)
, m_ulBufferingTimeOut(0)
, m_bBufferingOccured(FALSE)
, m_bBufferingNeeded(FALSE)
, m_pVideoFormat(NULL)
, m_pBltPacketQueue(NULL)
, m_pActiveVideoPacket(NULL)
, m_ulActiveVideoTime(0)
, m_bFirstFrame(TRUE)
, m_bBaseTimeSet(FALSE)
, m_bFirstSurfaceUpdate(TRUE)
, m_bPendingRedraw(FALSE)
, m_bVS1UpdateInProgress(FALSE)
, m_ulSyncSmoothingDepth(0)
, m_ulSyncInterval(SYNC_INTERVAL)
, m_ulBadSeqSampleCount(0)
, m_ulGoodSeqSampleCount(0)
, m_fTrendSyncDelta(0.0)
, m_pResizeCB(NULL)
, m_pVSurf2InputBIH(NULL)
, m_bIsScheduledCB(0)
#ifdef HELIX_FEATURE_VIDREND_UNTIMED_DECODE
, m_bUntimedRendering(FALSE)
#endif /* HELIX_FEATURE_VIDREND_UNTIMED_DECODE */
, m_bActiveVideoPacketLocalized(FALSE)
{
m_SetWinSize.cx = 0;
m_SetWinSize.cy = 0;
m_LastSetSize.cx = 0;
m_LastSetSize.cy = 0;
m_rViewRect.left = 0;
m_rViewRect.top = 0;
m_rViewRect.right = 0;
m_rViewRect.bottom = 0;
memset(&m_BitmapInfoHeader, 0, sizeof(HXBitmapInfoHeader));
}
CVideoRenderer::~CVideoRenderer()
{
// NOTE: You should do your renderer cleanup here, instead of
// in EndStream(), because your renderer is still left around
// after the stream is ended in case it is a display renderer
// and it needs to "paint" it's display area.
EndOptimizedBlt();
if (m_pActiveVideoPacket)
{
m_pActiveVideoPacket->Clear();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -