?? play_mp4.c
字號:
RMDBGLOG((ENABLE, "video DSI sent, size %ld\n", pSendContext->videodsiSize)); status = dump_data_into_file(pSendContext->play_opt, RMVDEMUX_VIDEO, pSendContext->videosample.buf, pSendContext->videosample.size, pSendContext->video_Info.TimeStamp, (pSendContext->video_Info.ValidFields & TIME_STAMP_INFO), pSendContext->video_Info.FirstAccessUnitPointer); if (RMFAILED(status)) { RMDBGLOG((ENABLE, "Cannot dump data %d\n", status)); return status; } if (pSendContext->videosample.buf != NULL) { RUAReleaseBuffer(pSendContext->pDMA, pSendContext->videosample.buf); pSendContext->videosample.buf = NULL; } pSendContext->sendVideoDSI = FALSE; return RM_OK;}static RMstatus Stop(struct SendMP4DataContext * pSendContext, RMuint32 devices){ RMstatus err = RM_OK; struct dcc_context *dcc_info = pSendContext->dcc_info; if (devices & RM_DEVICES_STC) { RMDBGLOG((ENABLE, "STOP: stc\n")); DCCSTCStop(dcc_info->pStcSource); } if (devices & RM_DEVICES_VIDEO) { if (pSendContext->SendVideoData) { RMDBGLOG((ENABLE, "STOP: video decoder\n")); err = DCCStopVideoSource(dcc_info->pVideoSource, DCCStopMode_LastFrame); if (RMFAILED(err)){ RMDBGLOG((ENABLE, "Error stopping video source %d\n", err)); return err; } pSendContext->lastVideoPTS = 0; pSendContext->lastSPUPTS = 0; pSendContext->sendVideoDSI = TRUE; } } if (devices & RM_DEVICES_AUDIO) { if ((pSendContext->SendAudioData) && (dcc_info->pMultipleAudioSource)) { RMDBGLOG((ENABLE, "STOP: multiple audio decoders\n")); err = DCCStopMultipleAudioSource(dcc_info->pMultipleAudioSource); if (RMFAILED(err)){ RMDBGLOG((ENABLE,"Error stopping multiple audio source %d\n", err)); return err; } pSendContext->lastAudioPTS = 0; } } if ((devices & RM_DEVICES_AUDIO) && (devices & RM_DEVICES_VIDEO)) { pSendContext->FirstSystemTimeStamp = TRUE; } if (pSendContext->monitorFIFOs) { RMDBGLOG((ENABLE, "FIFO STATUS after stop\n")); monitorFIFO(pSendContext, TRUE); RMDBGLOG((ENABLE, "**********************\n")); } return err;}static RMstatus Play(struct SendMP4DataContext * pSendContext, RMuint32 devices, enum DCCVideoPlayCommand mode){ RMstatus err = RM_OK; struct dcc_context *dcc_info = pSendContext->dcc_info; if (pSendContext->monitorFIFOs) { RMDBGLOG((ENABLE, "FIFO STATUS before play\n")); monitorFIFO(pSendContext, TRUE); RMDBGLOG((ENABLE, "**********************\n")); } if (devices & RM_DEVICES_STC) { RMDBGLOG((ENABLE, "PLAY: stc\n")); DCCSTCPlay(dcc_info->pStcSource); } if (devices & RM_DEVICES_VIDEO) { if (pSendContext->SendVideoData) { RMDBGLOG((ENABLE, "PLAY: video decoder\n")); err = DCCPlayVideoSource(dcc_info->pVideoSource, mode); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot play video decoder %d\n", err)); return err; } } send_videoDSI(pSendContext); } if (devices & RM_DEVICES_AUDIO) { if ((pSendContext->SendAudioData) && (dcc_info->pMultipleAudioSource)) { RMDBGLOG((ENABLE, "PLAY: multiple audio decoders\n")); err = DCCPlayMultipleAudioSource(dcc_info->pMultipleAudioSource); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot play video decoder %d\n", err)); return err; } } } return err;}// used for prebufferingstatic RMstatus Pause(struct SendMP4DataContext * pSendContext, RMuint32 devices){ RMstatus err = RM_OK; if (devices & RM_DEVICES_STC) { RMDBGLOG((ENABLE, "PAUSE: stc\n")); DCCSTCStop(pSendContext->dcc_info->pStcSource); } if (devices & RM_DEVICES_VIDEO) { if (pSendContext->SendVideoData) { RMDBGLOG((ENABLE, "PAUSE: video decoder\n")); err = DCCPauseVideoSource(pSendContext->dcc_info->pVideoSource); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot pause video decoder %d\n", err)); return err; } } } if (devices & RM_DEVICES_AUDIO) { if ((pSendContext->SendAudioData) && (pSendContext->dcc_info->pMultipleAudioSource)) { RMDBGLOG((ENABLE, "PAUSE: audio decoder\n")); err = DCCPauseMultipleAudioSource(pSendContext->dcc_info->pMultipleAudioSource); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot pause video decoder %d\n", err)); return err; } } } return err;}#define PLAY_TIMERS 0static RMstatus send_MP4_audio(struct SendMP4DataContext * pSendContext){ RMstatus status; RMuint64 pts; RMuint8 *buf = NULL; enum RM_PSM_State PlaybackStatus = RM_PSM_GetState(pSendContext->PSMcontext, &(pSendContext->dcc_info)); RMuint32 nextSampleSize = 0; if (PlaybackStatus == RM_PSM_Stopped) { return RM_OK; } if ((PlaybackStatus != RM_PSM_Playing) && (PlaybackStatus != RM_PSM_Paused) && (PlaybackStatus != RM_PSM_Prebuffering)) return RM_OK; if (pSendContext->audioTransferPending) goto send_data; if (pSendContext->play_opt->disk_ctrl_state == DISK_CONTROL_STATE_SLEEPING) RMDBGLOG((ENABLE, "trying to read from a suspended drive!!\n")); pSendContext->audiosample.buf = pSendContext->audioDMABuffer + pSendContext->audioDMABufferOffset; pSendContext->audiosample.size = (1<<pSendContext->dmaBufferSizeLog2) - pSendContext->audioDMABufferOffset; if (pSendContext->isAACaudioPayload) { buf = pSendContext->audiosample.buf; pSendContext->audiosample.size -= ADTS_HEADER_SIZE; pSendContext->audiosample.buf += ADTS_HEADER_SIZE; } if (!RMGetNextMP4Sample(pSendContext->mp4tA, &(pSendContext->audiosample), pSendContext->audiosample.size)) { RMDBGLOG((ENABLE,"Failed to get Audio sample -> end of audio stream\n")); pSendContext->audioEOS = TRUE; return RM_EOS; } if (!pSendContext->audiosample.size) RMDBGLOG((ENABLE, ">>> got an audio sample of size 0!\n")); RMGetMP4TrackNextSampleSize(pSendContext->mp4tA, &nextSampleSize); RMDBGLOG((DISABLE, "got audio sample of size %ld, nextSampleSize %lu, last audioDataSent %lu\n", pSendContext->audiosample.size, nextSampleSize, pSendContext->audioDataSent)); if (pSendContext->isAACaudioPayload) { FillAdtsHeader(buf, pSendContext->audiosample.size, pSendContext->AAC_SampleRateFromDSI, pSendContext->AAC_ChannelsFromDSI, pSendContext->AAC_ObjectIDFromDSI); pSendContext->audiosample.buf = buf; pSendContext->audiosample.size += ADTS_HEADER_SIZE; } if (pSendContext->audiosample.flags & MP4_CTS_VALID) { pSendContext->audio_Info.ValidFields = TIME_STAMP_INFO; pts = RMuint64from2RMuint32(pSendContext->audiosample.CTS_MSB, pSendContext->audiosample.CTS_LSB); pSendContext->audio_Info.TimeStamp = pts; if (pSendContext->audio_vop_tir != pSendContext->AudioCTSTimeScale) { pSendContext->audio_Info.TimeStamp = round_int_div(pts * pSendContext->audio_vop_tir, pSendContext->AudioCTSTimeScale); RMDBGLOG((DISABLE, "audio pts scaling! old %lld => %lld thru a factor %ld/%ld\n", pts, pSendContext->audio_Info.TimeStamp, pSendContext->audio_vop_tir, pSendContext->AudioCTSTimeScale)); } else RMDBGLOG((DISABLE, "setting pts to %llu\n", pts)); pSendContext->lastAudioPTS = (1000 * pSendContext->audio_Info.TimeStamp) / pSendContext->audio_vop_tir; } if (!pSendContext->SendAudioPts) { pSendContext->audio_Info.TimeStamp = 0; pSendContext->audio_Info.ValidFields = 0; } // happens only once if (!pSendContext->audio_ptsScalingMsg) { if (pSendContext->audio_vop_tir != pSendContext->AudioCTSTimeScale) { RMDBGLOG((ENABLE, ">>> audio pts scaling! thru a factor %ld/%ld\n", pSendContext->audio_vop_tir, pSendContext->AudioCTSTimeScale)); } else RMDBGLOG((ENABLE, ">>> no audio pts scaling required\n")); pSendContext->audio_ptsScalingMsg = TRUE; } if (pSendContext->FirstSystemTimeStamp && (pSendContext->audio_Info.ValidFields & TIME_STAMP_INFO)) { RMuint64 dummyPTS = pSendContext->audio_Info.TimeStamp; RMDBGLOG((ENABLE, "FirstSystemTimeStamp from audio = %lld(0x%llX) at %ld/sec = %llu s\n", dummyPTS, dummyPTS, pSendContext->audio_vop_tir, dummyPTS / pSendContext->audio_vop_tir)); pSendContext->FirstSystemTimeStamp = FALSE; RMDBGLOG((ENABLE, "setting timers\n")); DCCSTCSetTime(pSendContext->dcc_info->pStcSource, dummyPTS, pSendContext->audio_vop_tir);#if PLAY_TIMERS if ((PlaybackStatus != RM_PSM_Prebuffering) && (PlaybackStatus != RM_PSM_Paused) && (PlaybackStatus != RM_PSM_Stopped)) DCCSTCPlay(pSendContext->dcc_info->pStcSource);#endif } else if (pSendContext->FirstSystemTimeStamp) { if (pSendContext->forceTimersToZero) { RMDBGLOG((ENABLE, ">>> no pts, force timers to zero\n")); DCCSTCSetTime(pSendContext->dcc_info->pStcSource, 0, pSendContext->audio_vop_tir);#if PLAY_TIMERS if ((PlaybackStatus != RM_PSM_Prebuffering) && (PlaybackStatus != RM_PSM_Paused) && (PlaybackStatus != RM_PSM_Stopped)) DCCSTCPlay(pSendContext->dcc_info->pStcSource);#endif pSendContext->FirstSystemTimeStamp = FALSE; } else { RMDBGLOG((ENABLE, "waiting for first time stamp to be detected, timer not set!!!, audio skipped\n")); return RM_OK; } } RMDBGLOG((DISABLE, "about to send a packet audio dma 0x%08X, sample 0x%08X, size %ld, pts %lld(0x%llx) %s\n", pSendContext->pDMA, pSendContext->audiosample.buf, pSendContext->audiosample.size, pSendContext->audio_Info.TimeStamp, pSendContext->audio_Info.TimeStamp, (pSendContext->audio_Info.ValidFields & TIME_STAMP_INFO) ? "valid":"")); pSendContext->audioDMABufferOffset += pSendContext->audiosample.size; send_data: if (pSendContext->audiosample.size != 0) { if (pSendContext->SendAudioData) { RMint32 lastOKinstance; status = DCCMultipleAudioSendData(pSendContext->dcc_info->pMultipleAudioSource, pSendContext->pDMA, pSendContext->audiosample.buf, pSendContext->audiosample.size, &pSendContext->audio_Info, sizeof(pSendContext->audio_Info), &lastOKinstance); if (status != RM_OK) { if (status == RM_PENDING) { RMDBGLOG((ENABLE, "audio transfer pending\n")); pSendContext->audioTransferPending = TRUE; } return status; } pSendContext->audioTransferPending = FALSE; } status = dump_data_into_file(pSendContext->play_opt, RMVDEMUX_AUDIO, pSendContext->audiosample.buf, pSendContext->audiosample.size, pSendContext->audio_Info.TimeStamp, (pSendContext->audio_Info.ValidFields & TIME_STAMP_INFO), pSendContext->audio_Info.FirstAccessUnitPointer); if (RMFAILED(status)) { RMDBGLOG((ENABLE, "Cannot dump data %d\n", status)); } if (pSendContext->SendAudioData) { RMDBGLOG((SENDDBG, "sent a packet audio dma 0x%08X, sample 0x%08X, size %ld, total %ld, pts %lld(0x%llx) %s\n", pSendContext->pDMA, pSendContext->audiosample.buf, pSendContext->audiosample.size, pSendContext->audioDataSent, pSendContext->audio_Info.TimeStamp, pSendContext->audio_Info.TimeStamp, (pSendContext->audio_Info.ValidFields & TIME_STAMP_INFO) ? "valid":"")); } // required for prebuffering routine pSendContext->audioDataSent += pSendContext->audiosample.size; } else { RMDBGLOG((ENABLE, "got audio sample of size 0!\n")); } return RM_OK;} static RMstatus send_video_payload(struct SendMP4DataContext *pSendContext){ RMstatus status; RMuint32 sizeBuffer = (1 << pSendContext->dmaBufferSizeLog2); RMmp4Sample *sample = &(pSendContext->videosample); RMuint8 *videoDMAStartCodeBuffer; if (pSendContext->isH264) { // h264 streams packed into MP4 system files require startcode reinsertion. RMDBGLOG((H264_SC_DBG, "send_video_payload (size %lu)\n", sample->size)); if (sample->size < 3) RMDBGLOG((ENABLE, "warning read a sampleSize < 3\n")); else { RMuint32 nextSampleSize; RMGetMP4TrackNextSampleSize(pSendContext->mp4tV, &nextSampleSize); RMDBGLOG((H264_SC_DBG, "%02x %02x %02x %02x this sample size %6lu next %6lu flags %2lu\n", sample->buf[0], sample->buf[1], sample->buf[2], sample->buf[3], sample->size, nextSampleSize, sample->flags)); } if (sample->flags & MP4_AU_START) { pSendContext->h264sendStartCode = TRUE; pSendContext->h264readPacketSize = TRUE; /* clear the flag because if sending part of the sample returns pending, we'll get called again and we shouldn't send the startcode again */ sample->flags &= ~MP4_AU_START; } while (sample->size) { RMuint32 sizeToSend; RMDBGLOG((H264_SC_DBG, "available buffer count: %lu\n", RUAGetAvailableBufferCount(pSendContext->pDMA))); // send startcode if (pSendContext->h264sendStartCode) { // get a DMA buffer if (!pSendContext->startCodeDMABuffer) { get_buffer(pSendContext, &(pSendContext->startCodeDMABuffer)); if (pSendContext->processKeyResultValid) { RMDBGLOG((ENABLE, "a key was pressed during H264 startcode buffer wait")); // a key was pressed, return to main_loop to process it return RM_PENDING; } pSendContext->startCodeDMABufferOffset = 0; RMDBGLOG((DBG, "setting new buffer for video startcodes 0x%lx\n", (RMuint32)pSendContext->startCodeDMABuffer)); } videoDMAStartCodeBuffer = pSendContext->startCodeDMABuffer + pSendContext->startCodeDMABufferOffset; pSendContext->videoTransferPending = FALSE; // set StartCode (4bytes) RMuint32ToBeBuf(0x00000001, videoDMAStartCodeBuffer); if (pSendContext->SendVideoData) { // send startcode with PTS from the sample while (1) { status = RUASendData(pSendContext->pRUA, pSendContext->dcc_info->video_decoder, pSendContext->pDMA, videoDMAStartCodeBuffer, 4, &pSendContext->video_Info, sizeof(pSendContext->video_Info)); if (status == RM_OK) break; /* handle end of prebufferisation here */ else if (status == RM_PENDING) { struct RUAEvent e; check_prebuf_state(pSendContext, 0);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -