?? play_vdemux.c
字號:
while (RUASendData(pSendContext->pRUA, decoder, pSendContext->pDMA, send_buffer, send_length, (void*)&Info, sizeof(Info)) != RM_OK) { struct RUAEvent e; PROCESS_KEY_INSIDE_FUNCTION(); e.ModuleID = decoder; e.Mask = RUAEVENT_XFER_FIFO_READY; RUAWaitForMultipleEvents(pSendContext->pRUA, &e, 1, SENDDATA_TIMEOUT_US, NULL); } RUAReleaseBuffer(pSendContext->pDMA, send_buffer); return_from_callback: return;}static void PESCallback(RMuint8 *buffer, RMuint32 length, RMuint64 PTS, RMbool isPtsValid, RMvdemuxDataType dataType, RMuint64 PESOffset, void *context){ static RMascii *decoder_name[] = {"video", "audio", "spu"}; RMascii *string; struct demux_context *pSendContext = (struct demux_context *) context; RMuint32 decoder; struct emhwlib_info Info; RMbool send_data = FALSE; RMuint8 *send_buffer = (RMuint8 *) NULL; RMuint32 send_length = 0; RMuint8 *repack_buffer; RMuint64 repack_pts; RMuint32 repack_offset, repack_size; RMbool repack_pts_valid; RMuint32 send_pts; RMuint32 *pbyte_counter = 0; RMuint32 first_access_unit_pointer = 0; RMbool isFirstAccessUnitValid = FALSE; enum RM_PSM_State PlaybackStatus = RM_PSM_GetState(pSendContext->PSMcontext, &(pSendContext->dcc_info));#ifdef PTS_DISCONTINUITY_DETECTION static RMuint64 prevVpts = 0xffffffffffffffffll; static RMuint64 prevApts = 0xffffffffffffffffll;#endif if (pSendContext->ignoreCallback) { if ((actions.cmd == RM_QUIT) && (!actions.cmdProcessed)) { RMDBGLOG((ENABLE, "callback called when 'quit' command was issued\n")); goto return_from_callback; } if ((PlaybackStatus == RM_PSM_Stopped) && (actions.cmdProcessed)) { RMDBGLOG((ENABLE, "callback called when 'stop' command was issued\n")); goto return_from_callback; } if ((actions.cmd == RM_STOP_SEEK_ZERO) && (!actions.cmdProcessed)) { RMDBGLOG((ENABLE, "callback called when 'seekzero' command was issued\n")); goto return_from_callback; } if ((actions.cmd == RM_SEEK) && (!actions.cmdProcessed)) { RMDBGLOG((ENABLE, "callback called when 'seek' command was issued\n")); goto return_from_callback; } if (((actions.cmd == RM_IFWD) || (actions.cmd == RM_IRWD)) && (actions.cmdProcessed)) { RMDBGLOG((ENABLE, "callback called when 'iframe' command was issued\n")); goto return_from_callback; } RMDBGLOG((ENABLE, "********** ignoring Callback!! *********, cmd %lu, processed %lu\n", actions.cmd, actions.cmdProcessed)); goto return_from_callback; } switch (dataType) { case RMVDEMUX_AUDIO: if (pSendContext->audio_first_access_unit_pointer_valid) { isFirstAccessUnitValid = TRUE; first_access_unit_pointer = pSendContext->audio_first_access_unit_pointer; pSendContext->audio_first_access_unit_pointer_valid = FALSE; } break; default: isFirstAccessUnitValid = FALSE; first_access_unit_pointer = 0; break; } switch (dataType) { case RMVDEMUX_VIDEO: if ( ! play_opt->send_video) return ; decoder = pSendContext->dcc_info->video_decoder; string = decoder_name[0]; send_pts = play_opt->send_video_pts; repack_buffer = pSendContext->video_repack_buf; repack_offset = pSendContext->video_repack_offset; repack_size = pSendContext->video_repack_size; repack_pts = pSendContext->video_repack_pts; repack_pts_valid = pSendContext->video_repack_pts_valid; pbyte_counter = &pSendContext->video_byte_counter; //printf("Sending %lu bytes of video data\n", length); break; case RMVDEMUX_AUDIO: if ( ! play_opt->send_audio) return ; if ((PlaybackStatus != RM_PSM_Playing) && (PlaybackStatus != RM_PSM_Paused) && (PlaybackStatus != RM_PSM_Prebuffering)) return; decoder = pSendContext->dcc_info->audio_decoder; string = decoder_name[1]; send_pts = play_opt->send_audio_pts; repack_buffer = pSendContext->audio_repack_buf; repack_offset = pSendContext->audio_repack_offset; repack_size = pSendContext->audio_repack_size; repack_pts = pSendContext->audio_repack_pts; repack_pts_valid = pSendContext->audio_repack_pts_valid; pbyte_counter = &pSendContext->audio_byte_counter; //printf("Sending Audio data\n"); break; case RMVDEMUX_SUBPICTURE: if ( ! play_opt->send_spu) return ;#ifdef ENABLE_SPU_OP if (! pSendContext->enable_spu) { RMDBGPRINT((ENABLE, "disabled spu\n")); return; }#else return;#endif decoder = pSendContext->dcc_info->spu_decoder; string = decoder_name[2]; send_pts = play_opt->send_spu_pts; repack_buffer = pSendContext->spu_repack_buf; repack_offset = pSendContext->spu_repack_offset; repack_size = pSendContext->spu_repack_size; repack_pts = pSendContext->spu_repack_pts; repack_pts_valid = pSendContext->spu_repack_pts_valid; break; case RMVDEMUX_NAVIGATION: RMDBGPRINT((ENABLE, "navigation\n")); return; default: RMDBGPRINT((ENABLE, "Unknown data type %d\n", dataType)); return; } if ((pSendContext->repack_sample) && (repack_size>0) && ((isPtsValid) || (repack_offset + length > (RMuint32) (1<<play_opt->dmapool_log2size)) || (repack_size + length > REPACK_SIZE))) { send_buffer = repack_buffer + repack_offset; send_length = repack_size; Info.ValidFields = (repack_pts_valid && send_pts) ? TIME_STAMP_INFO : 0; Info.TimeStamp = repack_pts; send_data = TRUE; repack_offset += repack_size; repack_size = 0; repack_pts = 0; repack_pts_valid = FALSE; } else if (!pSendContext->repack_sample) { send_buffer = buffer; send_length = length; Info.ValidFields = ((isPtsValid && send_pts) ? TIME_STAMP_INFO : 0) | (isFirstAccessUnitValid ? FIRST_ACCESS_UNIT_POINTER_INFO : 0); Info.TimeStamp = PTS; Info.FirstAccessUnitPointer = first_access_unit_pointer; send_data = TRUE; } if (send_data) { if (1/*(PlaybackStatus == RM_PSM_Playing) || (PlaybackStatus == RM_PSM_Paused) || (PlaybackStatus == RM_PSM_NextPic)*/) { if (pSendContext->FirstSystemTimeStamp) { if (Info.ValidFields & TIME_STAMP_INFO) { RMDBGLOG((ENABLE, "FirstSystemTimeStamp from %s = %llu = 0x%llx (0x%llx)\n", string, Info.TimeStamp, Info.TimeStamp, Info.TimeStamp/2)); 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 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")); } } //fprintf( stderr, "send buffer5 0x%lx, sendbuffer 0x%lx length 0x%lx\n", decoder, send_buffer, send_length ); 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; RUASetProperty(pSendContext->pRUA, pSendContext->dcc_info->video_decoder, RMGenericPropertyID_InbandCommand, &InbandCmd, sizeof(InbandCmd), 0); 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; /* 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;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -