📄 play_video_checksum.c
字号:
if (file == NULL) { RMDBGLOG((ENABLE, "Cannot open file %s\n", play_opt->filename)); goto cleanup; } context.f_bitstream = file; RMSizeOfOpenFile(file, &context.fileSize);#if !(STORE_SEQ_HEADER_LOCALLY) 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; }#endif //STORE_SEQ_HEADER_LOCALLY /* initialize the external close caption source */ if (NULL == play_opt->bcc_filename) { context.bcc_enabled = FALSE; } else { RMnonAscii *naname; context.bcc_enabled = TRUE; naname = RMnonAsciiFromAscii(play_opt->bcc_filename); err = bcc_init(&context.pbcc, naname, dcc_info.pRUA, context.dcc_info); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Error %s: failed to init BCC subsystem.\n", RMstatusToString(err))); context.bcc_enabled = FALSE; } RMFreeNonAscii(naname); } context.PSMcontext = &PSMContext; PSMContext.validPSMContexts = 1; PSMContext.currentActivePSMContext = 1; PSMContext.keyflags = KEYFLAGS; /* Send WMV9 parameters */ if (video_opt->vcodec == EMhwlibVideoCodec_WMV) { struct VideoDecoder_WMV9VSProp_type wmv9_prop; RMuint32 Image_Width, Image_Height; RMDBGLOG((ENABLE, "Sending WMV9 parameters...\n")); Image_Width = video_opt->vcodec_max_width; Image_Height = video_opt->vcodec_max_height; wmv9_prop.Sequence = video_opt->wmv9_seq; wmv9_prop.Image_Width = Image_Width; wmv9_prop.Image_Height = Image_Height; wmv9_prop.MB_Width = (Image_Width + 15) / 16; wmv9_prop.MB_Height = (Image_Height + 15) / 16; err = RUASetProperty(dcc_info.pRUA, dcc_info.video_decoder, RMVideoDecoderPropertyID_WMV9VSProp, &wmv9_prop, sizeof(wmv9_prop), 0); }#if ENABLE_MONITOR context.monitor = TRUE;#endif#ifndef WITH_MONO RMTermInit(TRUE); // don't allow ctrl-C and the like ... RMSignalInit(NULL, NULL); // ... but catch other termination signals to call RMTermExit()#endif do { enum RM_PSM_State FSMstate; RMuint8 *buf; if (play_opt->start_pause) { RMDBGLOG((ENABLE, "start in pause mode!\n")); /* required, because if we do 'next' the decoder *must* be running */ err = Play(&context, RM_DEVICES_VIDEO, /*DCCVideoPlayIFrame*/DCCVideoPlayFwd); if (RMFAILED(err)) { fprintf(stderr, "Cannot start decoders %d\n", err); goto cleanup; } err = Pause(&context, RM_DEVICES_VIDEO); if (RMFAILED(err)) { fprintf(stderr, "Cannot pause decoders %d\n", err); goto cleanup; } RM_PSM_SetState(context.PSMcontext, &(context.dcc_info), RM_PSM_Paused); } else RM_PSM_SetState(context.PSMcontext, &(context.dcc_info), RM_PSM_Playing); play_opt->start_pause = FALSE; mainloop: RMDBGLOG((ENABLE, "mainloop\n")); if (RMSeekFile(file, 0, RM_FILE_SEEK_START) == RM_ERRORSEEKFILE) { RMDBGLOG((ENABLE,"seeking file to beginning\n")); goto cleanup; } context.byte_counter = 0; context.FirstPTS = 0; mainloop_no_seek: RMDBGLOG((ENABLE, "mainloop_no_seek\n")); /* do not set this property when start for the first time */ if (context.initVideo == TRUE) {#if STORE_SEQ_HEADER_LOCALLY resendheader = TRUE;#else 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;#endif //STORE_SEQ_HEADER_LOCALLY } context.FirstSystemTimeStamp = TRUE; context.highSpeedIFrameMode = FALSE; context.trickMode = FALSE; context.iframeMode = FALSE; FSMstate = RM_PSM_GetState(context.PSMcontext, &(context.dcc_info)); if ((FSMstate != RM_PSM_Paused) && (FSMstate != RM_PSM_Stopped)) { RM_PSM_SetState(context.PSMcontext, &(context.dcc_info), RM_PSM_Playing); } else { PROCESS_KEY(FALSE, TRUE); } 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); /* do prebufferization only when in playing state */ FSMstate = RM_PSM_GetState(context.PSMcontext, &(context.dcc_info)); if (FSMstate == RM_PSM_Playing) { /* required, because if we start straight into pause mode, we cant send buffers (weird) */ err = Play(&context, RM_DEVICES_VIDEO, DCCVideoPlayFwd); if (RMFAILED(err)) { fprintf(stderr, "Cannot start decoders %d\n", err); goto cleanup; } /* ...for prebuffering */ err = Pause(&context, RM_DEVICES_VIDEO | RM_DEVICES_STC); if (RMFAILED(err)) { fprintf(stderr, "Cannot pause decoders %d\n", err); goto cleanup; } RM_PSM_SetState(context.PSMcontext, &(context.dcc_info), RM_PSM_Prebuffering); context.prebuf_level = 0; }#ifdef WITH_MONO RMDCCInfo(&dcc_info); // pass DCC context to application#endif /* 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) { // additional 'while' used for taking care of commands issued during EOSWait while (1) { RMuint32 count; RMstatus status; struct emhwlib_info Info; #ifdef SEND_IBC if (!ibc_sent && (context.byte_counter >= HARDCODE_BYTECOUNT)) { SendInbandCommand(&context); ibc_sent = TRUE; }#endif /* first, try to fill up the CC fifo */ if (context.bcc_enabled) { bcc_feed(context.pbcc, dcc_info.pRUA, 0); } update_hdmi(&dcc_info, disp_opt, NULL); // PROCESS_KEY(FALSE, TRUE); 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, 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) */// 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; }#ifdef DO_CAPTURE get_picture(context.dcc_info);#endif// PROCESS_KEY(FALSE, TRUE);// RMDBGLOG((ENABLE, "RUAGetBuffer() FAILED!\n")); } // RMDBGLOG((ENABLE, "RUAGetBuffer() returned 0x%08lx\n", buf)); check_prebuf_state(&context, (RMuint32) (1<<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 ((!trickSizeToSend) && (dcc_info.seek_supported)) { trickSizeToSend = (RMuint32) (context.fileSize / (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.fileSize, (RMuint32)(play_opt->duration / 1000), trickSizeToSend, trickBuffersToSend, (1<<play_opt->dmapool_log2size))); } #if STORE_SEQ_HEADER_LOCALLY /* if we have to resend the sequence header, we copy it into the buffer 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<<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<<(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<<play_opt->dmapool_log2size), &count); trickBuffersSent++; RMDBGLOG((ENABLE, "sent buffer %lu, speed %lux\n", trickBuffersSent, context.highSpeedIFrameSpeed)); } else { if (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((DISABLE, "pos %llu (%llx); MSLength= %ld ; MSPts = %lld (bufferSize %ld) \n", position, position, MSLength, MSPts, (RMuint32)(1<<play_opt->dmapool_log2size) )); //MSPts *= 90000; //MSPts /= 1000; if (MSLength > (RMuint32)(1<<play_opt->dmapool_log2size)) { RMDBGLOG((ENABLE, "Buffer overflow!\n")); if (buf != NULL) { RUAReleaseBuffer(pDMA, buf); buf = NULL; } goto cleanup; } status = RMReadFile(file, buf, MSLength, &count); } else { status = RMReadFile(file, buf, (1<<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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -