📄 play_vdemux.c
字号:
context.spu_repack_size = 0; context.audio_repack_pts = 0; context.video_repack_pts = 0; context.spu_repack_pts = 0; context.audio_repack_pts_valid = FALSE; context.video_repack_pts_valid = FALSE; context.spu_repack_pts_valid = FALSE; context.audio_first_access_unit_pointer_valid = FALSE; context.audio_first_access_unit_pointer = 0; context.waitForValidAudioPTS = TRUE; context.waitForValidVideoPTS = TRUE; context.ignoreCallback = FALSE; if (demux) { RMvdemuxReset(demux); RMvdemuxSetVideoStream(demux, demux_opt->video_pid, 0); RMvdemuxSetSubpictureStream(demux, demux_opt->spu_subid); RMvdemuxSetAudioStream(demux, demux_opt->audio_pid, demux_opt->audio_subid); } DCCSTCSetSpeed(dcc_info.pStcSource, play_opt->speed_N, play_opt->speed_M); PlaybackStatus = RM_PSM_GetState(context.PSMcontext, &(context.dcc_info)); if ((PlaybackStatus != RM_PSM_Paused) && (PlaybackStatus != RM_PSM_Stopped)) { RMDBGLOG((ENABLE, "setting play state\n")); RM_PSM_SetState(context.PSMcontext, &(context.dcc_info), RM_PSM_Playing); } else PROCESS_KEY(FALSE, TRUE); // the following call will configure the decoders, after that we can 'pause' them err = Play(&context, RM_DEVICES_AUDIO | RM_DEVICES_VIDEO, DCCVideoPlayFwd); RMDBGLOG((ENABLE, "audio module 0x%lx video module 0x%lx\n",context.dcc_info->audio_decoder, context.dcc_info->video_decoder)); if (err != RM_OK) goto exit_with_error; /* do prebufferization only when in playing state */ if (RM_PSM_GetState(context.PSMcontext, &(context.dcc_info)) == RM_PSM_Playing) { Pause(&context, RM_DEVICES_STC | RM_DEVICES_VIDEO | RM_DEVICES_AUDIO); RM_PSM_SetState(context.PSMcontext, &(context.dcc_info), RM_PSM_Prebuffering); fprintf(stderr, "prebuffering\n"); } /* wake up disks if necessary */ switch (play_opt->disk_ctrl_state) { case DISK_CONTROL_STATE_DISABLE: case DISK_CONTROL_STATE_RUNNING: break; case DISK_CONTROL_STATE_SLEEPING: if(play_opt->disk_ctrl_callback && play_opt->disk_ctrl_callback(DISK_CONTROL_ACTION_RUN) == RM_OK) play_opt->disk_ctrl_state = DISK_CONTROL_STATE_RUNNING; break; } while (1) { // additionnal while to handle commands issued during EOSWait RMuint32 total = 0; while (1) { RMuint32 count; RMstatus status; PROCESS_KEY(FALSE, TRUE); if (demux_opt->repack_sample) { buf = repack_buf; } else { if (buf) { RMDBGLOG((ENABLE, "******************** unreleased buffer found!\n")); RUAReleaseBuffer(pDMA, buf); buf = NULL; } get_buffer: switch (play_opt->disk_ctrl_state) { case DISK_CONTROL_STATE_DISABLE: case DISK_CONTROL_STATE_SLEEPING: break; case DISK_CONTROL_STATE_RUNNING: if (dmabuffer_index > 0) { dmabuffer_index--; buf = dmabuffer_array[dmabuffer_index]; goto fill_buffer; } break; } while (RUAGetBuffer(pDMA, &buf, GETBUFFER_TIMEOUT_US) != RM_OK) { //RMDBGLOG((ENABLE, "\t\t****************get buffer failed!\n")); check_prebuf_state(&context, 0); switch (play_opt->disk_ctrl_state) { case DISK_CONTROL_STATE_DISABLE: case DISK_CONTROL_STATE_SLEEPING: break; case DISK_CONTROL_STATE_RUNNING: if(play_opt->disk_ctrl_callback && play_opt->disk_ctrl_callback(DISK_CONTROL_ACTION_SLEEP) == RM_OK) play_opt->disk_ctrl_state = DISK_CONTROL_STATE_SLEEPING; break; } PROCESS_KEY(FALSE, TRUE); } } check_prebuf_state(&context, (RMuint32) (1<<(play_opt->dmapool_log2size)));// fprintf( stderr, "prebuf_max 0x%x prebuffered bytes 0x%x dampoollog2size %d\n", (int)play_opt->prebuf_max, (int)context.prebufferedBytes, (int)play_opt->dmapool_log2size); switch (play_opt->disk_ctrl_state) { case DISK_CONTROL_STATE_DISABLE: case DISK_CONTROL_STATE_RUNNING: break; case DISK_CONTROL_STATE_SLEEPING: dmabuffer_array[dmabuffer_index] = buf; dmabuffer_index ++; if (dmabuffer_index + play_opt->disk_ctrl_low_level >= play_opt->dmapool_count) { if(play_opt->disk_ctrl_callback && play_opt->disk_ctrl_callback(DISK_CONTROL_ACTION_RUN) == RM_OK) play_opt->disk_ctrl_state = DISK_CONTROL_STATE_RUNNING; } goto get_buffer; } fill_buffer: if (RM_PSM_GetState(context.PSMcontext, &(context.dcc_info)) == RM_PSM_IRewind) { RMint64 position; RMuint64 seekto; if (!trickSizeToSend) { trickSizeToSend = (RMuint32) (context.file_size / (play_opt->duration / 500)); //there are roughly 2 iframes per second trickBuffersToSend = trickSizeToSend >> play_opt->dmapool_log2size; RMDBGLOG((ENABLE, "size %llu, duration %lu s, iframeSize %lu, buffers %lu (of %lu bytes)\n", context.file_size, (RMuint32)(play_opt->duration / 1000), trickSizeToSend, trickBuffersToSend, (1<<play_opt->dmapool_log2size))); } if (trickBuffersSent >= trickBuffersToSend) trickBuffersSent = 0; if (trickBuffersSent == 0) { RMGetCurrentPositionOfFile(file, &position); seekto = position - (RMuint64) 2 * trickBuffersToSend * (1<<(play_opt->dmapool_log2size)); RMDBGLOG((ENABLE, "pos %llu, seekto %llu\n", position, seekto)); status = RMSeekFile(file, seekto, RM_FILE_SEEK_START); if (status != RM_OK) { perror("error seeking in rwd trickmode, assume EOS\n"); break; } } status = RMReadFile(file, buf, (1<<play_opt->dmapool_log2size), &count); trickBuffersSent++; RMDBGLOG((ENABLE, "sent buffer %lu\n", trickBuffersSent)); } else { status = RMReadFile(file, buf, (1<<play_opt->dmapool_log2size), &count); { // sometimes the the main thread does not // save enough data for the software demux thread RMuint32 maxretry = 3; RMuint32 i = 0; while( (i < maxretry) && (status == RM_ERRORENDOFFILE) ) { RMDBGLOG((ENABLE, "read file failed, retrying... %d status %d, buf 0x%lx, count %d\n", i, (int)status, buf, count)); sleep( 1 ); status = RMReadFile(file, buf, (1<<play_opt->dmapool_log2size), &count); if( (status != RM_ERRORENDOFFILE) && (status != RM_ERRORREADFILE) ) RMDBGLOG((ENABLE, "succeed, got buffer, status %d, buf 0x%lx, count %d\n", (int)status, buf, count)); ; i ++; PROCESS_KEY(FALSE, TRUE); } } RMDBGLOG((SENDDBG, "Read file fill buffer 0x%lx %lu %lu %lu\n", buf, count, total, file_offset)); trickBuffersSent = 0; } total += count; RMDBGLOG((DISABLE, "bytes read %lu, total %lu\n", count, total)); if (status == RM_ERRORREADFILE) { RMDBGLOG((ENABLE, "Error reading file %d\n", status)); goto cleanup; } if (status == RM_ERRORENDOFFILE) { RMDBGLOG((ENABLE, "End of time shift buffer file, read failed, status %d, buf 0x%lx, count %d\n", (int)status, buf, count)); if (demux_opt->repack_sample) flush_repacked_sample(&context); else { RMDBGLOG((ENABLE, "release a buffer\n")); RUAReleaseBuffer(pDMA, buf); buf = NULL; } goto cleanup; } file_offset += count; if (demux) { RMvdemuxDemux(demux, buf, count); /* check if the user pressed a key when we were processing a callback */ RMDBGLOG((KEYDBG, "after callback\n")); PROCESS_KEY(FALSE, FALSE); } else { RMDBGLOG((ENABLE, "Error demux does not exit !\n" )); goto cleanup; } PROCESS_KEY(TRUE, TRUE); if (!demux_opt->repack_sample) { //RMDBGLOG((ENABLE, "release buffer 0x%lx\n", buf)); RUAReleaseBuffer(pDMA, buf); buf = NULL; } } // while 1 check_prebuf_state(&context, 0); switch (play_opt->disk_ctrl_state) { case DISK_CONTROL_STATE_DISABLE: case DISK_CONTROL_STATE_SLEEPING: break; case DISK_CONTROL_STATE_RUNNING: if(play_opt->disk_ctrl_callback && play_opt->disk_ctrl_callback(DISK_CONTROL_ACTION_SLEEP) == RM_OK) 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); err = WaitForEOS(&context, &actions); { RMuint64 stc; DCCSTCGetTime(dcc_info.pStcSource, &stc, 90000); RMDBGLOG((ENABLE, "Timer duration %llu s\n", stc/90000)); } if (err == RM_KEY_WHILE_WAITING_EOS) { err = RM_OK; PROCESS_KEY(FALSE, FALSE); if ((manutest == TRUE) && (actions.cmd == RM_MANU_QUIT_OK)) { goto cleanup; } } else { break; //EOS } } if (play_opt->loop_count > 0) play_opt->loop_count --; /* if there is another loop, stop devices */ if ((play_opt->loop_count > 0) || (play_opt->waitexit != TRUE) || (play_opt->infinite_loop)) Stop(&context, RM_DEVICES_AUDIO | RM_DEVICES_VIDEO | RM_DEVICES_STC, DCCStopMode_BlackFrame); } while ((play_opt->infinite_loop) || (play_opt->loop_count > 0)); cleanup: error = 0; RMTermExit(); exit_with_error: if( 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'))) ); } if (err != RM_OK) { RMDBGLOG((ENABLE, "exiting due to error %d, %s\n", err, RMstatusToString(err))); error = -1; //exit with error } RMDBGLOG((ENABLE, "closing...\n")); if (repack_buf != NULL) RMFree(repack_buf); if (dmabuffer_index) { RMuint32 i; for (i = 0; i < dmabuffer_index; i++) { RUAReleaseBuffer(pDMA, dmabuffer_array[i]); RMDBGLOG((ENABLE, "released buffer[%lu] @ 0x%08lx\n", i, dmabuffer_array[i])); } RMFree(dmabuffer_array); } if (file) { RMDBGLOG((ENABLE, "closing bitstream %s\n", alt_filename)); RMCloseFile(file); file = NULL; } if (pVideoSource) { RMDBGLOG((ENABLE, "stop video source\n")); err = DCCStopVideoSource(pVideoSource, DCCStopMode_LastFrame); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot stop video decoder %d\n", err)); error = -1; } } if (pAudioSource) { RMDBGLOG((ENABLE, "stop audio source\n")); err = DCCStopAudioSource(pAudioSource); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot stop audio decoder %d\n", err)); error = -1; } } if (dcc_info.pStcSource) { RMDBGLOG((ENABLE, "stop STC\n")); DCCSTCStop(dcc_info.pStcSource); } if (pDMA) { RMDBGLOG((ENABLE, "close DMA pool\n")); err = RUAClosePool(pDMA); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error cannot close dmapool %d\n", err)); error = -1; } } if (context.pReceive) DCCCloseReceive (context.pReceive); err = ReconnectHardwareDemux(); if( RMFAILED(err) ) { RMDBGLOG((ENABLE, "Error in reconnect hardware demux, %d\n", err)); } software_demux_in_action = FALSE; start_time_stamp = 0; start_file_position = 0; RMDBGLOG((ENABLE, ">->->->->->->->->->->->->->->->->->->->->->->->->>> SwtichToHardwareDemux 0x%lx, count %d\n", (void*)Tasks, (int)task_count )); return (void*)error;}//// functions related to hardware demux to software demux switching//void SetupSoftwareDemuxGlobal( struct context_per_task *tasks, RMuint32 taskcount, RMuint32 outputcountpertask ){ Tasks = tasks; task_count = taskcount; output_count_per_task = outputcountpertask; software_demux_in_action = FALSE; start_time_stamp = 0; start_file_position = 0; return;}RMstatus send_disable_output_demux_command(struct RUA *pRUA, RMuint32 demux, struct EMhwlibOutputMask_type *discmd) { struct RUAEvent evt; RMuint32 index; RMstatus err; evt.ModuleID = demux; evt.Mask = RUAEVENT_COMMANDCOMPLETION; err = RUAResetEvent(pRUA, &evt); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot reset demux OutputDisableCommand completion event, %s\n", RMstatusToString(err))); return err; } err = RUASetProperty(pRUA, demux, RMDemuxTaskPropertyID_OutputDisableCommand, discmd, sizeof(struct EMhwlibOutputMask_type), 0); i
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -