📄 play_video.c
字号:
before sending it to the video decoder and then read from the file till filling the buffer, otherwise, we just read the file into the buffer. */ if (resendheader == TRUE && headerread == TRUE) { RMint32 i; for (i = 0; i < HeaderSize ; i++) { *(buf+i) = header[i]; } status = RMReadFile(file, buf+HeaderSize, (1 << context.play_opt->dmapool_log2size)-(HeaderSize), &count); resendheader = FALSE; } else {#endif //STORE_SEQ_HEADER_LOCALLY if (context.highSpeedIFrameMode) { RMint64 position; RMuint64 seekto; if (trickBuffersSent >= trickBuffersToSend) trickBuffersSent = 0; if (trickBuffersSent == 0) { RMGetCurrentPositionOfFile(file, &position); seekto = position + (RMuint64) context.highSpeedIFrameSpeed * trickBuffersToSend * (1<<(context.play_opt->dmapool_log2size)); RMDBGLOG((DISABLE, "pos %llu, seekto %llu\n", position, seekto)); status = RMSeekFile(file, seekto, RM_FILE_SEEK_START); if (status != RM_OK) { perror("error seeking in fwd trickmode, assume EOS\n"); if (buf != NULL) { RUAReleaseBuffer(pDMA, buf); buf = NULL; } break; } } status = RMReadFile(file, buf, (1 << context.play_opt->dmapool_log2size), &count); trickBuffersSent++; RMDBGLOG((ENABLE, "sent buffer %lu, speed %lux\n", trickBuffersSent, context.highSpeedIFrameSpeed)); } else { if (context.video_opt->MSflag) { RMint64 position; RMuint64 dummy; RMuint8 *buffer = (RMuint8*)&dummy; RMGetCurrentPositionOfFile (file, &position); status = RMReadFile(file, buffer, sizeof(RMuint64), &count); if (status == RM_ERRORENDOFFILE) { if (buf != NULL) { RUAReleaseBuffer(pDMA, buf); buf = NULL; } break; } else if ((status != RM_OK) || (count != sizeof(RMuint64))) { fprintf(stderr, "read error while reading pts!\n"); if (buf != NULL) { RUAReleaseBuffer(pDMA, buf); buf = NULL; } goto cleanup; } MSPts = RMleBufToUint64(buffer); status = RMReadFile(file, buffer, sizeof(RMuint32), &count); if (status == RM_ERRORENDOFFILE) { if (buf != NULL) { RUAReleaseBuffer(pDMA, buf); buf = NULL; } break; } else if ((status != RM_OK) || (count != sizeof(RMuint32))) { fprintf(stderr, "read error while reading frame length!\n"); if (buf != NULL) { RUAReleaseBuffer(pDMA, buf); buf = NULL; } goto cleanup; } MSLength = RMleBufToUint32(buffer); RMDBGLOG((ENABLE, "pos %llu (%llx); MSLength= %ld ; MSPts = %lld (bufferSize %ld) \n", position, position, MSLength, MSPts, (RMuint32)(1 << context.play_opt->dmapool_log2size) )); //MSPts *= 90000; //MSPts /= 1000; if (MSLength > (RMuint32)(1 << context.play_opt->dmapool_log2size)) { RMDBGLOG((ENABLE, "Buffer overflow! (MSLength=%d,dmapool_log2size=%d)\n",MSLength,(RMuint32)(1 << context.play_opt->dmapool_log2size))); if (buf != NULL) { RUAReleaseBuffer(pDMA, buf); buf = NULL; } goto cleanup; } status = RMReadFile(file, buf, MSLength, &count); } else { status = RMReadFile(file, buf, (1 << context.play_opt->dmapool_log2size), &count); } }#if STORE_SEQ_HEADER_LOCALLY }#endif //STORE_SEQ_HEADER_LOCALLY if (status == RM_ERRORREADFILE) { RMDBGLOG((ENABLE, "reading file")); if (buf != NULL) { RUAReleaseBuffer(pDMA, buf); buf = NULL; } goto cleanup; } if (status == RM_ERRORENDOFFILE) { if (buf != NULL) { RUAReleaseBuffer(pDMA, buf); buf = NULL; } break; } #if STORE_SEQ_HEADER_LOCALLY /* parse the buffer and store the header */ if (headerread == FALSE) { headerread = StoreHeader(&context, buf, header, &HeaderSize, (1 << context.play_opt->dmapool_log2size)); if (headerread) RMDBGLOG((ENABLE, "stored SeqHeader, %lu bytes\n", HeaderSize)); }#endif //STORE_SEQ_HEADER_LOCALLY /* 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 (context.byte_counter == 0) { /* set the VopInfo property */ if (context.video_opt->MSflag == TRUE) { RMuint32 timeScale; DCCSTCGetTimeResolution(dcc_info.pStcSource, DCC_Video, &timeScale); DCCSTCSetTime(dcc_info.pStcSource, (context.play_opt->send_video_pts ? MSPts : 0)+context.stc_offset_ms*((RMint64)(timeScale/1000)), timeScale); } else { DCCSTCSetTime(dcc_info.pStcSource, context.play_opt->STC_initial_value+context.stc_offset_ms*90, 90000); Info.ValidFields = 0; /* Info.TimeStamp = 0; */ /* one shouldn't admit that first decoded picture has a PTS equal to 0 */ /* for instance, closed gops starting with IB...BP (B frames only have backward references) */ /* give decoding order B....B I P */ /* where I is the first decoded picture AND however doesn't have PTS = 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)); // Do not add offset here, its only a resync DCCSTCSetTime(dcc_info.pStcSource, stc, timeScale); context.ResyncTimer = FALSE; } else if (context.FirstPTS) { //after a seek RMDBGLOG((ENABLE, "first pts %lu\n", context.FirstPTS)); DCCSTCSetTime(dcc_info.pStcSource, context.FirstPTS+context.stc_offset_ms*90, 90000); Info.ValidFields = TIME_STAMP_INFO; Info.TimeStamp = context.FirstPTS; context.FirstPTS = 0; context.FirstSystemTimeStamp = FALSE; } else { Info.ValidFields = 0; Info.TimeStamp = 0; } if (RM_PSM_GetState(context.PSMcontext, &(context.dcc_info)) == RM_PSM_Prebuffering) { RMDBGPRINT((ENABLE, ".")); } if (context.video_opt->MSflag == TRUE) { if ((RMint64) MSPts != -1) { Info.ValidFields = context.play_opt->send_video_pts ? TIME_STAMP_INFO:0; Info.TimeStamp = MSPts; } else Info.ValidFields = 0; RMDBGLOG((DISABLE, "MSPts = %lld (0x%llx) pts= %lld (0x%llx) (valid %lu) byte_counter=0x%lx\n", MSPts, MSPts, Info.TimeStamp, Info.TimeStamp, Info.ValidFields, context.byte_counter)); } RMDBGLOG((SENDDBG, "sending %lu bytes, pts %llu, valid %lu\n", count, Info.TimeStamp, (RMuint32)Info.ValidFields)); if (Info.ValidFields) context.last_video_pts = Info.TimeStamp; // Pause //sleep(1); while (RUASendData(dcc_info.pRUA, dcc_info.video_decoder, pDMA, buf, count, &Info, sizeof(Info)) != RM_OK) { struct RUAEvent e; /* see previous comment on RUAGetBuffer */ check_prebuf_state(&context, 0); PROCESS_KEY(TRUE, TRUE); e.ModuleID = dcc_info.video_decoder; e.Mask = RUAEVENT_XFER_FIFO_READY; RUAWaitForMultipleEvents(dcc_info.pRUA, &e, 1, COMMON_TIMEOUT_US, NULL); } context.bitrate += count * 8; context.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); buf = NULL; } //while(1) check_prebuf_state(&context, 0); switch (context.play_opt->disk_ctrl_state) { case DISK_CONTROL_STATE_DISABLE: case DISK_CONTROL_STATE_SLEEPING: break; case DISK_CONTROL_STATE_RUNNING: if(context.play_opt->disk_ctrl_callback && context.play_opt->disk_ctrl_callback(DISK_CONTROL_ACTION_SLEEP) == RM_OK) context.play_opt->disk_ctrl_state = DISK_CONTROL_STATE_SLEEPING; break; } err = WaitForEOS(&context, &actions); { RMuint64 stc; DCCSTCGetTime(dcc_info.pStcSource, &stc, 90000); RMDBGLOG((ENABLE, "Timer duration %llu ms\n", stc/90)); } 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 (context.play_opt->loop_count > 0) context.play_opt->loop_count --; /* if there is another loop, stop devices */ if ((context.play_opt->loop_count > 0) || (context.play_opt->waitexit != TRUE) || (context.play_opt->infinite_loop)) Stop(&context, RM_DEVICES_VIDEO | RM_DEVICES_STC); if( context.video_opt->display_cc ) { /* left over cc must be cleaned when there is a pts discontinuity */ err = RUASetProperty(dcc_info.pRUA, dcc_info.ccfifo_in_id, RMCCFifoPropertyID_Flush, NULL, 0, 0); if( err != RM_OK ) { RMDBGLOG(( ENABLE, "cannot flush cc fifo, exit \n" )); goto cleanup; } } } while ((context.play_opt->loop_count > 0) || (context.play_opt->infinite_loop)); cleanup: if (file) RMCloseFile(file); if( context.play_opt->waitexit ) { RMascii key; Stop(&context, RM_DEVICES_STC); fprintf(stderr, "press q key again if you really want to stop & quit\n"); while ( !(RMGetKeyNoWait(&key) && ((key == 'q') || (key =='Q'))) ); Stop(&context, RM_DEVICES_VIDEO | RM_DEVICES_STC); }#ifndef WITH_MONO RMTermExit();#endif 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"));#ifdef WITH_MONO RMDCCInfo(NULL); // invalidate DCC context#endif if (context.dmabuffer_array) { RMuint32 i; for (i = 0; i < context.dmabuffer_index; i++) { RUAReleaseBuffer(pDMA, context.dmabuffer_array[i]); RMDBGLOG((ENABLE, "released buffer[%lu] @ 0x%08lx\n", i, context.dmabuffer_array[i])); } RMFree(context.dmabuffer_array); context.dmabuffer_index = 0; context.dmabuffer_array = NULL; } if (context.bcc_enabled) { RMDBGLOG((DEBUG, "Closing external closed caption subsystem...\n")); bcc_close(context.pbcc, dcc_info.pRUA); context.bcc_enabled = FALSE; RMDBGLOG((DEBUG, "Done closing external closed caption subsystem.\n")); } if (dcc_info.pStcSource) { Stop(&context, RM_DEVICES_STC); 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"));#ifndef WITH_MONO clear_display_options(&dcc_info, context.disp_opt);#endif /*WITH_MONO*/ } clear_video_options(&dcc_info, context.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")); }#ifndef WITH_MONO 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; }#endif /*WITH_MONO*/ return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -