📄 hwlprivate.c
字号:
unsigned short ptshi, ptslo; CQuasar *this = (CQuasar*)pQ->H.pIDecoder; Q4SymbolTable *pQ4 = (Q4SymbolTable*)this->pQ; // give some extra time for buffering pts = pMWD->Pts; if (((pts - scr) < 20000) && scr > 20000) scr -= 20000;// printk ("scr: 0x%08lx%08lx pts: 0x%08lx%08lx (%d)\n", // (DWORD)(scr>>32), (DWORD)(scr),// (DWORD)(pts>>32), (DWORD)(pts),// (long)(pts - scr));// printk ("vobu start ptm: 0x%08lx%08lx\n",// (DWORD)(pP->vobu_sptm >> 32),// (DWORD)(pP->vobu_sptm)); // in case there is not a pts for every frame // this will allow the ucode to calculate the pts correctly // for the first frame pP->vobu_sptm -= 6006; ptshi = (unsigned short)((pP->vobu_sptm >> 1) >> 16); ptslo = (unsigned short)((pP->vobu_sptm >> 1) & 0xFFFF); IDecoder_WriteDM (pQ->H.pIDecoder, pQ4->PicPTSLo.addr, ptslo); IDecoder_WriteDM (pQ->H.pIDecoder, pQ4->PicPTSHi.addr, ptshi); } if (pP->flags & CTS_AVAILABLE_FLAG) { scr = scr<<1; }// printk ("IDecoder_WriteSCR: %08lx\n", (unsigned long)(scr >> 1)); IDecoder_WriteSCR (pQ->H.pIDecoder, scr); pQ->H.SetSTC = 0; } rc=(IDecoderBoard_SendVideoPayload(pQ->H.pIDecoderBoard, pMWD, pP->packet.DataLeft, pP->flags, 1,/*bLastPacket: value has meaning here. F.G*/ &pQ->H.VideoByteCounter, &pQ->H.VideoEventPending)==TRUE)?0:-1; if (rc==0){// if (pP->flags)// printk ("vpts: %08lx (%d)\n", (unsigned long)(pP->packet.Pts >> 1), (int)pP->packet.DataLeft); pQ->H.VideoEventPending++; // printk ("pQ->H.VideoByteCounter = %d\n", (int)pQ->H.VideoByteCounter);#ifdef VERBOSE pQprintk("hwlprivate_feedme:[VIDEO] pP=%p, MWD=%p\n",pP,pMWD);#endif if (pP->flags) { pQ->last_video_pts_sent = (unsigned long)(pMWD->Pts >> 1); pQ->scr_when_last_video_pts_was_sent = (unsigned long)(IDecoder_ReadSCR (pQ->H.pIDecoder) >> 1); } /* if (pP->flags) { if (++vpts_counter > 10) { unsigned long long pts, scr; vpts_counter = 0; pts = pMWD->Pts; scr = IDecoder_ReadSCR (pQ->H.pIDecoder); printk ("vpts: 0x%02lx%08lx, scr: 0x%02lx%08lx, bytecounter: %lu, (%ld)\n", (unsigned long)(pts >> 32), (unsigned long)(pts), (unsigned long)(scr >> 32), (unsigned long)(scr), (unsigned long)pQ->H.VideoByteCounter, (long)(pts - scr)); } } */ }#ifdef VERBOSE else { DWORD a,v;// // pQprintk("Cant send VIDEO\n"); v=IDecoder_GetStatus(pQ->H.pIDecoder,VIDEO); a=IDecoder_GetStatus(pQ->H.pIDecoder,AUDIO); pQprintk("Audio = %ld, Video = %ld\n",a,v); }#endif return rc; break; case AUDIO: IDecoderBoard_FreeConsumedData (pQ->H.pIDecoderBoard, AUDIO, &pQ->H.AudioEventPending);// IDecoder_GetDataFifoInfo (pQ->H.pIDecoder, AUDIO, &datafifo);// if (datafifo.Emptiness < pP->packet.DataLeft)// return -1;// if (IDecoder_PacketsFifoEmptiness (pQ->H.pIDecoder, AUDIO) <= 35)// return -1; if (pP->flags) { // ``1'' means the PTS fifo is full. Not to be confused with audio payload fifo. if (IDecoderBoard_PtsFifoEmptiness(pQ->H.pIDecoderBoard,AUDIO)<=1) {// printk ("audio pts fifo full\n"); return -1; } }#if 1// printk ("(%d)\n", pMWD->FirstAccessUnitPointer);// if (pQ->H.AudioByteCounter == 0)// {// printk ("audio PTS when bytecounter=0 is %08lx\n",// pMWD->Pts);// } if ((pQ->H.AudioByteCounter == 0) && pP->scr && pP->flags) { long delta; unsigned long long scr, pts; scr = IDecoder_ReadSCR (pQ->H.pIDecoder); pts = pMWD->Pts & 0x1ffffffffll; if(pP->flags & CTS_AVAILABLE_FLAG) { scr = scr>>1; } delta = pts - scr;// printk ("(scr=%08lx, pts=%08lx)\n", (unsigned long)(scr>>1), (unsigned long)(pMWD->Pts>>1)); if (delta > 0) { rc = -1; } else { pP->flags = 0;// printk ("audio pts0 = %08lx, scr = %08lx\n", (unsigned long)(pMWD->Pts>>1), (unsigned long)(scr>>1)); rc=(IDecoderBoard_SendAudioPayload(pQ->H.pIDecoderBoard, pMWD, pP->packet.DataLeft, pP->flags, 1,/*bLastPacket: value has meaning here. F.G*/ &pQ->H.AudioByteCounter, &pQ->H.AudioEventPending)==TRUE)?0:-1; } } else { int pts_modified; long long original_pts = 0; pts_modified = 0; if ((pQ->H.eAudioFormat_value == AUDIO_FORMAT_AC3) && (pQ->H.eAudioDigitalOutput_value == AUDIO_OUTPUT_STEREO) && (pQ->H.pts_delay_valid == 0)) { unsigned long ac3_status_lo, ac3_status_hi, fscod, frmsizcod; ac3_status_lo = IDecoder_ReadReg (pQ->H.pIDecoder, AUDIO_ac3_status_lo); ac3_status_hi = IDecoder_ReadReg (pQ->H.pIDecoder, AUDIO_ac3_status_hi); fscod = (ac3_status_lo >> 10) & 0x3; frmsizcod = (ac3_status_lo >> 4) & 0x3f; // printk ("fscod: %02x, frmsizcod: %02x\n",// fscod, frmsizcod); if ((fscod <=3) && (frmsizcod < 38) && (ac3_status_hi & 0x8000)) { if (pP->flags) { int bytecounter_offset; if (pP->flags & PTS_AVAILABLE_FLAG) { // XXX assume 48kHz pQ->H.pts_delay = (512*4) / frmsizecod_table[fscod][frmsizcod] * 2880; } else { unsigned long timescale; IDecoderBoard_GetProperty (pQ->H.pIDecoderBoard, TIME_SET, etimAudioCTSTimeScale, 0, ×cale, sizeof(timescale), NULL);// printk ("audioctstimescale = %d\n", (int)timescale); // (256*6/frequency) * timescale = time for 1 ac3 frame if (fscod == 1) { // 44.1khz pQ->H.pts_delay = (512*4) / frmsizecod_table[fscod][frmsizcod] * (timescale*384/11025); } else if (fscod == 2) { // 32khz pQ->H.pts_delay = (512*4) / frmsizecod_table[fscod][frmsizcod] * (timescale*6/125); } else { // 48khz pQ->H.pts_delay = (512*4) / frmsizecod_table[fscod][frmsizcod] * (timescale*4/125); } } bytecounter_offset = (int)(frmsizecod_table[fscod][frmsizcod] << 1); bytecounter_offset = bytecounter_offset - (4096 % bytecounter_offset); if (pQ->H.AudioByteCounter > bytecounter_offset) { pQ->H.pts_delay_valid = 1; if (pMWD->FirstAccessUnitPointer) { pQ->H.pts_delay = 0; pQ->H.AudioByteCounter -= bytecounter_offset; //printk ("bytecounter_offset: %d\n", bytecounter_offset); } } //printk ("ac3 frame length: %d, delay: %d\n", (int)(frmsizecod_table[fscod][frmsizcod] << 1), pQ->H.pts_delay); } } pP->flags = 0; } else if (pP->flags) { pts_modified = 1; original_pts = pMWD->Pts; if (pQ->H.pts_delay_valid) pMWD->Pts -= pQ->H.pts_delay; } rc=(IDecoderBoard_SendAudioPayload(pQ->H.pIDecoderBoard, pMWD, pP->packet.DataLeft, pP->flags, 1,/*bLastPacket: value has meaning here. F.G*/ &pQ->H.AudioByteCounter, &pQ->H.AudioEventPending)==TRUE)?0:-1; if (pts_modified) pMWD->Pts = original_pts; }#else rc = 0; OSCompleteIo (0,pP->packet.pOverlapped);#endif if (rc==0){ pQ->H.AudioEventPending++; #ifdef VERBOSE pQprintk("hwlprivate_feedme:[AUDIO] pP=%p, MWD=%p\n",pP,pMWD);#endif if (pP->flags) { pQ->last_audio_pts_sent = (unsigned long)(pMWD->Pts >> 1); pQ->scr_when_last_audio_pts_was_sent = (unsigned long)(IDecoder_ReadSCR (pQ->H.pIDecoder) >> 1); } /* if (pP->flags) { if (++apts_counter > 20) { unsigned long long pts, scr; apts_counter = 0; pts = pMWD->Pts; scr = IDecoder_ReadSCR (pQ->H.pIDecoder); printk (" apts: 0x%02lx%08lx, scr: 0x%02lx%08lx, bytecounter: %lu, (%ld)\n", (unsigned long)(pts >> 32), (unsigned long)(pts), (unsigned long)(scr >> 32), (unsigned long)(scr), (unsigned long)pQ->H.AudioByteCounter, (long)(pts - scr)); } } */ } return rc; break; case SPU: IDecoderBoard_FreeConsumedData (pQ->H.pIDecoderBoard, SPU, &pQ->H.SpuEventPending); // need to send all spu pts's or else bad things may happen // (Men in Black director's commentary) if (IDecoderBoard_PtsFifoEmptiness(pQ->H.pIDecoderBoard,SPU)==1) return -1; rc=(IDecoderBoard_SendSpuPayload(pQ->H.pIDecoderBoard, pMWD, pP->packet.DataLeft, pP->flags, 1,/*bLastPacket: value has meaning here. F.G*/ &pQ->H.SpuByteCounter, &pQ->H.SpuEventPending)==TRUE)?0:-1; if (rc==0){ pQ->H.SpuEventPending++; #ifdef VERBOSE pQprintk("hwlprivate_feedme:[SPU] pP=%p, MWD=%p\n",pP,pMWD);#endif } return rc; break; case OSD: IDecoderBoard_FreeConsumedData (pQ->H.pIDecoderBoard, OSD, &pQ->H.OsdEventPending); rc=(IDecoderBoard_SendOSDPayload(pQ->H.pIDecoderBoard, pMWD, pP->packet.DataLeft, pP->flags, 1,/*bLastPacket: value has meaning here. F.G*/ &pQ->H.OsdByteCounter, &pQ->H.OsdEventPending)==TRUE)?0:-1; if (rc==0){ pQ->H.OsdEventPending++; #ifdef VERBOSE pQprintk("hwlprivate_feedme:[OSD] pP=%p, MWD=%p\n",pP,pMWD);#endif } return rc; break; default: pQprintk("hwlprivate_feedme: [UNKNOWN] pP=%p, MWD=%p\n",pP,pMWD); break; } return -1;}void hwlprivate_happeningwait(struct quasarprivate *pQ,waitable *h){ long timeout_jiffies=(unsigned long long)h->timeout_microsecond*(unsigned long long)HZ/1000000ULL; unsigned long targets; targets=h->mask&pQ->happening; while (1) { if (targets) { /* clear them. This induces problems when multiple processes are waiting on the same bits, a situation to avoid. */ pQ->happening=pQ->happening&(~targets); h->mask=targets;// pQprintk("hwlprivate_happeningwait: returning 0x%08lx to %d, happening is now 0x%08lx\n",targets,current->pid,pQ->happening); return; } timeout_jiffies=interruptible_sleep_on_timeout(&pQ->happening_queue,timeout_jiffies); // handle signals gently (esp. Control-C...) if ((timeout_jiffies==0)||signal_pending(current)) break; targets=h->mask&pQ->happening; } if (timeout_jiffies!=0) pQprintk("hwlprivate_happeningwait: signal pending\n");// pQprintk("hwlprivate_happeningwait: did not see 0x%08lx, saying timeout to %d\n",h->mask,current->pid); h->mask=0;}int hwlprivate_setproperty(struct quasarprivate *pQ,decoderproperty *pDp){ int rc=-EINVAL;// pQprintk("hwlprivate_setproperty: begun (set %ld,%ld=%p...)\n",pDp->PropSet,pDp->PropId,pDp->pValue); // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // we pend the setting of these properties until a complete osd image is // sent. if we do not do this, we get random osd corruption when this // property is set. if ((pDp->PropSet == VIDEO_SET) && (pDp->PropId == evDestinationWindow)) { QLOCK (); pQ->destination_pending = 1; memcpy (&pQ->destination_wnd, pDp->pValue, sizeof(pQ->destination_wnd)); QUNLOCK (); return 0; } if ((pDp->PropSet == VIDEO_SET) && (pDp->PropId == evInAspectRatio)) { QLOCK (); pQ->aspect_pending = 1; memcpy (&pQ->in_aspect_ratio, pDp->pValue, sizeof(pQ->in_aspect_ratio)); QUNLOCK (); return 0; } if ((pDp->PropSet == VIDEO_SET) && (pDp->PropId == evOutDisplayOption)) { CQuasar *this = (CQuasar*)pQ->H.pIDecoder; Q4SymbolTable *pQ4 = (Q4SymbolTable*)this->pQ; QLOCK (); pQ->display_pending = 1; // init pan scan display (some dvds do not have this information, // so we should init it - patch to fix "bad" dvds - eg. Erin Brokovich // region 2 - danish version) IDecoder_WriteDM (pQ->H.pIDecoder, pQ4->DisplayHorSize.addr, 540); memcpy (&pQ->out_display_option, pDp->pValue, sizeof(pQ->out_display_option)); QUNLOCK (); return 0; } if ((pDp->PropSet == OSD_SET) && (pDp->PropId == eOsdDestinationWindow)) { QLOCK (); pQ->osd_destination_pending = 1; memcpy (&pQ->osd_destination_wnd, pDp->pValue, sizeof(pQ->osd_destination_wnd)); QUNLOCK (); return 0; } if ((pDp->PropSet == VIDEO_SET) && (pDp->PropId == evForcedProgressiveAlways)) { QLOCK (); pQ->forced_progressive_pending = 1; pQ->forced_progressive = *((int *)pDp->pValue); QUNLOCK (); return 0; } if ((pDp->PropSet == DECODER_SET) && (pDp->PropId == edecVideoStd)) { QLOCK (); if (*((int *)pDp->pValue)) pQ->H.is_mpeg4 = 1; else pQ->H.is_mpeg4 = 0; QUNLOCK (); } // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // it seems that after you set the hdtv parameters (evCustomHdtvParams) // you can never go back to tv mode using properties // here is a hack to allow this // XXX see with aurelia if ((pDp->PropSet == VIDEO_SET) && (pDp->PropId == evOutputDevice)) { evOutputDevice_type *pOutputDevice = (evOutputDevice_type *)pDp->pValue; if (*pOutputDevice == evOutputDevice_TV) { QLOCK (); IDecoderBoard_SetCustomTvHdtv (pQ->H.pIDecoderBoard, 0, 0); QUNLOCK (); } } QLOCK (); rc=(IDecoderBoard_SetProperty(pQ->H.pIDecoderBoard,pDp->PropSet,pDp->PropId,0,pDp->pValue,pDp->PropTypeLength,NULL)==Q_OK)?0:-1; QUNLOCK (); if ((pDp->PropSet==AUDIO_SET) && (pDp->PropId==eAudioFormat)) pQ->H.eAudioFormat_value=*(unsigned long *)pDp->pValue; if ((pDp->PropSet==AUDIO_SET) && (pDp->PropId==eAudioDigitalOutput)) pQ->H.eAudioDigitalOutput_value=*(unsigned long *)pDp->pValue; // pQprintk("hwlprivate_setproperty: done (rc=%d)\n",rc); return rc;}int hwlprivate_getproperty(struct quasarprivate *pQ,decoderproperty *pDp){ int rc=-EINVAL; // avoid logging here; people use getproperty to monitor and get here often ;-)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -