📄 play_model3_video.c
字号:
&video_profile.Profile, &video_profile.Level, &video_profile.ExtraPictureBufferCount, &video_profile.MaxWidth, &video_profile.MaxHeight); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Unknown video decoder codec \n")); goto cleanup; } } video_profile.ExtraPictureBufferCount = video_opt->vcodec_extra_pictures; err = DCCXOpenVideoDecoderSource(dcc_info.pDCC, &video_profile, &pVideoSource); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot open video decoder %d\n", err)); goto cleanup; } #ifdef ABCDRM_MODEL3 { RMuint32 BtsFIFO; err = DCCXGetBtsFIFO(pVideoSource, &BtsFIFO); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot get the BtsFIFO address, %s\n", RMstatusToString(err))); goto cleanup; } err = start_abcdrm(dcc_info.pRUA, BtsFIFO); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot start the ABCDRM shared library and xtask\n")); goto cleanup; } }#endif // ABCDRM_MODEL3 vcodec = video_profile.Codec; err = DCCXSetVideoDecoderSourceCodec(pVideoSource, vcodec); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot set video decoder codec %d\n", err)); goto cleanup; } } err = DCCGetScalerModuleID(dcc_info.pDCC, dcc_info.route, DCCSurface_Video, videoscaler_id, &(dcc_info.SurfaceID)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot get surface to display video source %d\n", err)); goto cleanup; } err = DCCSetSurfaceSource(dcc_info.pDCC, dcc_info.SurfaceID, pVideoSource); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot set the surface source %d\n", err)); goto cleanup; } err = DCCGetVideoDecoderSourceInfo(pVideoSource, &(dcc_info.video_decoder), &(dcc_info.spu_decoder), &(dcc_info.video_timer)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error getting video decoder source information %d\n", err)); goto cleanup; } dcc_info.pVideoSource = pVideoSource; dcc_info.state = (play_opt->start_pause) ? RM_PAUSED : RM_PLAYING; dcc_info.trickmode_id = RM_NO_TRICKMODE; dcc_info.seek_supported = FALSE; dcc_info.iframe_supported = FALSE; // apply the fixed vop rate if required err = apply_video_decoder_options(&dcc_info, video_opt); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error applying video_decoder_options %d\n", err)); goto cleanup; } set_default_out_window(&(dcc_info.disp_info->out_window)); set_default_out_window(&(dcc_info.disp_info->osd_window[0])); set_default_out_window(&(dcc_info.disp_info->osd_window[1])); dcc_info.disp_info->active_window = &(dcc_info.disp_info->out_window); dcc_info.disp_info->video_enable = TRUE; err = apply_display_options(&dcc_info, disp_opt); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot set display options %d\n", err)); goto cleanup; } display_key_usage(KEYFLAGS); /* dmapool must be created after the module open in case we do no copy transfers */ err = RUAOpenPool(dcc_info.pRUA, 0/*dcc_info.video_decoder*/, DMA_BUFFER_COUNT, DMA_BUFFER_SIZE_LOG2, RUA_POOL_DIRECTION_SEND, &pDMA); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error cannot open dmapool %d\n", err)); goto cleanup; } context.pDMA = pDMA; file = open_stream(play_opt->filename, RM_FILE_OPEN_READ, 0); if (file == NULL) { RMDBGLOG((ENABLE, "Cannot open file %s\n", play_opt->filename)); goto cleanup; } context.f_bitstream = file; RMSizeOfOpenFile(file, &context.fileSize); RMDBGLOG((ENABLE, "file: %s, size %llu, duration %llu s \n", play_opt->filename, context.fileSize, play_opt->duration / 1000)); dcc_info.RM_PSM_commands = RM_PSM_ENABLE_PLAY; dcc_info.RM_PSM_commands |= RM_PSM_ENABLE_STOP; dcc_info.RM_PSM_commands |= RM_PSM_ENABLE_PAUSE; dcc_info.RM_PSM_commands |= RM_PSM_ENABLE_SPEED; dcc_info.RM_PSM_commands |= RM_PSM_ENABLE_FASTER; dcc_info.RM_PSM_commands |= RM_PSM_ENABLE_SLOWER; dcc_info.RM_PSM_commands |= RM_PSM_ENABLE_NEXTPIC; dcc_info.trick_supported = TRUE; if ((play_opt->duration > 1000) && (context.fileSize > 0)) { RMDBGLOG((ENABLE, "seek, ffwd and iframe modes enabled\n")); dcc_info.RM_PSM_commands |= RM_PSM_ENABLE_SEEK; dcc_info.RM_PSM_commands |= RM_PSM_ENABLE_IFWD; dcc_info.seek_supported = TRUE; dcc_info.iframe_supported = TRUE; } context.dcc_info = &dcc_info; context.PSMcontext = &PSMContext; PSMContext.validPSMContexts = 1; PSMContext.currentActivePSMContext = 1; PSMContext.keyflags = KEYFLAGS; RMTermInit(TRUE); // don't allow ctrl-C and the like ... RMSignalInit(NULL, NULL); // ... but catch other termination signals to call RMTermExit() do { //RMuint32 cmd; /* required in order to start playing right away, otherwise, if state is stopped, process_command will block until an exit of stop is issued */ RM_PSM_SetState(&PSMContext, &(context.dcc_info), RM_PSM_Playing); mainloop: if (RMSeekFile(file, 0, RM_FILE_SEEK_START) == RM_ERRORSEEKFILE) { RMDBGLOG((ENABLE,"seeking file to beginning\n")); goto cleanup; } byte_counter = 0; mainloop_no_seek: if (dcc_info.state == RM_PLAYING_TRICKMODE) { dcc_info.state = RM_PLAYING; dcc_info.trickmode_id = RM_NO_TRICKMODE; } context.FirstSystemTimeStamp = TRUE; context.FirstPTS = 0; if (NTimes) { // first time in loop no need to stop Stop(&context, RM_DEVICES_VIDEO | RM_DEVICES_STC); err = RUAResetPool(pDMA); // needed for no dram copy version on standalone if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error cannot reset dmapool\n")); goto cleanup; } } RMDBGLOG((ENABLE, "DCCSTCSetSpeed %lx %lx\n", play_opt->speed_N, play_opt->speed_M)); DCCSTCSetSpeed(dcc_info.pStcSource, play_opt->speed_N, play_opt->speed_M); Play(&context, RM_DEVICES_VIDEO, DCCVideoPlayFwd); while (1) { // additional 'while' used for taking care of commands issued during EOSWait RMuint8 *buf; while (1) { RMuint32 count; RMstatus status; struct emhwlib_info Info; /* do not set this property when start for the first time */ if (context.initVideo == TRUE) { RMbool keep_sequence = TRUE; err = RUASetProperty(dcc_info.pRUA, dcc_info.video_decoder, RMVideoDecoderPropertyID_StorePreviousVideoHeader, &keep_sequence, sizeof(keep_sequence), 0); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error setting video decoder to keep sequence header on Stop %d\n", err)); return err; } RMDBGLOG((ENABLE, "init video decoder\n")); context.initVideo = FALSE; } PROCESS_KEY(FALSE, TRUE); while (RUAGetBuffer(pDMA, &buf, COMMON_TIMEOUT_US) != RM_OK) { /* this has a double purpose: 1) in mpeg4 elementary streams, the video decoder is able to recover the PTS from the stream. When doing Stop/Play, after the Play the video decoder will find the correct PTS, since we cant set the STC to that value because it's unknown to us, there would be a delay until STC (set to zero) meets the PTS the decoder got. The solution is to prebufferize (thus the decoder will get the PTS and we can obtain it thru a property, and then set the STC accordingly) 2) prebuffering, because we dont start playing until fifo's are full (unintended purpose) */ if ((!context.isSTCRunning) && (RM_PSM_GetState(context.PSMcontext, &(context.dcc_info)) != RM_PSM_Paused) && (RM_PSM_GetState(context.PSMcontext, &(context.dcc_info)) != RM_PSM_Stopped)){ RMuint64 pts; RMuint32 timeScale; err = RUAGetProperty(dcc_info.pRUA, dcc_info.video_decoder, RMVideoDecoderPropertyID_LastDecodedPTS, &pts, sizeof(pts)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot get video PTS\n")); pts = 0; } DCCSTCGetTimeResolution(dcc_info.pStcSource, DCC_Video, &timeScale); RMDBGLOG((ENABLE, "next pts %llu, unit %lu\n", pts, timeScale)); DCCSTCSetTime(dcc_info.pStcSource, pts, timeScale); RMDBGLOG((ENABLE, "start STC\n")); Play(&context, RM_DEVICES_STC, 0); context.isSTCRunning = TRUE; } PROCESS_KEY(FALSE, TRUE); } { { status = RMReadFile(file, buf, (1<<DMA_BUFFER_SIZE_LOG2), &count); RMDBGLOG((ENABLE, "ReadFile to buf %p\n", buf)); } } if (status == RM_ERRORREADFILE) { RMDBGLOG((ENABLE, "reading file")); if (buf != NULL) RUAReleaseBuffer(pDMA, buf); goto cleanup; } if (status == RM_ERRORENDOFFILE) { if (buf != NULL) RUAReleaseBuffer(pDMA, buf); break; } /* fast forward may have been too fast for the decoder. Must set the STC to the current picture in display to avoid skipping frames to catch STC */ if (byte_counter == 0) { DCCSTCSetTime(dcc_info.pStcSource, 0, 90000); //DCCSTCPlay(dcc_info.pStcSource); Info.ValidFields = TIME_STAMP_INFO; Info.TimeStamp = 0; } else if ((context.ResyncTimer) && (!context.FirstPTS)) { RMuint64 stc; RMuint32 timeScale; RMuint64 currentSTC; err = RUAGetProperty(dcc_info.pRUA, dcc_info.SurfaceID, RMGenericPropertyID_CurrentDisplayPTS, &stc, sizeof(stc)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot get video PTS\n")); } DCCSTCGetTimeResolution(dcc_info.pStcSource, DCC_Video, &timeScale); if (timeScale == 90000) stc *= 2; DCCSTCGetTime(dcc_info.pStcSource, ¤tSTC, timeScale); RMDBGLOG((ENABLE, "resync STC(%llu) to %llu, timeScale %lu\n", currentSTC, stc, timeScale)); DCCSTCSetTime(dcc_info.pStcSource, stc, timeScale); //DCCSTCPlay(dcc_info.pStcSource); Info.ValidFields = TIME_STAMP_INFO; Info.TimeStamp = stc; context.ResyncTimer = FALSE; } else if (context.FirstPTS) { //after a seek RMDBGLOG((ENABLE, "first pts %lu\n", context.FirstPTS)); DCCSTCSetTime(dcc_info.pStcSource, context.FirstPTS, 90000); Info.ValidFields = TIME_STAMP_INFO; Info.TimeStamp = context.FirstPTS; context.FirstPTS = 0; context.FirstSystemTimeStamp = FALSE; } else { Info.ValidFields = 0; Info.TimeStamp = 0; } RMDBGLOG((SENDDBG, "sending %lu bytes, pts %llu, valid %lu\n", count, Info.TimeStamp, (RMuint32)Info.ValidFields)); while (RUASendData(dcc_info.pRUA, dcc_info.video_decoder, pDMA, buf, count, &Info, sizeof(Info)) != RM_OK) { struct RUAEvent e; /* see comment on RUAGetBuffer */ if ((!context.isSTCRunning) && (RM_PSM_GetState(context.PSMcontext, &(context.dcc_info)) != RM_PSM_Paused) && (RM_PSM_GetState(context.PSMcontext, &(context.dcc_info)) != RM_PSM_Stopped)) { RMuint64 pts; RMuint32 timeScale; err = RUAGetProperty(dcc_info.pRUA, dcc_info.video_decoder, RMVideoDecoderPropertyID_LastDecodedPTS, &pts, sizeof(pts)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot get video PTS\n")); pts = 0; } DCCSTCGetTimeResolution(dcc_info.pStcSource, DCC_Video, &timeScale); RMDBGLOG((ENABLE, "next pts %llu, unit %lu\n", pts, timeScale)); DCCSTCSetTime(dcc_info.pStcSource, pts, timeScale); RMDBGLOG((ENABLE, "start STC\n")); Play(&context, RM_DEVICES_STC, 0); context.isSTCRunning = TRUE; } PROCESS_KEY(TRUE, TRUE); e.ModuleID = dcc_info.video_decoder; e.Mask = RUAEVENT_XFER_FIFO_READY; while (RUAWaitForMultipleEvents(dcc_info.pRUA, &e, 1, COMMON_TIMEOUT_US, NULL) != RM_OK) { PROCESS_KEY(TRUE, TRUE); } } byte_counter += count; /* sendind data may fill-up the xfer fifo, so we reset the event */ { struct RUAEvent e; e.ModuleID = dcc_info.video_decoder; e.Mask = RUAEVENT_XFER_FIFO_READY; RUAResetEvent(dcc_info.pRUA, &e); } RUAReleaseBuffer(pDMA, buf); } //while(1) if (!context.isSTCRunning){ /* in case the file is shorter than the DMA pool set the STC in play state */ RMuint64 pts; RMuint32 timeScale; err = RUAGetProperty(dcc_info.pRUA, dcc_info.video_decoder, RMVideoDecoderPropertyID_LastDecodedPTS, &pts, sizeof(pts)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot get video PTS\n")); pts = 0; } DCCSTCGetTimeResolution(dcc_info.pStcSource, DCC_Video, &timeScale); RMDBGLOG((ENABLE, "next pts %llu, unit %lu\n", pts, timeScale)); DCCSTCSetTime(dcc_info.pStcSource, pts, timeScale); RMDBGLOG((ENABLE, "start STC\n")); Play(&context, RM_DEVICES_STC, 0); context.isSTCRunning = 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) { RMDBGLOG((ENABLE, "command while waiting for EOS\n")); err = RM_OK; PROCESS_KEY(FALSE, FALSE); } else {#ifdef WITH_MONO /* callback to signal EOS to curacao/mono */ RMEOSCallback(); break;#else break; // EOS#endif } } // additional while if (play_opt->loop_count > 0) play_opt->loop_count --; } while ((play_opt->loop_count > 0) || (play_opt->infinite_loop)); cleanup:#ifdef ABCDRM_MODEL3 stop_abcdrm(dcc_info.pRUA);#endif // ABCDRM_MODEL3 if (file) RMCloseFile(file); if( play_opt->waitexit ) { RMascii key; RMDBGLOG((ENABLE, "press q key again if you really want to stop & quit\n")); while ( !(RMGetKeyNoWait(&key) && ((key == 'q') || (key =='Q'))) ); } RMTermExit(); if (dcc_info.pStcSource) { RMDBGLOG((DEBUG, "Closing STC...\n")); err = DCCSTCClose(dcc_info.pStcSource); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error cannot close STC %d\n", err)); } RMDBGLOG((DEBUG, "Done closing STC.\n")); } if (pVideoSource) { RMDBGLOG((DEBUG, "Stopping video source...\n")); err = DCCStopVideoSource(pVideoSource, DCCStopMode_LastFrame); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot stop video decoder %d\n", err)); } RMDBGLOG((DEBUG, "Done stopping video source.\n")); RMDBGLOG((DEBUG, "Closing video source...\n")); err = DCCCloseVideoSource(pVideoSource); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error cannot close video decoder %d\n", err)); } RMDBGLOG((DEBUG, "Done closing video source.\n")); } clear_video_options(&dcc_info, video_opt); if (pDMA) { RMDBGLOG((DEBUG, "Closing RUA DMA pool...\n")); err = RUAClosePool(pDMA); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error cannot close dmapool %d\n", err)); } RMDBGLOG((DEBUG, "Done closing RUA DMA pool.\n")); } err = DCCClose(dcc_info.pDCC); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot close DCC %d\n", err)); } err = RUADestroyInstance(dcc_info.pRUA); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot destroy RUA instance %d\n", err)); return -1; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -