📄 play_capture_audio.c
字号:
RMstatus err; RMDBGLOG((FUNCNAME, "%s\n",__func__)); // Sanity checks if (pAudio == NULL) return RM_FATALINVALIDPOINTER; if (pAudio->dcc_info->pAudioSource == NULL) { return RM_OK; } if (pAudio->Setup.ExternalClk && pAudio->Setup.SampleRate && (pAudio->audio_opt != NULL)) { // Restore internal audio engine clock pAudio->audio_opt->ExternalClk = FALSE; pAudio->audio_opt->SampleRate = pAudio->Setup.SampleRate; err = apply_audio_engine_options(pAudio->dcc_info, pAudio->audio_opt); pAudio->audio_opt->ExternalClk = TRUE; } // stop capture err = capsam_audio_stop_capture(pAudio); // stop playback err = DCCStopAudioSource(pAudio->dcc_info->pAudioSource); if (RMFAILED(err)) { fprintf(stderr, "Cannot stop audio decoder! %s\n", RMstatusToString(err)); } // close playback err = DCCCloseAudioSource(pAudio->dcc_info->pAudioSource); pAudio->dcc_info->pAudioSource = NULL; if (RMFAILED(err)) { fprintf(stderr, "Error, cannot close audio decoder! %s\n", RMstatusToString(err)); } return err;}/* Initializes and starts capture, and playback of captured audio *//* This function needs audio_opt for the audio playback *//* If your application is using a different method to set up the audio decoder, follow this example for the passthrough */RMstatus capsam_audio_start_passthrough( struct capsam_audio_instance *pAudio){ RMstatus err; struct DCCAudioProfile audio_profile; RMDBGLOG((FUNCNAME, "%s\n",__func__)); // Sanity checks if (pAudio == NULL) return RM_FATALINVALIDPOINTER; if (pAudio->audio_opt == NULL) return RM_FATALINVALIDPOINTER; if (pAudio->dcc_info->pAudioSource) { capsam_audio_stop_passthrough(pAudio); } // Open AudioDecoder audio_profile.BitstreamFIFOSize = AUDIO_FIFO_SIZE; audio_profile.XferFIFOCount = XFER_FIFO_COUNT; audio_profile.DemuxProgramID = pAudio->Setup.AudioEngineID * 2; audio_profile.AudioEngineID = pAudio->Setup.AudioEngineID; audio_profile.AudioDecoderID = pAudio->audio_opt->AudioDecoderID; audio_profile.STCID = pAudio->Setup.STCTimerNumber; err = DCCOpenAudioDecoderSource(pAudio->dcc_info->pDCC, &audio_profile, &(pAudio->dcc_info->pAudioSource)); if (RMFAILED(err)) { fprintf(stderr, "Cannot open audio decoder! %s\n", RMstatusToString(err)); return err; } err = DCCGetAudioDecoderSourceInfo(pAudio->dcc_info->pAudioSource, &(pAudio->dcc_info->audio_decoder), &(pAudio->dcc_info->audio_engine), &(pAudio->dcc_info->audio_timer)); if (RMFAILED(err)) { fprintf(stderr, "Error getting audio decoder source information! %s\n", RMstatusToString(err)); return err; } pAudio->audio_opt->AudioEngineID = pAudio->Setup.AudioEngineID; pAudio->audio_opt->SampleRate = pAudio->Setup.SampleRate; //pAudio->audio_opt->ExternalClk = pAudio->Setup.ExternalClk; //pAudio->audio_opt->ExternalClkFreq = pAudio->Setup.ExternalClkFreq; print_parsed_audio_options(pAudio->audio_opt); // apply the sample rate, serial out status err = apply_audio_engine_options(pAudio->dcc_info, pAudio->audio_opt); if (RMFAILED(err)) { fprintf(stderr, "Error applying audio engine options! %s\n", RMstatusToString(err)); return err; } // apply the audio format - uninit, set codec, set specific parameters, init err = apply_audio_decoder_options(pAudio->dcc_info, pAudio->audio_opt); if (RMFAILED(err)) { fprintf(stderr, "Error applying audio_decoder_options! %s\n", RMstatusToString(err)); return err; } // Send Play command to audio playback err = DCCPlayAudioSource(pAudio->dcc_info->pAudioSource); if (RMFAILED(err)) { fprintf(stderr, "Cannot play audio decoder! %s\n", RMstatusToString(err)); return err; } // Start audio capture err = capsam_audio_start_capture(pAudio); if (RMFAILED(err)) { fprintf(stderr, "Error starting audio capture! %s\n", RMstatusToString(err)); return err; } return err;}/** Detetct audio codec from 86xx SI channel status and from Pc/Pe values parsed by audio uCode Input: stat->ChannelStatus stat->Pc stat->Pe pAudio->Setup.BitsPerSample (capture 16 or 24 bit from I2S) Fills in: pAudio->auto_detect_codec (TRUE: codec could not be determined) pAudio->audio_opt->Codec pAudio->audio_opt optional values for that codec pAudio->audio_opt->OutputChannels (PCM only)*//* This function needs audio_opt for the audio playback */RMstatus capsam_audio_get_codec_from_spdif_info( struct capsam_audio_instance *pAudio, struct AudioEngine_InputSPDIFStatus_type *stat){ RMDBGLOG((FUNCNAME, "%s\n",__func__)); // Sanity checks if (pAudio == NULL) return RM_FATALINVALIDPOINTER; if (pAudio->audio_opt == NULL) return RM_FATALINVALIDPOINTER; //fprintf(stderr, "get_spdif_codec(ChStat:0x%08lX, Pc:0x%02X, Pe:0x%02X)\n", stat->ChannelStatus, stat->Pc, stat->Pe); if (stat->ChannelStatus & 0x0002) { if ((stat->Pc & 0x1F) == 0) return RM_OK; // Null data, no change if ((stat->Pc & 0x1F) == 3) return RM_OK; // Pause data, no change if (RMunshiftBits(stat->Pc, 3, 13) != pAudio->Setup.CaptureBitstream) return RM_OK; // Not our stream } pAudio->auto_detect_codec = FALSE; if (stat->ChannelStatus & 0x0002) { fprintf(stderr, "Detected Codec: "); switch (stat->Pc & 0x1F) { default: fprintf(stderr, "Unknown or reserved codec type: %u\n", stat->Pc & 0x1F); if (0) case 0: fprintf(stderr, "Null Data\n"); if (0) case 3: fprintf(stderr, "Pause\n"); if (0) case 2: fprintf(stderr, "SMPTE 338M Time Stamp Data\n"); if (0) case 27: fprintf(stderr, "SMPTE 338M KLV Data\n"); if (0) case 28: fprintf(stderr, "SMPTE 338M Dolby E Data\n"); if (0) case 29: fprintf(stderr, "SMPTE 338M Captioning Data\n"); if (0) case 30: fprintf(stderr, "SMPTE 338M User Data\n"); pAudio->audio_opt->auto_detect_codec = TRUE; break; case 1: fprintf(stderr, "AC3\n"); pAudio->audio_opt->Codec = AudioDecoder_Codec_AC3; pAudio->audio_opt->Ac3Params.OutputChannels = Ac3_LR; break; case 4: fprintf(stderr, "MPEG 1 Layer 1\n"); pAudio->audio_opt->Codec = AudioDecoder_Codec_MPEG1; break; case 5: fprintf(stderr, "MPEG 1 Layer 2 or 3, MPEG 2 w/o extension\n"); pAudio->audio_opt->Codec = AudioDecoder_Codec_MPEG1; break; case 6: fprintf(stderr, "MPEG 2 w/ extension\n"); pAudio->audio_opt->Codec = AudioDecoder_Codec_MPEG1; break; case 7: fprintf(stderr, "MPEG 2 AAC\n"); pAudio->audio_opt->Codec = AudioDecoder_Codec_AAC; // TODO 0, 1, 2 or 3? pAudio->audio_opt->AACParams.InputFormat = 0; pAudio->audio_opt->AACParams.OutputChannels = Aac_LR; break; case 8: fprintf(stderr, "MPEG 2 Layer 1\n"); pAudio->audio_opt->Codec = AudioDecoder_Codec_MPEG1; break; case 9: fprintf(stderr, "MPEG 2 Layer 2\n"); pAudio->audio_opt->Codec = AudioDecoder_Codec_MPEG1; break; case 10: fprintf(stderr, "MPEG 2 Layer 3\n"); pAudio->audio_opt->Codec = AudioDecoder_Codec_MPEG1; break; case 11: fprintf(stderr, "DTS Type I\n"); pAudio->audio_opt->Codec = AudioDecoder_Codec_DTS; pAudio->audio_opt->DtsParams.OutputChannels = Dts_LR; break; case 12: fprintf(stderr, "DTS Type II\n"); pAudio->audio_opt->Codec = AudioDecoder_Codec_DTS; pAudio->audio_opt->DtsParams.OutputChannels = Dts_LR; break; case 13: fprintf(stderr, "DTS Type III\n"); pAudio->audio_opt->Codec = AudioDecoder_Codec_DTS; pAudio->audio_opt->DtsParams.OutputChannels = Dts_LR; break; case 14: fprintf(stderr, "ATRAC (unsupported)\n"); pAudio->auto_detect_codec = TRUE; //pAudio->audio_opt->Codec = ; break; case 15: fprintf(stderr, "ATRAC 2/3 (unsupported)\n"); pAudio->auto_detect_codec = TRUE; //pAudio->audio_opt->Codec = ; break; case 18: fprintf(stderr, "WMA Pro\n"); pAudio->audio_opt->Codec = AudioDecoder_Codec_WMAPRO; break; case 31: switch (stat->Pe) { default: fprintf(stderr, "Unknown extended data-type: %u\n", stat->Pe); pAudio->auto_detect_codec = TRUE; break; } break; } } else { fprintf(stderr, "Detected Codec: PCM\n"); pAudio->auto_detect_codec = FALSE; pAudio->audio_opt->Codec = AudioDecoder_Codec_PCM; if ((pAudio->Setup.CaptureSource == 0) && (pAudio->Setup.BitsPerSample >= 24)) { // 24 bit on I2S only pAudio->audio_opt->SubCodec = 0; pAudio->audio_opt->PcmCdaParams.ChannelAssign = PcmCda2_LR; pAudio->audio_opt->PcmCdaParams.BitsPerSample = 24; pAudio->audio_opt->PcmCdaParams.MsbFirst = ! pAudio->Setup.AudioInLSBfirst; } else { pAudio->audio_opt->SubCodec = 1; pAudio->audio_opt->LpcmVobParams.ChannelAssign = LpcmVob2_LR; pAudio->audio_opt->LpcmVobParams.BitsPerSample = 16; } pAudio->audio_opt->OutputChannels = Audio_Out_Ch_LR; // capture has only one I2S pin, equals 2 channels. spdif is always 2 ch. } return RM_OK;}/** set up auto-detection of audio codec. if capturing from SPDIF, start audio passthrough to enable parsing of Pc/Pd values from stream *//* This function needs audio_opt for the audio playback */RMstatus capsam_start_detect_audio( struct capsam_audio_instance *pAudio){ RMstatus err; struct AudioEngine_InputSPDIFStatus_type stat; RMDBGLOG((FUNCNAME, "%s\n",__func__)); // Sanity checks if (pAudio == NULL) return RM_FATALINVALIDPOINTER; if (pAudio->audio_opt == NULL) return RM_FATALINVALIDPOINTER; if (pAudio->Setup.CaptureSource > 0) { if (! pAudio->dcc_info->pAudioSource) { // capture has not yet been set up, start the capture without playback to parse Pc/Pe from SPDIF stream fprintf(stderr, "\n\n\nStarting dummy audio capture (AC3)\n\n\n\n"); pAudio->audio_opt->Codec = AudioDecoder_Codec_AC3; err = capsam_audio_start_passthrough(pAudio); } err = capsam_audio_get_spdif_channel_status(pAudio, &stat); if (RMFAILED(err)) stat.Pc = 0; } else { // only LPCM on I2S stat.ChannelStatus = 0; stat.Pc = 0; } pAudio->auto_detect_codec = TRUE; err = capsam_audio_get_codec_from_spdif_info(pAudio, &stat); if (RMSUCCEEDED(err) && (! pAudio->auto_detect_codec)) { pAudio->CurrChStat = stat.ChannelStatus; pAudio->CurrPc = stat.Pc; } return err;}/* transition to a new audio state, and perform the necessary actions of that transition */RMstatus capsam_audio_set_state( struct capsam_audio_instance *pAudio, enum audio_state audio_state){ RMstatus err = RM_OK; RMDBGLOG((FUNCNAME, "%s\n",__func__)); switch (audio_state) { case audio_state_off: // no audio present fprintf(stderr, " -- capsam_audio_set_state( OFF )\n"); if (pAudio->audio_state != audio_state_off) { err = capsam_audio_stop_passthrough(pAudio); } break; case audio_state_request: // start 200 mSec wait, check if audio is unstable during this wait fprintf(stderr, " -- capsam_audio_set_state( WAIT )\n"); if (pAudio->audio_state == audio_state_on) { err = capsam_audio_stop_passthrough(pAudio); } fprintf(stderr, "ACR PLL is presumed to be LOCKED\n"); pAudio->audio_pll_locked = TRUE; // might be set to FALSE by "PLL unlocked" interrupt during the 200 mSec, if PLL is unlocked pAudio->audio_guard_time = RMGetTimeInMicroSeconds(); break; case audio_state_on: // audio is stable and running fprintf(stderr, " -- capsam_audio_set_state( ON )\n"); pAudio->audio_guard_time = RMGetTimeInMicroSeconds(); if (pAudio->audio_state != audio_state_on) { err = capsam_audio_start_passthrough(pAudio); } break; } pAudio->audio_state = audio_state; return err;}/* handle steps of the audio state machine */RMstatus capsam_audio_check_state( struct capsam_audio_instance *pAudio){ RMstatus err = RM_OK; RMuint64 now; RMDBGLOG((FUNCNAME, "%s\n",__func__)); switch (pAudio->audio_state) { case audio_state_off: // no audio present //fprintf(stderr, " -- audio_state is ( OFF )\n"); break; case audio_state_request: // wait 200 mSec for stable audio //fprintf(stderr, " -- audio_state is ( WAIT )\n"); now = RMGetTimeInMicroSeconds(); if (RMCyclesElapsed64(pAudio->audio_guard_time, now) >= 200 * 1000) { if (pAudio->audio_pll_locked) { err = capsam_audio_set_state(pAudio, audio_state_on); } else { err = capsam_audio_set_state(pAudio, audio_state_request); } } break; case audio_state_on: // audio is stable and running //fprintf(stderr, " -- audio_state is ( ON )\n"); if (! pAudio->audio_pll_locked) { err = capsam_audio_set_state(pAudio, audio_state_request); } break; } return err;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -