📄 play_video_checksum.c
字号:
#if 1 if (video_opt->vcodec == EMhwlibVideoCodec_WMV) { struct video_context *context = pSendContext; // Hack: send last PTS again so that video ucode can get the EOS. The problem is that // there is still data in the FIFO and the next inband command is not read by the video microcode. struct emhwlib_info Info; RMuint8 *buffer; RMDBGLOG((ENABLE, "video is WMV, hack EOS\n")); while(RUAGetBuffer(context->pDMA, &buffer, TIMEOUT_10MS) != RM_OK) { /* should never happen since we released an empty buffer before getting here */ RMDBGLOG((ENABLE,"Cannot get buffer for EOS\n")); } buffer[0] = 0; Info.ValidFields = TIME_STAMP_INFO; Info.TimeStamp = context->last_video_pts; while (RUASendData(context->dcc_info->pRUA, context->dcc_info->video_decoder, context->pDMA, buffer, 1, &Info, sizeof(Info)) != RM_OK) { usleep(TIMEOUT_10MS); // Should rarelly happen... } RUAReleaseBuffer(context->pDMA, buffer); }#endif NTimes++; fprintf(stderr, "File ready %ld times, waiting for EOS\n", NTimes); eos_bit_field |= EOS_BIT_FIELD_VIDEO; return WaitForEOSWithCommand2(pSendContext->PSMcontext, &(pSendContext->dcc_info), pActions, eos_bit_field);}#if STORE_SEQ_HEADER_LOCALLYstatic RMbool StoreHeader(RMuint8 *buffer, RMuint8 *seqhead, RMint32 *HeaderSize, RMint32 BufSize){ RMint32 i, size, start; i = 0; if ((video_opt->MPEGProfile == Profile_MPEG2_HD) || (video_opt->MPEGProfile == Profile_MPEG2_SD) || (video_opt->MPEGProfile == Profile_MPEG2_DVD) || (video_opt->MPEGProfile == Profile_MPEG2_SD_DeInt) || (video_opt->MPEGProfile == Profile_MPEG2_HD_DeInt) || (video_opt->MPEGProfile == Profile_MPEG2_DVD_DeInt) ) { while (1) { if ((buffer[i] == 0) && (buffer[i+1] == 0) && (buffer[i+2] == 1) && (buffer[i+3] == 0xB3)) break; i++; if (i >= BufSize-3) return FALSE; } /* fprintf(stderr, "\nMPEG2 escape sequence found at: %ld\n", i); */ start = i; i++; while (1) { if ((buffer[i] == 0) && (buffer[i+1] == 0) && (buffer[i+2] == 1) && (buffer[i+3] == 0xB8)) break; i++; if (i >= BufSize-3) return FALSE; } size = i - start; /* fprintf(stderr, "size %ld, i=%ld, byte at: %02X, next byte %02X\n", size, i, buffer[i], buffer[i+3]); */ if (size > MAXHEADERSIZE) { fprintf(stderr, "header found exceeded maximum header allowed length\n"); return FALSE; } i = 0; for (i = 0; i < size; i++) { seqhead[i] = buffer[start + i]; } *HeaderSize = size; return TRUE; } if ((video_opt->MPEGProfile == Profile_MPEG4_SD) || (video_opt->MPEGProfile == Profile_MPEG4_HD) || (video_opt->MPEGProfile == Profile_MPEG4_SD_Padding) || (video_opt->MPEGProfile == Profile_MPEG4_HD_Padding) || (video_opt->MPEGProfile == Profile_MPEG4_SD_DeInt) || (video_opt->MPEGProfile == Profile_MPEG4_HD_DeInt) || (video_opt->MPEGProfile == Profile_MPEG4_SD_DeInt_Padding) || (video_opt->MPEGProfile == Profile_MPEG4_HD_DeInt_Padding)) { while (1) { if ((buffer[i] == 0) && (buffer[i+1] == 0) && (buffer[i+2] == 1) && ((buffer[i+3] == 0xB5) || (((RMint8)buffer[i+3] >= 0) && ((RMint8)buffer[i+3] <= 0x1F)))) break; i++; if (i >= BufSize-3) return FALSE; }/* fprintf(stderr, "\nMPEG4 escape sequence found at: %ld\n", i); */ start = i; i++; while (1) { if ((buffer[i] == 0) && (buffer[i+1] == 0) && (buffer[i+2] == 1) && (buffer[i+3] == 0xB6)) break; i++; if (i >= BufSize-3) return FALSE; } size = i - start; /* fprintf(stderr, "size %ld, i=%ld, byte at: %02X, next byte %02X\n", size, i, buffer[i], buffer[i+3]); */ if (size > MAXHEADERSIZE) { fprintf(stderr, "header found exceeded maximum header allowed length\n"); return FALSE; } i = 0; for (i = 0; i < size; i++) { seqhead[i] = buffer[start+i]; } *HeaderSize = size; return TRUE; } return FALSE;}#endif // STORE_SEQ_HEADER_LOCALLYstatic RMstatus Stop(struct video_context *pSendContext, RMuint32 devices){ RMstatus err = RM_OK; if (devices & RM_DEVICES_STC) { RMDBGLOG((ENABLE, "STOP: stc\n")); DCCSTCStop(pSendContext->dcc_info->pStcSource); } if (devices & RM_DEVICES_VIDEO) { if (pSendContext->dcc_info->pVideoSource) { RMDBGLOG((ENABLE, "STOP: video decoder\n")); err = DCCStopVideoSource(pSendContext->dcc_info->pVideoSource, DCCStopMode_LastFrame); if (RMFAILED(err)){ RMDBGLOG((ENABLE, "Error stopping video source %d\n", err)); return err; } pSendContext->video_decoder_initialized = FALSE; pSendContext->FirstSystemTimeStamp = TRUE; pSendContext->initVideo = TRUE; err = RUAResetPool(pSendContext->pDMA); // needed for no dram copy version on standalone if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error cannot reset dmapool\n")); return err; } } } return err;}static RMstatus Pause(struct video_context * pSendContext, RMuint32 devices){ RMstatus err; if ((devices & RM_DEVICES_VIDEO) && (pSendContext->dcc_info->pVideoSource)) { RMDBGLOG((ENABLE, "pausing video decoder\n")); err = DCCPauseVideoSource(pSendContext->dcc_info->pVideoSource); if (RMFAILED(err)) { fprintf(stderr, "Cannot pause video decoder %d\n", err); return err; } } if ((devices & RM_DEVICES_STC) && (pSendContext->dcc_info->pStcSource)) { RMDBGLOG((ENABLE, "stop stc\n")); err = DCCSTCStop(pSendContext->dcc_info->pStcSource); if (RMFAILED(err)) { fprintf(stderr, "Cannot stop STC %d\n", err); return err; } } return RM_OK;}static RMstatus Play(struct video_context * pSendContext, RMuint32 devices, enum DCCVideoPlayCommand mode){ RMstatus err = RM_OK; if (devices & RM_DEVICES_STC) { RMDBGLOG((ENABLE, "PLAY: stc\n")); DCCSTCPlay(pSendContext->dcc_info->pStcSource); } if (devices & RM_DEVICES_VIDEO) { if (pSendContext->dcc_info->pVideoSource) { if (pSendContext->initVideo) { /*(!pSendContext->video_decoder_initialized) {*/ RMbool keep_sequence = TRUE; RMDBGLOG((ENABLE, "PLAY: initDecoder\n")); err = RUASetProperty(pSendContext->dcc_info->pRUA, pSendContext->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; } pSendContext->video_decoder_initialized = TRUE; pSendContext->initVideo = FALSE; } RMDBGLOG((ENABLE, "PLAY: video decoder %s\n", (mode == DCCVideoPlayIFrame ? "(iframe)":""))); err = DCCPlayVideoSource(pSendContext->dcc_info->pVideoSource, mode); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot play video decoder %d\n", err)); return err; } } } return err;}static RMstatus seek(struct video_context *pSendContext, RMuint32 time_sec){ RMuint64 bytesSec = pSendContext->fileSize / (play_opt->duration / 1000); RMuint32 timeSec = 0; RMuint64 seekPos; timeSec = pSendContext->dcc_info->seek_time; seekPos = timeSec * bytesSec; RMDBGLOG((ENABLE, "seek to %lu s \n", timeSec)); Stop(pSendContext, RM_DEVICES_VIDEO); RMDBGLOG((ENABLE, ">> %llu bytes/sec, seekto %lu sec => pos %llu, pts %lu\n", bytesSec, timeSec, seekPos, (timeSec*90000))); RMSeekFile(pSendContext->f_bitstream, seekPos, RM_FILE_SEEK_START); pSendContext->byte_counter = seekPos; pSendContext->FirstPTS = timeSec*90000; Play(pSendContext, RM_DEVICES_VIDEO, DCCVideoPlayFwd); RM_PSM_SetState(pSendContext->PSMcontext, &(pSendContext->dcc_info), RM_PSM_Playing); return RM_OK;}/* highspeed iframe mode works only when using STC timers */#define MEAN_DEPTH 7#define DIVERGENCE_TRIGGER 10static RMint64 shiftReg1[MEAN_DEPTH];static RMint64 shiftReg2[MEAN_DEPTH];static RMint32 count1 = 0, count2 = 0;static RMstatus computeSpeed(struct video_context *pSendContext){ RMuint32 samplingT = 200; // 1/5 sec RMuint64 stc; RMstatus err; enum RM_PSM_State PlaybackStatus = RM_PSM_GetState(pSendContext->PSMcontext, &(pSendContext->dcc_info)); if (!pSendContext->dcc_info->seek_supported) return RM_OK; if ((PlaybackStatus == RM_PSM_IForward) || (PlaybackStatus == RM_PSM_IRewind)) { RMint32 N; RMuint32 M; RMuint32 speedX, speedX2; RMint64 currentPTS, diff1, diff2, currentDecoded, delta = 0; RMint64 speed1 = 0, speed2 = 0, sum1, sum2; RMuint32 i; RMbool skip = TRUE; DCCSTCGetTime(pSendContext->dcc_info->pStcSource, &stc, 1000); DCCSTCGetSpeed(pSendContext->dcc_info->pStcSource, &N, &M); if (N > 0) { samplingT *= N; samplingT = (RMuint32) round_int_div((RMuint64)samplingT, M); if (stc > pSendContext->lastSTC + samplingT) { delta = stc - pSendContext->lastSTC; pSendContext->lastSTC = stc; err = RUAGetProperty(pSendContext->dcc_info->pRUA, pSendContext->dcc_info->SurfaceID, RMGenericPropertyID_CurrentDisplayPTS, ¤tPTS, sizeof(currentPTS)); err = RUAGetProperty(pSendContext->dcc_info->pRUA, pSendContext->dcc_info->video_decoder, RMVideoDecoderPropertyID_LastDecodedPTS, ¤tDecoded, sizeof(currentDecoded)); diff1 = (RMint64)stc - (RMint64)(currentPTS / 45); diff2 = (RMint64)stc - (RMint64)(currentDecoded / 45); speed1 = diff1; speed2 = diff2; skip = FALSE; } } else { N *= -1; samplingT *= N; samplingT = (RMuint32) round_int_div((RMuint64)samplingT, M); if (stc < pSendContext->lastSTC - samplingT) { delta = pSendContext->lastSTC - stc; pSendContext->lastSTC = stc; err = RUAGetProperty(pSendContext->dcc_info->pRUA, pSendContext->dcc_info->SurfaceID, RMGenericPropertyID_CurrentDisplayPTS, ¤tPTS, sizeof(currentPTS)); err = RUAGetProperty(pSendContext->dcc_info->pRUA, pSendContext->dcc_info->video_decoder, RMVideoDecoderPropertyID_LastDecodedPTS, ¤tDecoded, sizeof(currentDecoded)); diff1 = (RMint64)(currentPTS / 45) - (RMint64)stc; diff2 = (RMint64)(currentDecoded / 45) - (RMint64)stc; speed1 = diff1; speed2 = diff2; skip = FALSE; } } if (skip == FALSE) { sum1 = sum2 = 0; for (i = 0; i < MEAN_DEPTH; i++) { if (shiftReg1[0] < shiftReg1[i]) sum1++; if (shiftReg2[0] < shiftReg2[i]) sum2++; } if (sum1 > MEAN_DEPTH/2) count1++; else count1 = 0; if (sum2 > MEAN_DEPTH/2) count2++; else count2 = 0; speedX = (RMuint32)round_int_div((RMuint64)N, M); speedX2 = (RMuint32)round_int_div((RMuint64)delta, 200); RMDBGLOG((ENABLE, "time %llu (%ld/%lu=%lux, %lu), sampling %lu, delta %4llu, sum1 %lld, sum2 %lld, diff3 %lld(%ld), diff4 %lld(%ld) %s\n", stc, N, M, speedX, speedX2, samplingT, delta, sum1, sum2, speed1, count1, speed2, count2, ((count1 > DIVERGENCE_TRIGGER) && (count2 > DIVERGENCE_TRIGGER)) ? "DIVERGE!":"")); pSendContext->lastVideoPTS = currentPTS; pSendContext->lastDecoded = currentDecoded; for (i = 0 ; i < MEAN_DEPTH-1 ; i++) shiftReg1[i] = shiftReg1[i+1]; shiftReg1[MEAN_DEPTH-1] = speed1; for (i = 0 ; i < MEAN_DEPTH-1 ; i++) shiftReg2[i] = shiftReg2[i+1]; shiftReg2[MEAN_DEPTH-1] = speed2; if ((count1 > DIVERGENCE_TRIGGER) && (count2 > DIVERGENCE_TRIGGER) && (!pSendContext->highSpeedIFrameMode)) { RMDBGLOG((ENABLE, "enable high speed iframe mode\n")); pSendContext->highSpeedIFrameMode = TRUE; } pSendContext->highSpeedIFrameSpeed = speedX; } } return RM_OK;}static void check_prebuf_state(struct video_context *pSendContext, RMuint32 buffersize){ RMbool quit_prebuf; enum RM_PSM_State PlaybackStatus = RM_PSM_GetState(pSendContext->PSMcontext, &(pSendContext->dcc_info)); if (PlaybackStatus != RM_PSM_Prebuffering) return; /* if fail in getbuffer force quitting prebuffering state */ quit_prebuf = ((buffersize == 0) || ((play_opt->prebuf_max > 0) && (pSendContext->prebuf_level >= play_opt->prebuf_max))) ? TRUE : FALSE; pSendContext->prebuf_level += buffersize; quit_prebuf = TRUE; if (quit_prebuf) { RMDBGLOG((ENABLE, "exit prebuffering state\n")); RMDBGLOG((ENABLE, "setting play state\n")); RM_PSM_SetState(pSendContext->PSMcontext, &(pSendContext->dcc_info), RM_PSM_Playing);#if START_IN_IFRAME_MODE Play(pSendContext, RM_DEVICES_VIDEO | RM_DEVICES_STC, DCCVideoPlayIFrame);#else Play(pSendContext, RM_DEVICES_VIDEO | RM_DEVICES_STC, DCCVideoPlayFwd);#endif }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -