📄 play_demux.c
字号:
if (dataType == RMVDEMUX_VIDEO) prevVpts = Info.TimeStamp; if (dataType == RMVDEMUX_AUDIO) prevApts = Info.TimeStamp;#endif } else if (!(play_opt->send_audio_pts || play_opt->send_audio_pts)) { Info.TimeStamp = 0; RMDBGLOG((ENABLE, "No PTS -> Init FirstSystemTimeStamp = %llu\n", Info.TimeStamp)); pSendContext->realFirstPTS = (RMint64) (Info.TimeStamp + pSendContext->start_90khz); // set the STC to 1sec before the real value, so that we dont the first frame when prebuffering DCCSTCSetTime(pSendContext->dcc_info->pStcSource, (RMuint64)(pSendContext->realFirstPTS - 90000), 90000); pSendContext->FirstSystemTimeStamp = FALSE;#ifdef PTS_DISCONTINUITY_DETECTION prevVpts = Info.TimeStamp; prevApts = Info.TimeStamp;#endif } else RMDBGLOG((ENABLE, "waiting for valid PTS\n")); } } if ((pSendContext->waitForValidAudioPTS) && (dataType == RMVDEMUX_AUDIO) && (send_pts)) { if (Info.ValidFields & TIME_STAMP_INFO) { RMDBGLOG((ENABLE, "first valid audio PTS %llu(0x%09llx), start sending audio\n",Info.TimeStamp,Info.TimeStamp)); pSendContext->waitForValidAudioPTS = FALSE;#ifdef PTS_DISCONTINUITY_DETECTION prevApts = Info.TimeStamp;#endif } else { // dont send audio with invalid pts RMDBGLOG((ENABLE, "audio pts not valid\n")); if (isPtsValid) { repack_pts_valid = TRUE; repack_pts = PTS; } goto end_data_callback; } } if ((pSendContext->waitForValidVideoPTS) && (dataType == RMVDEMUX_VIDEO) && (send_pts)) { if (Info.ValidFields & TIME_STAMP_INFO) { RMDBGLOG((ENABLE, "first valid video PTS %llu(0x%09llx), start sending video\n",Info.TimeStamp,Info.TimeStamp)); pSendContext->waitForValidVideoPTS = FALSE;#ifdef PTS_DISCONTINUITY_DETECTION prevVpts = Info.TimeStamp;#endif } else { // dont send video with invalid pts RMDBGLOG((ENABLE, "video pts not valid\n")); if (isPtsValid) { repack_pts_valid = TRUE; repack_pts = PTS; } goto end_data_callback; } }#ifdef PTS_DISCONTINUITY_DETECTION if (Info.ValidFields & TIME_STAMP_INFO) { RMint64 diff = 0; if ((pSendContext->fakePrevPts) && (dataType == RMVDEMUX_AUDIO)) { RMDBGPRINT((ENABLE, "Set prevAPTS to 0x%09llx\n", Info.TimeStamp)); prevApts = Info.TimeStamp; pSendContext->fakePrevPts = FALSE; } if ((dataType == RMVDEMUX_VIDEO) && (prevVpts != 0xffffffffffffffffll)) { diff = Info.TimeStamp - prevVpts; prevVpts = Info.TimeStamp; RMDBGPRINT((DISABLE, "Vpts = %9llx %8lx (%lx)\n", Info.TimeStamp, pSendContext->video_byte_counter, file_offset)); } else if ((dataType == RMVDEMUX_AUDIO) && (prevApts != 0xffffffffffffffffll)) { diff = Info.TimeStamp - prevApts; prevApts = Info.TimeStamp; RMDBGPRINT((DISABLE, "Apts = %9llx %8lx (%lx)\n", Info.TimeStamp, pSendContext->audio_byte_counter, file_offset)); } if ((diff < -PTS_DISCONTINUITY_RANGE) || (diff > PTS_DISCONTINUITY_RANGE)) { struct InbandCommand_type InbandCmd; RMDBGPRINT((ENABLE, "%spts discontinuity = %9llx -> %9llx\n", (dataType == RMVDEMUX_VIDEO)?"V":"A", Info.TimeStamp-diff, Info.TimeStamp)); DCCSTCSetDiscontinuity(pSendContext->dcc_info->pStcSource, Info.TimeStamp-2*90000, 90000); InbandCmd.Tag = INBAND_COMMAND_TAG_DISCONTINUITY | INBAND_COMMAND_ACTION_STOP; InbandCmd.Coordinate = 0;// if (dataType == RMVDEMUX_VIDEO) RUASetProperty(pSendContext->pRUA, pSendContext->dcc_info->video_decoder, RMGenericPropertyID_InbandCommand, &InbandCmd, sizeof(InbandCmd), 0);// if (dataType == RMVDEMUX_AUDIO) RUASetProperty(pSendContext->pRUA, pSendContext->dcc_info->audio_decoder, RMGenericPropertyID_InbandCommand, &InbandCmd, sizeof(InbandCmd), 0); } }#endif // PTS_DISCONTINUITY_DETECTION if (PlaybackStatus == RM_PSM_Prebuffering) RMDBGPRINT((ENABLE, "%s", dataType == RMVDEMUX_AUDIO ? "a":"v")); { RMuint64 stc; DCCSTCGetTime(pSendContext->dcc_info->pStcSource, &stc, 90000); RMDBGLOG((SENDDBG, "sending %s, %lu, pts %llu(0x%09llx) %s stc %llu(0x%09llx)\n", dataType == RMVDEMUX_AUDIO ? "audio":"video", send_length, Info.TimeStamp, Info.TimeStamp, Info.ValidFields & TIME_STAMP_INFO ? "valid":"", stc, stc)); } if (Info.ValidFields & TIME_STAMP_INFO) { static RMint64 max_diff = 0, min_diff = 0; RMint64 diff; if ( (prevVpts != 0xffffffffffffffffll) && (prevApts != 0xffffffffffffffffll) ) { diff = (RMint64)(prevVpts - prevApts) / (RMint64)90; /* diff in miliseconds */ RMDBGLOG((DISABLE, "diff %lld %llx %llx\n", diff, prevVpts, prevApts)); if ( (diff < -100) || (diff > 100)) { if ( (diff > 0) && (diff > max_diff+100) ) { max_diff = diff; RMDBGLOG((ENABLE, " %lld\n", diff)); } if ( (diff < 0) && (diff < min_diff-100) ) { min_diff = diff; RMDBGLOG((ENABLE, " %lld\n", diff)); } } } } while (RUASendData(pSendContext->pRUA, decoder, pSendContext->pDMA, send_buffer, send_length, (void*)&Info, sizeof(Info)) != RM_OK) { struct RUAEvent e; check_prebuf_state(pSendContext, 0); PROCESS_KEY_INSIDE_FUNCTION(); PlaybackStatus = RM_PSM_GetState(pSendContext->PSMcontext, &(pSendContext->dcc_info)); /* skip audio in trickmode */ if ((dataType == RMVDEMUX_AUDIO) && ((PlaybackStatus == RM_PSM_Slow) || (PlaybackStatus == RM_PSM_Fast) || (PlaybackStatus == RM_PSM_NextPic))) goto end_data_callback; e.ModuleID = decoder; e.Mask = RUAEVENT_XFER_FIFO_READY; RUAWaitForMultipleEvents(pSendContext->pRUA, &e, 1, SENDDATA_TIMEOUT_US, NULL); } if ( pbyte_counter ) *pbyte_counter = *pbyte_counter + send_length; if ( 0 && (Info.ValidFields & TIME_STAMP_INFO) ) { RMuint32 pts; err = RUAGetProperty(pSendContext->pRUA, decoder, RMGenericPropertyID_LastTransferredHwPts, &pts, sizeof(pts)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "RMGenericPropertyID_LastTransferredHwPts Error %d on decoder 0x%lx\n", err, decoder)); } else { RMDBGLOG((ENABLE, " %s in queue = %ld ms\n", string, (((RMuint32)Info.TimeStamp/2) - pts)/45)); } } /* sendind data may fill-up the xfer fifo, so we reset the event */ { struct RUAEvent e; e.ModuleID = decoder; e.Mask = RUAEVENT_XFER_FIFO_READY; RUAResetEvent(pSendContext->pRUA, &e); } } if (pSendContext->repack_sample) { RMuint32 val; val = RMmax(length, REPACK_SIZE); if ((repack_offset + val) > (RMuint32) (1<<play_opt->dmapool_log2size)) { RUAReleaseBuffer(pSendContext->pDMA, repack_buffer); repack_buffer = (RMuint8 *) NULL; repack_offset = 0; } if (repack_buffer == NULL) { while (RUAGetBuffer(pSendContext->pDMA, &repack_buffer, GETBUFFER_TIMEOUT_US) != RM_OK) { PROCESS_KEY_INSIDE_FUNCTION(); RMDBGLOG((DISABLE, "Wait for a buffer\n")); } } memcpy(repack_buffer + repack_offset + repack_size, buffer, length); repack_size += length; if (isPtsValid) { repack_pts_valid = TRUE; repack_pts = PTS; } } end_data_callback: switch (dataType) { case RMVDEMUX_VIDEO: pSendContext->video_repack_buf = repack_buffer; pSendContext->video_repack_offset = repack_offset; pSendContext->video_repack_size = repack_size; pSendContext->video_repack_pts = repack_pts; pSendContext->video_repack_pts_valid = repack_pts_valid; break; case RMVDEMUX_AUDIO: pSendContext->audio_repack_buf = repack_buffer; pSendContext->audio_repack_offset = repack_offset; pSendContext->audio_repack_size = repack_size; pSendContext->audio_repack_pts = repack_pts; pSendContext->audio_repack_pts_valid = repack_pts_valid; break; case RMVDEMUX_SUBPICTURE: pSendContext->spu_repack_buf = repack_buffer; pSendContext->spu_repack_offset = repack_offset; pSendContext->spu_repack_size = repack_size; pSendContext->spu_repack_pts = repack_pts; pSendContext->spu_repack_pts_valid = repack_pts_valid; break; default: RMDBGLOG((ENABLE, "Invalid data type %d\n", dataType)); return; } return_from_callback: return;}static void AC3DTSCallback(RMuint8 numberOfFrameHeaders, RMuint16 firstAccessUnitPointer, void *context){ struct demux_context *pSendContext = (struct demux_context *) context; //RMDBGPRINT((ENABLE, "AC3DTSCallback: firstAccessUnitPointer= %x\n", firstAccessUnitPointer)); pSendContext->audio_first_access_unit_pointer_valid = TRUE; pSendContext->audio_first_access_unit_pointer = firstAccessUnitPointer; return;}static void LPCMCallback(RMuint8 numberOfFrameHeaders, RMuint16 firstAccessUnitPointer, RMuint32 frequency, RMuint8 numberOfChannels, RMvdemuxQuantization quantizationWordLength, void *context){ struct demux_context *pSendContext = (struct demux_context *) context; //RMDBGPRINT((ENABLE, "LPCMCallback: firstAccessUnitPointer= %x\n", firstAccessUnitPointer)); pSendContext->audio_first_access_unit_pointer_valid = TRUE; pSendContext->audio_first_access_unit_pointer = firstAccessUnitPointer; return;}static void aobPcm_callback (RMuint16 firstAccessUnitPointer, RMvdemuxQuantization quantizationGr1, RMvdemuxQuantization quantizationGr2, RMuint32 samplingFreqGr1, RMuint32 samplingFreqGr2, RMuint8 bitShift, RMuint8 channelAssign, void * context){} static void mlp_callback (RMuint16 firstAccessUnitPointer, RMuint8 forwardAUSearchPointer, RMuint8 backwardAUSearchPointer, void *context){}static RMstatus WaitForEOS(struct demux_context *context, struct RM_PSM_Actions *pActions){ RMuint32 eos_bit_field = 0; enum RM_PSM_State PlaybackStatus = RM_PSM_GetState(context->PSMcontext, &(context->dcc_info)); NTimes++; if (verbose_stderr != 0) fprintf(stderr, "File ready %ld times, waiting for EOS\n", NTimes); if (context->video_byte_counter > 0) { eos_bit_field |= EOS_BIT_FIELD_VIDEO; } if ((context->audio_byte_counter > 0) && ((PlaybackStatus == RM_PSM_Playing) || (PlaybackStatus == RM_PSM_Prebuffering))) { eos_bit_field |= EOS_BIT_FIELD_AUDIO; } return WaitForEOSWithCommand(context->PSMcontext, &(context->dcc_info), pActions, eos_bit_field);}static RMstatus InitUserDataProcessing(struct demux_context *pcontext){ RMstatus err; switch(user_data_app_mode) { case user_data_dma_full_buffer: case user_data_dma_no_delay: case user_data_dma_minimum_size: case user_data_dma_exact_size: { struct Receive_type Receive; Receive.pRUA = pcontext->pRUA; Receive.targetModule = EMHWLIB_TARGET_MODULE(VideoDecoder, EMHWLIB_MODULE_INDEX(pcontext->dcc_info->video_decoder), 1); Receive.buffer_count = 4; Receive.buffer_size_log2 = 12; // 4k per buffer -> 16M err = DCCOpenReceive(&Receive, &pcontext->pReceive, &pcontext->pDmaUserData); if (user_data_app_mode == user_data_dma_no_delay) { struct EMhwlibReadBufferCompletion bc; bc.mode = EMhwlibReadBufferCompletionMode_NoDelay; /* complete the buffer as soon as the microcode sent data */ bc.threshold = 0; /* ignored */ err = RUASetProperty(pcontext->pRUA, Receive.targetModule, RMGenericPropertyID_ReadBufferCompletion, &bc, sizeof(bc), 0); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "RMGenericPropertyID_ReadBufferCompletion Error %d\n", err)); return err; } } else if (user_data_app_mode == user_data_dma_minimum_size) { struct EMhwlibReadBufferCompletion bc; bc.mode = EMhwlibReadBufferCompletionMode_MinimumSize; /* complete the buffer when the buffer has more than the threshold value */ bc.threshold = 256; err = RUASetProperty(pcontext->pRUA, Receive.targetModule, RMGenericPropertyID_ReadBufferCompletion, &bc, sizeof(bc), 0); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "RMGenericPropertyID_ReadBufferCompletion Error %d\n", err)); return err; } } else if (user_data_app_mode == user_data_dma_exact_size) { struct EMhwlibReadBufferCompletion bc; bc.mode = EMhwlibReadBufferCompletionMode_ExactSize; /* complete the buffer when the buffer has exactly the threshold value */ bc.threshold = 256; err = RUASetProperty(pcontext->pRUA, Receive.targetModule, RMGenericPropertyID_ReadBufferCompletion, &bc, sizeof(bc), 0); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "RMGenericPropertyID_ReadBufferCompletion Error %d\n", err)); return err; } } break; } case user_data_get_chunk256_without_dma: break; case user_data_rua_mapping_without_dma: { struct gbus_fifo *fifo; struct UserDataFIFOInfo udfi; if (pllad == NULL) { pllad = llad_open("0"); pgbus = gbus_open(pllad); } err = RUAGetProperty(pcontext->pRUA, VideoDecoder, RMVideoDecoderPropertyID_UserDataFIFOInfo, &udfi, sizeof(udfi)); fifo = (struct gbus_fifo *)udfi.ContainerAddress; pcontext->user_data_fifo_base = gbus_read_uint32(pgbus, (RMuint32) &(fifo->base)); pcontext->user_data_fifo_size = gbus_read_uint32(pgbus, (RMuint32) &(fifo->size)); if ( (pcontext->user_data_fifo_base == 0) || (pcontext->user_data_fifo_size == 0) ) { fprintf(stderr, "USER_DATA ERROR: user_data_fifo_base or user_data_fifo_size is NULL\n"); return RM_ERROR; } pcontext->user_data_fifo_container = udfi.ContainerAddress; RMDBGLOG((DISABLE, "user_data_fifo_container=%lx base=%lx size=%lx\n", pcontext->user_data_fifo_container, pcontext->user_data_fifo_base, pcontext->user_data_fifo_size)); err = RUALock(pcontext->pRUA, pcontext->user_data_fifo_base, pcontext->user_data_fifo_size); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "USER_DATA ERROR: Unable to lock output!\n")); } pcontext->pmapped_user_data_fifo_base = RUAMap(pcontext->pRUA, pcontext->user_data_fifo_base, pcontext->user_data_fifo_size); break; } case no_user_data: default: return RM_OK; } pcontext->f_record = fopen("userdata.bin", "wb"); if (pcontext->f_record == NULL) RMDBGLOG((ENABLE, "Error opening userdata.bin")); pcontext->f_record_size = 0; return RM_OK;}static void SaveUserData(struct demux_context *pcontext){ RMstatus err; RMuint32 targetModule = EMHWLIB_TARGET_MODULE(VideoDecoder, EMHWLIB_MODULE_INDEX(pcontext->dcc_info->video_decoder), 1); struct RUAEvent e; e.ModuleID = pcontext->dcc_info->video_decoder; switch(user_data_app_mode) { case user_data_dma_full_buffer: case user_data_dma_no_delay:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -