📄 play_audio.c
字号:
SampleClock = 48000; f.PLL = PLLGen_cd_6; f.PLLOutput = PLLOut_1; // or _1 or _2 f.MaxM = 31; f.Clock = ClockSignal_RClk2; f.Frequency = SampleClock * 256; RUASetProperty(dcc_info->pRUA, PLL, RMPLLPropertyID_Frequency, &f, sizeof(f), 0); //printf("finish set RCLK2...\n");}#endif // Query Memory needed for AudioCapture Module dram_in.SerialInFIFOSize = AUDIO_FIFO_SIZE; dram_in.XferFIFOCount = XFER_FIFO_COUNT; err = RUAExchangeProperty(dcc_info->pRUA, audio_capture, RMAudioCapturePropertyID_DRAMSize, &dram_in, sizeof(dram_in), &dram_out, sizeof(dram_out)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "No memory available for Audio RISC Processor! %s\n", RMstatusToString(err))); return err; } // construct open profile memset(&capture_open, 0, sizeof(struct AudioCapture_Open_type)); capture_open.CaptureMode = capture_mode; capture_open.Delay = ((audio_opt->CaptureDelay) ? audio_opt->CaptureDelay : 1824) / 2; // Delay is 45000 Hz based start PTS if (audio_opt->CaptureSource == 0) { // Capture from I2S, 32 bit frames //capture_open.SI_CONF = 0x109; // 16 bit I2S frames capture_open.SI_CONF = 0x107 | // SerialIn Configuration, 32 bit frames (audio_opt->AudioInAlign << 3) | (audio_opt->AudioInLSBfirst ? 0x200 : 0x000); capture_source = AudioCapture_Source_I2S; } else { // Capture from SPDIF, always 16 bit frames if (audio_opt->CaptureSource == 1) {#if (EM86XX_CHIP >= EM86XX_CHIPID_TANGO15) // in 8622/24 Tango 1.5 and 8634 Tango 2 spdif is dedicated line, use it with source=1 capture_open.SI_CONF = 0x900; // capture from SI_SPDIF } else if (audio_opt->CaptureSource == 2) {#endif capture_open.SI_CONF = 0x100; // capture from SI_DATA } else { fprintf(stderr, "Error, wrong audio source: %lu\n", audio_opt->CaptureSource); return RM_ERROR; } capture_source = AudioCapture_Source_SPDIF; } capture_open.SI_CONF |= 0x80000000; // extended info in unused bits of SI_CONF if ((audio_opt->CaptureSource == 0) && (audio_opt->Codec == AudioDecoder_Codec_PCM)) { RMuint32 BitsPerSample; switch (audio_opt->SubCodec) { default: BitsPerSample = audio_opt->PcmCdaParams.BitsPerSample; break; case 1: BitsPerSample = audio_opt->LpcmVobParams.BitsPerSample; break; case 2: BitsPerSample = audio_opt->LpcmAobParams.BitsPerSampleGroup1; break; case 3: BitsPerSample = audio_opt->PcmCdaParams.BitsPerSample; break; } if (BitsPerSample >= 24) { capture_open.SI_CONF |= 0x40000000; // don't truncate 24 bit PCM samples to 16 bits } } // allocate memory only when it is file mode if(!capture_mode){ // memory allocation for capture module capture_open.SerialInFIFOSize = dram_in.SerialInFIFOSize; capture_open.XferFIFOCount = dram_in.XferFIFOCount; // allocate cached memory capture_open.CachedSize = dram_out.CachedSize; if (capture_open.CachedSize > 0){ capture_open.CachedAddress = RUAMalloc(dcc_info->pRUA, 0, RUA_DRAM_CACHED, capture_open.CachedSize); printf("audio capture cached addr: 0x%08lX, size 0x%08lX, end: 0x%08lX\n", capture_open.CachedAddress, capture_open.CachedSize, capture_open.CachedAddress + capture_open.CachedSize); p_context->capture_cached_addr = (RMuint32)capture_open.CachedAddress; } else { capture_open.CachedAddress = 0; } // allocate uncached memory capture_open.UncachedSize = dram_out.UncachedSize; if (capture_open.UncachedSize > 0){ capture_open.UncachedAddress = RUAMalloc(dcc_info->pRUA, 0, RUA_DRAM_UNCACHED, capture_open.UncachedSize); printf("audio capture uncached addr: 0x%08lX, size 0x%08lX, end: 0x%08lX\n", capture_open.UncachedAddress, capture_open.UncachedSize, capture_open.UncachedAddress + capture_open.UncachedSize); p_context->capture_uncached_addr = capture_open.UncachedAddress; } else { capture_open.UncachedAddress = 0; } } err = RUASetProperty(dcc_info->pRUA, audio_capture, RMAudioCapturePropertyID_Open, &capture_open, sizeof(capture_open), 0); if (RMFAILED(err)) { fprintf(stderr, "Error opening audio capture module!\n"); return err; } err = RUASetProperty(dcc_info->pRUA, audio_capture, RMAudioCapturePropertyID_Source, &capture_source, sizeof(capture_source), 0); if (RMFAILED(err)) { fprintf(stderr, "Error setting audio capture source!.\n"); return err; } capture_type = audio_opt->CaptureType; err = RUASetProperty(dcc_info->pRUA, audio_capture, RMAudioCapturePropertyID_SpdifDataType, &capture_type, sizeof(capture_type), 0); if (RMFAILED(err)) { fprintf(stderr, "Error setting audio capture type!.\n"); return err; } err = RUASetProperty(dcc_info->pRUA, audio_capture, RMAudioCapturePropertyID_Capture, &cmd, sizeof(cmd), 0); if (RMFAILED(err)) fprintf(stderr, "Error sending capture ON command.\n"); // open buffer pool only when file capture mode if(!capture_mode){ err = RUAOpenPool(dcc_info->pRUA, audio_capture, p_context->play_opt->dmapool_count, p_context->play_opt->dmapool_log2size, RUA_POOL_DIRECTION_RECEIVE, &(p_context->pDMA)); if (RMFAILED(err)){ RMDBGLOG((ENABLE, "Error while creating DMA Pool for receiving! %s\n", RMstatusToString(err))); } } return err;}static RMstatus StopAudioCapture(struct dcc_context *dcc_info, RMuint32 audio_capture, struct audio_context* p_context){ enum AudioCapture_Capture_type cmd = AudioCapture_Capture_Off; RMuint32 temp = 0; RMstatus err; err = RUASetProperty(dcc_info->pRUA, audio_capture, RMAudioCapturePropertyID_Capture, &cmd, sizeof(cmd), 0); if (RMFAILED(err)) fprintf(stderr, "Error sending capture OFF command.\n"); err = RUASetProperty(dcc_info->pRUA, audio_capture, RMAudioCapturePropertyID_Close, &temp, sizeof(temp), 0); if (RMFAILED(err)) { fprintf(stderr, "Error closing capture module!\n"); return err; } if(p_context->capture_cached_addr){ RUAFree(dcc_info->pRUA, p_context->capture_cached_addr); p_context->capture_cached_addr = 0; } if(p_context->capture_uncached_addr){ RUAFree(dcc_info->pRUA, p_context->capture_uncached_addr); p_context->capture_uncached_addr = 0; } if(p_context->fp_capture){ fclose(p_context->fp_capture); p_context->fp_capture = NULL; } return err;}static RMstatus Stop(struct audio_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_AUDIO) { if (pSendContext->dcc_info->pMultipleAudioSource) { if (pSendContext->play_opt->disk_ctrl_state != DISK_CONTROL_STATE_DISABLE) { while (pSendContext->dmabuffer_index > 0) { pSendContext->dmabuffer_index--; if (pSendContext->dmabuffer_array[pSendContext->dmabuffer_index]) { RMDBGLOG((ENABLE, "releasing buffer index %lu buffer %p\n", pSendContext->dmabuffer_index, pSendContext->dmabuffer_array[pSendContext->dmabuffer_index])); RUAReleaseBuffer(pSendContext->pDMA, pSendContext->dmabuffer_array[pSendContext->dmabuffer_index]); } } } RMDBGLOG((ENABLE, "STOP: multiple audio decoders\n")); err = DCCStopMultipleAudioSource(pSendContext->dcc_info->pMultipleAudioSource); if (RMFAILED(err)){ RMDBGLOG((ENABLE, "Error stopping audio source %d\n", err)); return err; } pSendContext->audio_decoder_initialized = FALSE; pSendContext->FirstSystemTimeStamp = TRUE; pSendContext->FirstPTS = 0; /* because DMAPool and BitstreamFIFO are the same in standalone when using elementary streams we need to reset the pool */ 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 Play(struct audio_context * pSendContext, RMuint32 devices){ RMstatus err = RM_OK; if (devices & RM_DEVICES_STC) { RMDBGLOG((ENABLE, "PLAY: stc\n")); DCCSTCPlay(pSendContext->dcc_info->pStcSource); } if (devices & RM_DEVICES_AUDIO) { if (pSendContext->dcc_info->pMultipleAudioSource) { if (!pSendContext->audio_decoder_initialized) { pSendContext->audio_decoder_initialized = TRUE; } RMDBGLOG((ENABLE, "PLAY: multiple audio decoders\n")); err = DCCPlayMultipleAudioSource(pSendContext->dcc_info->pMultipleAudioSource); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot play audio decoder %d\n", err)); return err; } } } return err;}// used for prebufferingstatic RMstatus Pause(struct audio_context * 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_AUDIO) { if (pSendContext->dcc_info->pMultipleAudioSource) { RMDBGLOG((ENABLE, "PAUSE: multiple audio decoders\n")); err = DCCPauseMultipleAudioSource(pSendContext->dcc_info->pMultipleAudioSource); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot play audio decoder %d\n", err)); return err; } } } return err;}static RMstatus seek(struct audio_context *pSendContext, RMuint32 time_sec){ RMuint64 bytesSec = pSendContext->fileSize / pSendContext->Duration; RMuint32 timeSec = 0; RMuint64 seekPos; RMuint32 audioPTS; RMstatus err; struct DCCAudioSourceHandle audioHandle; timeSec = time_sec; seekPos = timeSec * bytesSec; RMDBGLOG((ENABLE, "seek to %lu s\n", timeSec)); // we assume multiple decoders are in sync DCCMultipleAudioSourceGetSingleDecoderHandleForInstance(pSendContext->dcc_info->pMultipleAudioSource, 0, &audioHandle); err = RUAGetProperty(pSendContext->dcc_info->pRUA, audioHandle.moduleID, RMAudioDecoderPropertyID_CurrentPTS, &audioPTS, sizeof(audioPTS)); if (err != RM_OK) { RMDBGLOG((ENABLE, "error getting current pts property for audio, error %lu\n", (RMuint32)err)); return RM_ERROR; } RMDBGLOG((ENABLE, "current audio pts %lu(0x%08lx)\n", audioPTS, audioPTS)); Stop(pSendContext, RM_DEVICES_AUDIO); RMDBGLOG((ENABLE, ">> %llu bytes/sec, seekto %lu sec => pos %llu\n", bytesSec, timeSec, seekPos)); // pcm should start at the correct sample position if (pSendContext->audio_opt[0].Codec == AudioDecoder_Codec_PCM) { seekPos -= seekPos % pSendContext->PCMblockSize; RMDBGLOG((ENABLE, "PCM audio blockSize %lu, new seekPos %lld\n", pSendContext->PCMblockSize, seekPos)); } if (pSendContext->skipFirstNBytes) { RMDBGLOG((ENABLE, "adjust seek pos due to skipping of %lu bytes\n", pSendContext->skipFirstNBytes)); seekPos += pSendContext->skipFirstNBytes; } RMSeekFile(pSendContext->f_bitstream, seekPos, RM_FILE_SEEK_START); DCCSTCSetTime(pSendContext->dcc_info->pStcSource, timeSec*pSendContext->audio_vop_tir, pSendContext->audio_vop_tir); pSendContext->FirstSystemTimeStamp = TRUE; pSendContext->FirstPTS = timeSec*pSendContext->audio_vop_tir; Play(pSendContext, RM_DEVICES_AUDIO); RM_PSM_SetState(pSendContext->PSMcontext, &(pSendContext->dcc_info), RM_PSM_Playing); return RM_OK;}static RMstatus resumeFromTrick(struct audio_context *pSendContext){ RMuint64 stc; RMuint32 timeSec; DCCSTCGetTime(pSendContext->dcc_info->pStcSource, &stc, pSendContext->audio_vop_tir); RMDBGLOG((ENABLE, "resume from trick at %llu s\n", stc/pSendContext->audio_vop_tir)); timeSec = (RMuint32) (stc / pSendContext->audio_vop_tir); seek(pSendContext, timeSec); return RM_OK;}static void check_prebuf_state(struct audio_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/senddata force quitting prebuffering state */ quit_prebuf = ((buffersize == 0) || ((pSendContext->play_opt->prebuf_max > 0) && (pSendContext->prebufferedBytes >= pSendContext->play_opt->prebuf_max))) ? TRUE : FALSE; pSendContext->prebufferedBytes += buffersize; if (quit_prebuf) { RMDBGLOG((ENABLE, "exit prebuffering state, enter play state (bufsize %lu, prebuffered %lu)\n", buffersize, pSendContext->prebufferedBytes)); fprintf(stderr, "now playing\n"); RM_PSM_SetState(pSendContext->PSMcontext, &(pSendContext->dcc_info), RM_PSM_Playing); Play(pSendContext, RM_DEVICES_STC | RM_DEVICES_AUDIO); pSendContext->prebufferedBytes = 0; }}#ifdef WITH_MONOint main_audio(struct mono_info *mono){#elseint main(int argc, char *argv[]){ /*for MONO compatibility, always access these variables through the global pointers*/ struct playback_cmdline playback_options; /*access through play_opt*/ struct audio_cmdline audio_options[MAX_AUDIO_DECODER_INSTANCES]; /*access through audio_opt*/ struct dh_context dh_info = {0,};#endif RMstatus err = RM_ERROR; RMfile file = NULL; // Error code for open struct dcc_context dcc_info = {0,}; RMuint32 file_offset = 0; RMuint32 audio_capture; struct audio_context context = {0,}; struct RM_PSM_Context PSMContext;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -