}
}
+UINT PESPacket::countPictureHeaders(bool h264) const
+{
+ if (size < 12) return 0;
+ UINT pattern = ( ((UINT)data[ 8] << 24) |
+ ((UINT)data[ 9] << 16) |
+ ((UINT)data[10] << 8) |
+ (UINT)data[11] );
+ UINT pos = 11;
+ UINT count=0;
+ if (h264) {
+
+ while (pos<size)
+ {
+ pos++;
+ pattern = (pattern << 8) | data[pos];
+ if (pattern==DEMUXER_H264_ACCESS_UNIT) count++;
+ }
+ return count;
+ } else {
+ while (pos<size)
+ {
+ pos++;
+ pattern = (pattern << 8) | data[pos];
+ if (pattern==DEMUXER_PIC_HEAD) count++;
+ }
+ return count;
+ }
+}
+
UINT PESPacket::findSeqHeader(bool h264) const
{
if (seq_header != 1) return seq_header;
nalu.getBits(8); //constraints
nalu.getBits(8); //level_idc
nalu.getUe(); //seq_parameter_set_id
+ int chroma=1;
if (profile==100 || profile==110 || profile==122 || profile==144)
{
- if (nalu.getUe()==3)
+ chroma=nalu.getUe();
+ if (chroma==3)
{
nalu.getBits(1);
}
}
}
}
+ int chromunitx=1;
+ int chromunity=1;
+ switch (chroma) {
+ case 0:
+ chromunitx=chromunity=1; break;
+ case 1:
+ chromunitx=chromunity=2; break;
+ case 2:
+ chromunitx=2;chromunity=1; break;
+ case 3:
+ chromunitx=chromunity=1; break;
+ };
+
nalu.getUe(); //log2framenum
UINT temp=nalu.getUe();
if (temp==0) //pict order
nalu.getBits(1);
if (nalu.getBits(1))
{
- nalu.getUe();
- nalu.getUe();
- nalu.getUe();
- nalu.getUe();
+ horizontal_size-=nalu.getUe()*chromunitx;
+ horizontal_size-=nalu.getUe()*chromunitx;
+ vertical_size-=nalu.getUe()*(2-interlaced)*chromunity;
+ vertical_size-=nalu.getUe()*(2-interlaced)*chromunity;
}
if (nalu.getBits(1))
{
UINT findPictureHeader(bool h264) const;
UINT findSeqHeader(bool h264) const;
+ UINT countPictureHeaders(bool h264) const;
static const ULLONG PTS_INVALID = (1LL << 33);
protected:
void copyFrom(const PESPacket& packet);
{
packetNumber++;
}
+ UINT numpicts=packet.countPictureHeaders(h264);
- if (frameCounting && packet.findPictureHeader(h264) &&
+ if (frameCounting && numpicts &&
packet.getPacketType() >= PESTYPE_VID0 &&
packet.getPacketType() <= PESTYPE_VIDMAX)
{
- ULONG frame_num = (frameNumber)++;
+ frameNumber+=numpicts;
+ ULONG frame_num = frameNumber;
if ((h264 || packet.findSeqHeader(h264) > 1) && packet.hasPTS())
{
PTSMapEntry me;
virtual long long SetStartOffset(long long curreftime, bool *rsync)=0;
virtual void ResetTimeOffsets()=0;
+ virtual bool dtsTimefix(){return false;} //determines if the draintargets needs a mixure of pts and dts or not
+
// The following two functions are used by the Stream
// to deliver media packets to the front end (DrainTarget).
//
}
DsAllocator::~DsAllocator() {
- ((OsdWin*)Osd::getInstance())->setExternalDriving(NULL,vwidth,vheight);
((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_off);
+ ((OsdWin*)Osd::getInstance())->setExternalDriving(NULL,vwidth,vheight);
CleanupSurfaces();
}
void DsAllocator::GetEVRSamples()
{
+ Lock();
MFCLOCK_STATE clockstate;
if (mfclock) mfclock->GetState(0,&clockstate);
//MessageBox(0,"get samples","samples",0);
- Lock();
+
if (mfclock && clockstate==MFCLOCK_STATE_STOPPED && fullevrsamples.size()>0)
{
Unlock();
//Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_PROCESSINPUTNOTIFY received");
GetEVRSamples(); } break;
case MFVP_MESSAGE_BEGINSTREAMING:{
- //Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_BEGINSTREAMING received");
+ Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_BEGINSTREAMING received");
ResetSyncOffsets();
((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
- ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_started);
+ //((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_started);//No need to do this causes misbehaviout
endofstream=false;
}break;
case MFVP_MESSAGE_ENDSTREAMING: {
- //Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_ENDSTREAMING received");
+ Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_ENDSTREAMING received");
((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_off);
((OsdWin*)Osd::getInstance())->setExternalDriving(NULL,vwidth,vheight);
//FlushEVRSamples();
if (PRESENTATION_CURRENT_POSITION!=startoffset) FlushEVRSamples();
((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
+ Log::getInstance()->log("DsAllocator", Log::DEBUG , "OnClockStart");
((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_started);
GetEVRSamples();
timeEndPeriod(1);
((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_off);
+
+ Log::getInstance()->log("DsAllocator", Log::DEBUG , "OnClockStop");
((OsdWin*)Osd::getInstance())->setExternalDriving(NULL,vwidth,vheight);
FlushEVRSamples();
return S_OK;
{
timeEndPeriod(1);
((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
+
+ Log::getInstance()->log("DsAllocator", Log::DEBUG , "OnClockPause");
((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_pause);
return S_OK;
}
HRESULT STDMETHODCALLTYPE DsAllocator::OnClockRestart(MFTIME systime)
{
((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
+
+ Log::getInstance()->log("DsAllocator", Log::DEBUG , "OnClockRestart");
((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_started);
return S_OK;
HRESULT hres=sample->GetSampleTime(&prestime);
if (hres==S_OK)
{
- mfclock->GetCorrelatedTime(0,¤ttime,&systime);
+ if (mfclock) mfclock->GetCorrelatedTime(0,¤ttime,&systime);
}
LONGLONG delta=prestime-currenttime;
} else if (evrstate==EVR_pres_started)
{
LPDIRECT3DSURFACE9 surf;
- dsallocator->GetNextSurface(&surf,&waittime);
+ if (dsallocator) dsallocator->GetNextSurface(&surf,&waittime);
if (surf==NULL)
{
Render();
{
RenderDS(surf);
surf->Release();
- dsallocator->DiscardSurfaceandgetWait(&waittime);
+ if (dsallocator) dsallocator->DiscardSurfaceandgetWait(&waittime);
}
}
}
}
#ifdef WIN32
//ok we have the pts now convert it to a continously time code in 100ns units
- if (hasdts ) newPacket.presentation_time=(ULLONG)(newPacket.dts*10000LL/90LL);
+ if (hasdts && draintarget->dtsTimefix()) newPacket.presentation_time=(ULLONG)(newPacket.dts*10000LL/90LL);
else newPacket.presentation_time=(ULLONG)(newPacket.pts*10000LL/90LL);
//newPacket.presentation_time-=draintarget->SetStartOffset((ULLONG)(newPacket.pts*10000LL/90LL),&newPacket.disconti);
vmrdeinterlacing=2;//Best
videofilterselected=-1;
videoH264filterselected=-1;
+ OSVERSIONINFO verinfo;
+ verinfo.dwOSVersionInfoSize=sizeof(verinfo);
+ GetVersionEx(&verinfo);
+
+ if (verinfo.dwMajorVersion>=6) {
currentpresenter=EVR;
+ } else {
+ currentpresenter=VMR9;
+ }
+ videoH264dtsfix=false;
+ videompeg2dtsfix=false;
currentpresenter=VMR9;
}
+ name=vdr->configLoad("DirectShow","videoH264dtsfix");
+ if (name!=NULL) {
+ if (STRCASECMP(name,"YES")==0) {
+ videoH264dtsfix=true;
+ } else {
+ videoH264dtsfix=false;
+ }
+ }
+ name=vdr->configLoad("DirectShow","videompeg2dtsfix");
+ if (name!=NULL) {
+ if (STRCASECMP(name,"YES")==0) {
+ videompeg2dtsfix=true;
+ } else {
+ videompeg2dtsfix=false;
+ }
+ }
+
name=vdr->configLoad("DirectGraphics", "StretchFiltering");
if (name!=NULL) {
if (STRCASECMP(name,"None")==0) {
currentpresenter=EVR;
}
}break;
+ case 4: {
+ if (STRCASECMP(option->options[option->userSetChoice],"Yes")==0) {
+ videoH264dtsfix=true;
+ } else {
+ videoH264dtsfix=false;
+ }
+ }break;
+ case 5: {
+ if (STRCASECMP(option->options[option->userSetChoice],"Yes")==0) {
+ videompeg2dtsfix=true;
+ } else {
+ videompeg2dtsfix=false;
+ }
+ }break;
};
return false;
if (((OsdWin*)Osd::getInstance())->IsEvrSupported())
{
static const char* presenteropts[]={"EVR","VMR9"};
- option = new Option(3,tr("Video Presenter Filter"),"DirectShow", "VideoPresenter",Option::TYPE_TEXT,2,0,0,presenteropts,NULL,false,this);
+ option = new Option(3,tr("Video Presenter Filter"),"DirectShow", "VideoPresenter",Option::TYPE_TEXT,2,
+ (currentpresenter==EVR)?0:1,0,presenteropts,NULL,false,this);
} else {
static const char* presenteropts[]={"VMR9"};
option = new Option(3,tr("Video Presenter Filter"),"DirectShow", "VideoPresenter",Option::TYPE_TEXT,1,0,0,presenteropts,NULL,false,this);
options->push_back(option);
pane->addOptionLine(option);
+ static const char* yesnoopts[]={"Yes","No"};
+ option = new Option(4,tr("Video H264 fix dts time"), "DirectShow","videoH264dtsfix",Option::TYPE_TEXT,2,1,0,yesnoopts,NULL,false,this);
+ options->push_back(option);
+ pane->addOptionLine(option);
+
+ option = new Option(5,tr("Video Mpeg2 fix dts time"), "DirectShow","videompeg2dtsfix",Option::TYPE_TEXT,2,1,0,yesnoopts,NULL,false,this);
+ options->push_back(option);
+ pane->addOptionLine(option);
+
+
}
if (h264)
{
+ if (vid_details.width!=0 && vid_details.height!=0)
+ {
sourcefilter->GetVideoPin()->SetPinMode(MPTYPE_VIDEO_H264,&vid_details);
}
else
{
+ sourcefilter->GetVideoPin()->SetPinMode(MPTYPE_VIDEO_H264,NULL);
+ }
+
+ }
+ else
+ {
+ if (vid_details.width!=0 && vid_details.height!=0)
+ {
sourcefilter->GetVideoPin()->SetPinMode(MPTYPE_VIDEO_MPEG2,&vid_details);
}
+ else
+ {
+ sourcefilter->GetVideoPin()->SetPinMode(MPTYPE_VIDEO_MPEG2,NULL);
+ }
+ }
if (videofilter->EnumPins(&pinenum) == S_OK)
{
IPin *current=NULL;
virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos);
virtual UINT DeliverMediaSample(UCHAR* buffer, UINT *samplepos);
UINT DeliverMediaPacket(const MediaPacket packet, const UCHAR* buffer, UINT *samplepos);
+ virtual bool dtsTimefix() {if (h264)return videoH264dtsfix; else return videompeg2dtsfix;}
virtual bool supportsh264();
IBaseFilter *getVideoH264Filter();
VideoFilterDescList videoH264filterlist;
int videoH264filterselected;
+ bool videoH264dtsfix;
+ bool videompeg2dtsfix;
#endif
int dsInitVideoFilter();
IMediaControl* dsmediacontrol;