play_asf.c
来自「1. 8623L平台」· C语言 代码 · 共 1,567 行 · 第 1/4 页
C
1,567 行
/* software decode wmapro while polling disk ready status, otherwise we might run out of buffer in case buffer size is too small or when spinning up the disk takes too long. probably not necessary in this case, since we are coming from a seek and buffers are flushed anyway */ while (poll_count--) { if (SendContext.play_opt->disk_ctrl_callback(DISK_CONTROL_ACTION_RUN_NOWAIT) == RM_OK) { SendContext.play_opt->disk_ctrl_state = DISK_CONTROL_STATE_RUNNING; break; } asf_try_decode_wmapro(&SendContext, FALSE); PROCESS_KEY(TRUE, TRUE); usleep(TIMEOUT_100MS); } if (SendContext.play_opt->disk_ctrl_state != DISK_CONTROL_STATE_RUNNING) RMDBGLOG((ENABLE, "warning, couldn't wakeup disk in time\n")); } break; } while (1) { // additional 'while' used for taking care of commands issued during EOSWait while(1) { RMuint32 count; /* first, try to fill up the CC fifo */ if (SendContext.bcc_enabled) { bcc_feed(SendContext.pbcc, SendContext.pRUA, SendContext.Preroll); } //asf_try_decode_wmapro(&SendContext, FALSE); //PROCESS_KEY(TRUE); PROCESS_KEY(FALSE, TRUE); update_hdmi(SendContext.dcc_info, SendContext.disp_opt, &(SendContext.audio_opt[0])); /* wake up disks if necessary */ switch (SendContext.play_opt->disk_ctrl_state) { case DISK_CONTROL_STATE_DISABLE: case DISK_CONTROL_STATE_RUNNING: break; case DISK_CONTROL_STATE_SLEEPING: if (SendContext.play_opt->disk_ctrl_callback) { RMuint32 poll_count = DISK_CONTROL_MAX_WAKEUP_COUNT; /* software decode wmapro while polling disk ready status, otherwise we might run out of buffer in case buffer size is too small or when spinning up the disk takes too long. probably not necessary in this case, since we are coming from a seek and buffers are flushed anyway */ while (poll_count--) { if (SendContext.play_opt->disk_ctrl_callback(DISK_CONTROL_ACTION_RUN_NOWAIT) == RM_OK) { SendContext.play_opt->disk_ctrl_state = DISK_CONTROL_STATE_RUNNING; break; } asf_try_decode_wmapro(&SendContext, FALSE); PROCESS_KEY(TRUE, TRUE); usleep(TIMEOUT_100MS); } if (SendContext.play_opt->disk_ctrl_state != DISK_CONTROL_STATE_RUNNING) RMDBGLOG((ENABLE, "warning, couldn't wakeup disk in time\n")); } break; }#ifdef CHECK_BUFFER_4_FREAD { int cWait = 0;#endif get_buffer: switch (SendContext.play_opt->disk_ctrl_state) { case DISK_CONTROL_STATE_DISABLE: case DISK_CONTROL_STATE_SLEEPING: break; case DISK_CONTROL_STATE_RUNNING: if (SendContext.dmabuffer_index > 0) { SendContext.dmabuffer_index--; buffer = SendContext.dmabuffer_array[SendContext.dmabuffer_index]; RMDBGLOG((ENABLE, "fill buffer phase: got buffer %p (index %lu, level %lu, count %lu)\n", buffer, SendContext.dmabuffer_index, SendContext.play_opt->disk_ctrl_low_level, SendContext.play_opt->dmapool_count)); goto fill_buffer; } break; } RMDBGLOG((DISABLE, "try to RUAGetBuffer. AvailableBufferCount= %ld\n", RUAGetAvailableBufferCount(SendContext.pDMA))); while(RUAGetBuffer(SendContext.pDMA, &buffer, GETBUFFER_TIMEOUT_US) != RM_OK) { /*RMbool gotKey;*/ asf_check_prebuf_state(&SendContext, 0);#ifdef CHECK_BUFFER_4_FREAD cWait ++;#endif switch (SendContext.play_opt->disk_ctrl_state) { case DISK_CONTROL_STATE_DISABLE: case DISK_CONTROL_STATE_SLEEPING: break; case DISK_CONTROL_STATE_RUNNING: if(SendContext.play_opt->disk_ctrl_callback && SendContext.play_opt->disk_ctrl_callback(DISK_CONTROL_ACTION_SLEEP) == RM_OK) SendContext.play_opt->disk_ctrl_state = DISK_CONTROL_STATE_SLEEPING; break; } asf_try_decode_wmapro(&SendContext, FALSE); PROCESS_KEY(FALSE, TRUE); update_hdmi(SendContext.dcc_info, SendContext.disp_opt, &(SendContext.audio_opt[0])); }#ifdef CHECK_BUFFER_4_FREAD if(cWait>0)printf("FRead wait: %d\n", cWait); }#endif #if (EM86XX_MODE == EM86XX_MODEID_STANDALONE) && (EM86XX_CHIP != EM86XX_CHIPID_TANGO2) buffer = (RMuint8 *)((RMuint32)buffer & 0x7fffffff);#endif asf_check_prebuf_state(&SendContext, (1 << SendContext.play_opt->dmapool_log2size)); switch (SendContext.play_opt->disk_ctrl_state) { case DISK_CONTROL_STATE_DISABLE: case DISK_CONTROL_STATE_RUNNING: break; case DISK_CONTROL_STATE_SLEEPING: SendContext.dmabuffer_array[SendContext.dmabuffer_index] = buffer; SendContext.dmabuffer_index ++; if (SendContext.dmabuffer_index + SendContext.play_opt->disk_ctrl_low_level >= SendContext.play_opt->dmapool_count) { if (SendContext.play_opt->disk_ctrl_callback) { RMuint32 poll_count = DISK_CONTROL_MAX_WAKEUP_COUNT; /* software decode wmapro while polling disk ready status, otherwise we might run out of buffer in case buffer size is too small or when spinning up the disk takes too long */ while (poll_count--) { if (SendContext.play_opt->disk_ctrl_callback(DISK_CONTROL_ACTION_RUN_NOWAIT) == RM_OK) { SendContext.play_opt->disk_ctrl_state = DISK_CONTROL_STATE_RUNNING; break; } asf_try_decode_wmapro(&SendContext, FALSE); PROCESS_KEY(TRUE, TRUE); usleep(TIMEOUT_100MS); } if (SendContext.play_opt->disk_ctrl_state != DISK_CONTROL_STATE_RUNNING) RMDBGLOG((ENABLE, "warning, couldn't wakeup disk in time\n")); } } RMDBGLOG((ENABLE, "recycle buffer phase: got buffer %p (index %lu, level %lu, count %lu)\n", buffer, SendContext.dmabuffer_index, SendContext.play_opt->disk_ctrl_low_level, SendContext.play_opt->dmapool_count)); goto get_buffer; } fill_buffer: err = readBitstream(&SendContext, buffer, &count); if (err == RM_OK) { rc = RMASFVDemuxDEMUX(SendContext.vASFDemux,buffer, count); } else if (err == RM_EOS) { RMDBGLOG((ENABLE, "wait for eos\n")); if (buffer != NULL) RUAReleaseBuffer(SendContext.pDMA, buffer); break; } else if (err == RM_SKIP_DATA) { RMint64 currentTime; RMuint64 stc; //get the time in 1000th units because presentation time from ASF is always in 1/1000 //!!! the above assumption might be wrong see #5529, however it doesnt change this routine DCCSTCGetTime(SendContext.dcc_info->pStcSource, &stc, 1000); currentTime = (RMuint64)stc; if ((currentTime > (RMint64)SendContext.lastSTC + 1000) || (currentTime < (RMint64)SendContext.lastSTC - 1000)) { SendContext.lastSTC = stc; RMDBGLOG((ENABLE, "time = %llu/%llu (%ld/100)\n", currentTime, SendContext.Duration, (currentTime * 100) / SendContext.Duration)); } if (currentTime > (RMint64)SendContext.Duration) { RMDBGLOG((ENABLE, "currentTime > duration!\n")); goto signal_eos; break; } else if (currentTime <= 0) { RMDBGLOG((ENABLE, "currentTime <= 0\n")); goto signal_eos; break; } usleep(100000); // to prevent high CPU usage } else if (err == RM_DRM_DECRYPTION_FAILED) { RMDBGLOG((ENABLE, "decrytion error, abort\n")); if (buffer != NULL) RUAReleaseBuffer(SendContext.pDMA, buffer); goto exit_with_error; } else if (err == RM_ERRORENDOFFILE) { RMDBGLOG((ENABLE, "EOF %s (%ld), wait for eos\n", RMstatusToString(err), err)); if (buffer != NULL) RUAReleaseBuffer(SendContext.pDMA, buffer); break; } else { RMDBGLOG((ENABLE, "error %s (%ld), exit\n", RMstatusToString(err), err)); if (buffer != NULL) RUAReleaseBuffer(SendContext.pDMA, buffer); goto exit_with_error; } if (buffer != NULL) { RMDBGLOG((RELEASE_BUFFER_ENABLE, "Releasing buffer %p\n", buffer)); RUAReleaseBuffer(SendContext.pDMA, buffer); buffer = NULL; }#if 0 /* TODO: This code should use multiple audio. Get profiling value */ { RMreal profile; err = RUAGetProperty(SendContext.pRUA, SendContext.dcc_info->audio_decoder, RMGenericPropertyID_Profile, &profile, sizeof(profile)); if (err == RM_OK) { printf("Audio DSP Usage = %02.2f%%\n", profile); } }#endif /* check if the user pressed a key when we were processing a callback */ RMDBGLOG((DISABLE, "process_key after demuxing, actions 0x%lx toDo 0x%lx\n", SendContext.actions.cmd, SendContext.actions.toDoActions)); PROCESS_KEY(TRUE, FALSE); update_hdmi(SendContext.dcc_info, SendContext.disp_opt, &(SendContext.audio_opt[0])); { asf_try_decode_wmapro(&SendContext, FALSE); PROCESS_KEY(TRUE, TRUE); } } asf_check_prebuf_state(&SendContext, 0); switch (SendContext.play_opt->disk_ctrl_state) { case DISK_CONTROL_STATE_DISABLE: case DISK_CONTROL_STATE_SLEEPING: break; case DISK_CONTROL_STATE_RUNNING: if(SendContext.play_opt->disk_ctrl_callback && SendContext.play_opt->disk_ctrl_callback(DISK_CONTROL_ACTION_SLEEP) == RM_OK) SendContext.play_opt->disk_ctrl_state = DISK_CONTROL_STATE_SLEEPING; break; } // in case we're still in pause state, wait for a key PROCESS_KEY(FALSE, TRUE); check_wmapro_fifo_emptiness_on_eos: if (!RMfifo_is_empty(SendContext.wmapro_fifo)) { RMDBGLOG((ENABLE, "WMAPRO FIFO is not empty before EOS\n")); asf_try_decode_wmapro(&SendContext, TRUE); PROCESS_KEY(TRUE, TRUE); goto check_wmapro_fifo_emptiness_on_eos; } fprintf(stderr, "File ready %ld times, waiting for EOS\n", NTimes+1); err = asf_WaitForEOS(&SendContext, &SendContext.actions); { RMuint64 stc; DCCSTCGetTime(dcc_info.pStcSource, &stc, SendContext.video_vop_tir); RMDBGLOG((ENABLE, "Timer duration %llu ms, Header Duration %llu ms\n", stc, SendContext.Duration)); } if (err == RM_KEY_WHILE_WAITING_EOS) { err = RM_OK; PROCESS_KEY(FALSE, FALSE); continue; } else { if ((SendContext.isIFrameMode) && (SendContext.IFrameDirection < 0) && 0) goto wmapro_decoder_delete; else { signal_eos:#ifdef WITH_MONO /* callback to signal EOS to curacao/mono */ RMEOSCallback(); /* process any command that might be issued after an EOS signalling */ PROCESS_KEY(FALSE, TRUE); /* after processing the key, if we are still here, proceed with EOS */#endif break; // EOS } } } if (SendContext.play_opt->loop_count > 0) SendContext.play_opt->loop_count --;wmapro_decoder_delete: if (SendContext.vDecoder != (void *)NULL) { RMDBGLOG((ENABLE, "closing wmaprodecoder\n")); RMWMAProVDecoderClose(SendContext.vDecoder); RMDeleteWMAProVDecoder(SendContext.vDecoder); SendContext.vDecoder = (void *)NULL; asf_flush_wmaproFIFO(&SendContext); } NTimes++; /* if there is another loop, stop devices */ if ((SendContext.play_opt->loop_count > 0) || (SendContext.play_opt->waitexit != TRUE) || (SendContext.play_opt->infinite_loop)) asf_Stop(&SendContext, RM_DEVICES_STC | RM_DEVICES_AUDIO | RM_DEVICES_VIDEO); } while ((SendContext.play_opt->infinite_loop) || (SendContext.play_opt->loop_count > 0)); cleanup: error = 0; //normal exit exit_with_error: if( SendContext.play_opt->waitexit ) { RMascii key; fprintf(stderr, "press q key again if you really want to stop & quit\n"); while ( !(RMGetKeyNoWait(&key) && ((key == 'q') || (key =='Q'))) ); asf_Stop(&SendContext, RM_DEVICES_STC); asf_Stop(&SendContext, RM_DEVICES_STC | RM_DEVICES_AUDIO | RM_DEVICES_VIDEO); } if (err != RM_OK) { fprintf(stderr, "quitting due to error %s (%d)...\n", RMstatusToString(err), err); error = err; //exit with error } RMDBGLOG((ENABLE, "closing...\n")); if(asf_close(&SendContext, wmapro_fifo_buffer_original, dtcpCookieHandle) != RM_OK) { fprintf(stderr, "ERROR WHILE CLOSING\n"); } if (error) RMDBGLOG((ENABLE, "exiting with error %s (%d)\n", RMstatusToString(error), error)); return error;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?