📄 play_asf.c
字号:
RMuint32 prev_MON_V; RMuint32 nb_bytes_since_prev_timeV; RMuint32 byteRateV; RMuint32 maxByteRateV;#endif /* #### Begin CARDEA code #### */ void * cardea_context; RMuint8 sample_id[8]; /* #### End CARDEA code #### */ RMbool fDecodingWMAPROPacket; struct RMfifo *wmapro_fifo; struct wmapro_buffer_info *pread_wmapro_info; RMbool bcc_enabled; struct bcc *pbcc; RMuint32 prebufferedBytes; // for VC1 RMuint8 *seqHeader; RMuint32 seqHeaderSize; RMbool addSeqHeader; RMbool addEntryHeader; RMbool addFrameHeader; RMuint8 *entryHeader; RMuint32 entryHeaderSize; RMbool isVC1; RMbool getStartCodeBuffer; RMuint8 *startCodeBuffer; RMuint32 startCodeBufferSize; RMuint32 startCodeBufferLeft; // to allow sending audio when in trickmodes RMbool sendAudioTrickmode; RMbool monitorFIFOs; struct timeval last; RMbool bypass_drm; RMbool linear_playback; RMuint32 audioStreams; RMuint32 audioStreamTable[10]; RMuint32 audioInstances; struct video_cmdline *video_opt; struct display_cmdline *disp_opt; struct audio_cmdline *audio_opt; struct playback_cmdline *play_opt;#ifndef WITH_MONO struct display_context disp_info;#endif struct priv_cmdline priv_opt; struct RM_PSM_Actions actions; struct stream_info stream_table[4]; RMuint64 lastVideoPTS; void **dmabuffer_array; RMuint32 dmabuffer_index; RMbool audioSamplesDropped; RMstatus audioSetupStatus; RMstatus videoSetupStatus; enum RMProcess_key_goto gotoRequest; RMuint64 stc_offset_ms;};/* prototypes */static RMstatus Stop(struct asf_context *pSendContext, RMuint32 devices);static RMstatus Play(struct asf_context * pSendContext, RMuint32 devices, enum DCCVideoPlayCommand mode);static RMstatus setup_video_decoder(struct asf_context *pSendContext);static RMstatus setup_audio_decoder(struct asf_context *pSendContext);static RMstatus SyncTimerWithDecoderPTS(struct asf_context *pSendContext);static RMstatus restartAudioDecoder(struct asf_context * pSendContext);static void flush_wmaproFIFO(struct asf_context *pSendContext);static RMuint64 round_int_div(RMuint64 numerator, RMuint32 divisor);static RMstatus asf_FastAudioRecovery(struct asf_context * pSendContext);static RMstatus asf_ResumeFromIFrameTrickMode(struct asf_context * pSendContext);static RMstatus asf_seek(struct asf_context * pSendContext, RMuint64 time);static RMstatus asf_InitIFrameTrickMode(struct asf_context* pSendContext);#define GET_DATA_FIFO_INFO(pRUA, ModuleId) \ { \ struct DataFIFOInfo DataFIFOInfo; \ RMuint32 fullness; \ RUAGetProperty(pRUA, ModuleId, RMGenericPropertyID_DataFIFOInfo, &DataFIFOInfo, sizeof(DataFIFOInfo)); \ fullness = (100*DataFIFOInfo.Readable)/DataFIFOInfo.Size; \ fprintf(stderr, "Data %lx: st=%08lx sz=%ld wr=%ld rd=%ld --> f : %lu/100\n", ModuleId, DataFIFOInfo.StartAddress, \ DataFIFOInfo.Size, DataFIFOInfo.Writable, DataFIFOInfo.Readable, fullness); \ } \#define GET_XFER_FIFO_INFO(pRUA, ModuleId) \ { \ struct XferFIFOInfo_type XferFIFOInfo; \ RMuint32 fullness; \ RUAGetProperty(pRUA, ModuleId, RMGenericPropertyID_XferFIFOInfo, &XferFIFOInfo, sizeof(XferFIFOInfo)); \ fullness = (100*XferFIFOInfo.Readable)/XferFIFOInfo.Size; \ fprintf(stderr, "XFER %lx: st=%08lx sz=%ld wr=%ld rd=%ld er=%lx --> f : %lu/100\n", ModuleId, XferFIFOInfo.StartAddress, \ XferFIFOInfo.Size, XferFIFOInfo.Writable, XferFIFOInfo.Readable, XferFIFOInfo.Erasable, fullness); \ }#define GET_XFER_FIFO_BYTES_QUEUED(pRUA, ModuleId) \ { \ RMuint32 bytes_queued; \ RUAGetProperty(pRUA, ModuleId, RMGenericPropertyID_XferFIFOBytesQueued, &bytes_queued, sizeof(bytes_queued)); \ fprintf(stderr, "XFER %lx: %lu\n", ModuleId, bytes_queued); \ }#define MONITOR_FIFO_INTERVAL_US 250000static void monitorFIFO(struct asf_context *context, RMbool alwaysShow){ struct timeval now; RMint32 elapsed; RMuint64 ptime; struct dcc_context *dcc_info = context->dcc_info; gettimeofday(&now, NULL); elapsed = (now.tv_sec - context->last.tv_sec) * 1000000; elapsed += (now.tv_usec - context->last.tv_usec); if (elapsed > MONITOR_FIFO_INTERVAL_US || alwaysShow){ DCCSTCGetTime(dcc_info->pStcSource, &ptime, 90000); fprintf(stderr, "\n*****************************\n"); fprintf(stderr, "STC = %lld (%lld secs) \n", ptime, (ptime/90000)); /* sample code to get fifo info */ if (dcc_info->pVideoSource) { fprintf(stderr, "Video :\n"); GET_DATA_FIFO_INFO(dcc_info->pRUA, dcc_info->video_decoder); GET_XFER_FIFO_INFO(dcc_info->pRUA, dcc_info->video_decoder); GET_XFER_FIFO_BYTES_QUEUED(dcc_info->pRUA, dcc_info->video_decoder); } if (dcc_info->pMultipleAudioSource) { struct DCCAudioSourceHandle audioHandle; RMuint32 i; for (i = 0; i < context->audioInstances; i++) { fprintf(stderr, "Audio[%lu] :\n", i); DCCMultipleAudioSourceGetSingleDecoderHandleForInstance(dcc_info->pMultipleAudioSource, i, &audioHandle); GET_DATA_FIFO_INFO(dcc_info->pRUA, audioHandle.moduleID); GET_XFER_FIFO_INFO(dcc_info->pRUA, audioHandle.moduleID); GET_XFER_FIFO_BYTES_QUEUED(dcc_info->pRUA, audioHandle.moduleID); } } fprintf(stderr, "*****************************\n"); gettimeofday(&context->last, NULL); fflush(stderr); } return;}static enum RMProcess_key_goto process_key_sub(struct asf_context *pProcessContext,RMuint8 release,RMuint8 getkey,RMuint8 incallback,RMuint32 dataType){ RMuint32 i; RMstatus err; RMuint32 dummy; RMuint8 *buffer = (RMuint8*)&dummy; enum RM_PSM_State OldPlaybackState = RM_PSM_GetState(pProcessContext->PSMcontext, &(pProcessContext->dcc_info)); enum RM_PSM_State PlaybackStatus = RM_PSM_GetState(pProcessContext->PSMcontext, &(pProcessContext->dcc_info)); RMuint8 got_key=0; if (getkey) { if ((OldPlaybackState == RM_PSM_Stopped) || (OldPlaybackState == RM_PSM_Paused)) { switch (pProcessContext->play_opt->disk_ctrl_state) { case DISK_CONTROL_STATE_DISABLE: case DISK_CONTROL_STATE_SLEEPING: break; case DISK_CONTROL_STATE_RUNNING: if(pProcessContext->play_opt->disk_ctrl_callback && pProcessContext->play_opt->disk_ctrl_callback(DISK_CONTROL_ACTION_SLEEP) == RM_OK) pProcessContext->play_opt->disk_ctrl_state = DISK_CONTROL_STATE_SLEEPING; break; } } RMDBGLOG((KEYDBG, "process_key\n")); err = process_command(pProcessContext->PSMcontext, &(pProcessContext->dcc_info), &pProcessContext->actions); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error while processing key %d\n", err)); return RMProcess_key_goto_cleanup; } if ((pProcessContext->actions.performedActions) || (pProcessContext->actions.toDoActions) || (pProcessContext->actions.cmd != RM_NONE)) got_key=1; } if (pProcessContext->actions.toDoActions & RM_PSM_RESYNC_TIMER) { RMDBGLOG((ENABLE, "resyncTimer\n")); SyncTimerWithDecoderPTS(pProcessContext); pProcessContext->actions.toDoActions &= ~RM_PSM_RESYNC_TIMER; } if (pProcessContext->actions.toDoActions & RM_PSM_FLUSH_VIDEO) { RMDBGLOG((ENABLE, "flushVIDEO\n")); Stop(pProcessContext, RM_DEVICES_VIDEO); pProcessContext->actions.toDoActions &= ~RM_PSM_FLUSH_VIDEO; } if (pProcessContext->actions.toDoActions & RM_PSM_DEMUX_NORMAL) { RMDBGLOG((ENABLE, "demuxNormal\n")); if (RMFAILED(asf_ResumeFromIFrameTrickMode(pProcessContext))) { RMDBGLOG((ENABLE,"Error during resume from trickmode, abort.\n")); return RMProcess_key_goto_cleanup; } pProcessContext->isIFrameMode = FALSE; pProcessContext->actions.toDoActions &= ~RM_PSM_DEMUX_NORMAL; } if (pProcessContext->actions.toDoActions & RM_PSM_DEMUX_IFRAME) { RMDBGLOG((ENABLE, "demuxIFrame\n")); if (release) { if (buffer != NULL) { RMDBGLOG((ENABLE, "release a buffer\n")); RUAReleaseBuffer(pProcessContext->pDMA, buffer); buffer = NULL; } else RMDBGLOG((ENABLE, "no buffer to release\n")); } if (RMFAILED(asf_InitIFrameTrickMode(pProcessContext))) { RMDBGLOG((ENABLE,"Error during init trickmode, abort.\n")); return RMProcess_key_goto_cleanup; } pProcessContext->isIFrameMode = TRUE; pProcessContext->ignoreCallback = FALSE; pProcessContext->actions.toDoActions &= ~RM_PSM_DEMUX_IFRAME; } if (pProcessContext->actions.toDoActions & RM_PSM_FIRST_PTS) { RMDBGLOG((ENABLE, "firstPTS\n")); /*pProcessContext->FirstSystemTimeStamp = TRUE;*/ pProcessContext->actions.toDoActions &= ~RM_PSM_FIRST_PTS; } if (pProcessContext->actions.toDoActions & RM_PSM_NORMAL_PLAY) { RMDBGLOG((ENABLE, "normal play\n")); if ((pProcessContext->audio_parameters[pProcessContext->audio_stream_index].enabled) && (pProcessContext->AudioStreamFound) && (pProcessContext->sendAudioTrickmode)) { RMDBGLOG((ENABLE, "******* reset audio timer routing\n")); routeAudioTimerToDisplayPTS(pProcessContext->dcc_info, FALSE); unMuteAudio(pProcessContext->dcc_info); } if ((pProcessContext->play_opt->fast_audio_recovery) && (pProcessContext->VideoStreamFound) && !(pProcessContext->linear_playback)) asf_FastAudioRecovery(pProcessContext); pProcessContext->actions.toDoActions &= ~RM_PSM_NORMAL_PLAY; } \ if (pProcessContext->actions.performedActions & RM_PSM_VIDEO_STOPPED) { RMDBGLOG((ENABLE, "video stopped\n")); pProcessContext->video_decoder_initialized = FALSE; if (pProcessContext->isVC1) { RMDBGLOG((ENABLE, "codec: VC1 Advanced Profile, will add seqHeader to bitstream\n")); pProcessContext->addSeqHeader = TRUE; } pProcessContext->actions.performedActions &= ~RM_PSM_VIDEO_STOPPED; } if (pProcessContext->actions.performedActions & RM_PSM_AUDIO_STOPPED) { RMDBGLOG((ENABLE, "audio stopped\n")); Stop(pProcessContext, RM_DEVICES_AUDIO); pProcessContext->actions.performedActions &= ~RM_PSM_AUDIO_STOPPED; } if (pProcessContext->actions.performedActions & RM_PSM_STC_STOPPED) { RMDBGLOG((ENABLE, "stc stopped\n")); pProcessContext->actions.performedActions &= ~RM_PSM_STC_STOPPED; } if ((pProcessContext->actions.cmd == RM_QUIT) && (!pProcessContext->actions.cmdProcessed)) { RMDBGLOG((ENABLE, "got quit\n")); pProcessContext->ignoreCallback = FALSE; pProcessContext->actions.cmdProcessed = TRUE; if (incallback) pProcessContext->ignoreCallback = TRUE; return RMProcess_key_goto_cleanup; } if ((!pProcessContext->audio_decoder_initialized) && (OldPlaybackState != RM_PSM_Playing) && (RM_PSM_GetState(pProcessContext->PSMcontext, &(pProcessContext->dcc_info)) == RM_PSM_Playing)) { RMDBGLOG((ENABLE, "restart audio decoder due to play\n")); restartAudioDecoder(pProcessContext); RMDBGLOG((ENABLE, "syncTimer\n")); SyncTimerWithDecoderPTS(pProcessContext); if ((pProcessContext->AudioStreamFound) && (!pProcessContext->VideoStreamFound)) return RMProcess_key_goto_mainloop_seek; } if ((RM_PSM_GetState(pProcessContext->PSMcontext, &(pProcessContext->dcc_info)) == RM_PSM_Stopped) && (pProcessContext->actions.cmdProcessed)) { RMDBGLOG((ENABLE,"Got stop command\n")); pProcessContext->ignoreCallback = FALSE; pProcessContext->isIFrameMode = FALSE; pProcessContext->video_decoder_initialized = FALSE; pProcessContext->audio_decoder_initialized = FALSE; pProcessContext->FirstSystemTimeStamp = TRUE; if (incallback) pProcessContext->ignoreCallback = TRUE; return RMProcess_key_goto_wmapro_decoder_delete; } \ if ((pProcessContext->actions.cmd == RM_STOP_SEEK_ZERO) && (!pProcessContext->actions.cmdProcessed)) { RMDBGLOG((ENABLE,"Got stop seek zero command\n")); if (release) { if (buffer != NULL) { RMDBGLOG((ENABLE, "release a buffer\n")); RUAReleaseBuffer(pProcessContext->pDMA, buffer); buffer = NULL; } else RMDBGLOG((ENABLE, "no buffer to release\n")); } Stop(pProcessContext, RM_DEVICES_STC | RM_DEVICES_AUDIO | RM_DEVICES_VIDEO); RM_PSM_SetState(pProcessContext->PSMcontext, &(pProcessContext->dcc_info), RM_PSM_Stopped); pProcessContext->ignoreCallback = FALSE; pProcessContext->isIFrameMode = FALSE; pProcessContext->video_decoder_initialized = FALSE; pProcessContext->audio_decoder_initialized = FALSE; pProcessContext->FirstSystemTimeStamp = TRUE; pProcessContext->actions.cmdProcessed = TRUE; if (incallback) pProcessContext->ignoreCallback = TRUE; return RMProcess_key_goto_wmapro_decoder_delete; } if ((pProcessContext->actions.cmd == RM_SEEK) && (!pProcessContext->actions.cmdProcessed)){ RMDBGLOG((ENABLE,"Got seek command\n")); if (release) { if (buffer != NULL) { RMDBGLOG((ENABLE, "release a buffer\n")); RUAReleaseBuffer(pProcessContext->pDMA, buffer); buffer = NULL; } else RMDBGLOG((ENABLE, "no buffer to release\n")); } if (RMFAILED(asf_seek(pProcessContext, pProcessContext->dcc_info->seek_time))) { RMDBGLOG((ENABLE,"Error during seek, abort.\n")); return RMProcess_key_goto_cleanup; } RM_PSM_SetState(pProcessContext->PSMcontext, &(pProcessContext->dcc_info), RM_PSM_Playing); DCCSTCSetSpeed(pProcessContext->dcc_info->pStcSource, pProcessContext->play_opt->speed_N, pProcessContext->play_opt->speed_M); pProcessContext->ignoreCallback = FALSE; pProcessContext->isIFrameMode = FALSE; pProcessContext->actions.cmdProcessed = TRUE; if (incallback) pProcessContext->ignoreCallback = TRUE; return RMProcess_key_goto_mainloop_seek; } if ((pProcessContext->actions.cmd == RM_DUALMODE_CHANGE) && (!pProcessContext->actions.cmdProcessed)) { fprintf(stderr, "Changing DualMode to :"); switch(pProcessContext->audio_opt[0].OutputDualMode) { case DualMode_LeftMono: fprintf(stderr, " RightMono\n"); pProcessContext->audio_opt[0].OutputDualMode = DualMode_RightMono; break; case DualMode_RightMono: fprintf(stderr, " MixMono\n"); pProcessContext->audio_opt[0].OutputDualMode = DualMode_MixMono; break; case DualMode_MixMono: fprintf(stderr, " Stereo\n"); pProcessContext->audio_opt[0].OutputDualMode = DualMode_Stereo; break; case DualMode_Stereo: fprintf(stderr, " LeftMono\n"); pProcessContext->audio_opt[0].OutputDualMode = DualMode_LeftMono; break; default: fprintf(stderr, " Unknown dual mode\n"); break; } for (i=0; i < pProcessContext->audioInstances; i++) { pProcessContext->audio_opt[i].OutputDualMode = pProcessContext->audio_opt[0].OutputDualMode;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -