📄 play_audio.c
字号:
context.play_opt->disk_ctrl_low_level, context.play_opt->dmapool_count)); goto get_buffer; } fill_buffer: { RMint64 currentTime; RMuint64 stc; DCCSTCGetTime(context.dcc_info->pStcSource, &stc, context.audio_vop_tir); currentTime = (RMint64)stc; if ((currentTime > (RMint64)(context.lastSTC + context.audio_vop_tir)) || (currentTime < (RMint64)(context.lastSTC - context.audio_vop_tir))){ context.lastSTC = currentTime; currentTime /= context.audio_vop_tir; if (context.Duration) { RMDBGLOG((ENABLE, "stc time = %llu/%llu secs (%lld/100)\n", currentTime, context.Duration, (currentTime * 100)/context.Duration)); } else RMDBGLOG((ENABLE, "stc time = %llu secs\n", currentTime)); } } if (context.trickMode) { RMint64 currentTime; RMuint64 stc; DCCSTCGetTime(context.dcc_info->pStcSource, &stc, context.audio_vop_tir); currentTime = (RMint64)stc; status = RM_SKIP_DATA; // dont send the buffers if ((currentTime > (RMint64)(context.lastSTC + context.audio_vop_tir)) || (currentTime < (RMint64)(context.lastSTC - context.audio_vop_tir))){ context.lastSTC = currentTime; } currentTime /= context.audio_vop_tir; if ((currentTime > (RMint64)context.Duration) || (currentTime < 0)) { fprintf(stderr, "end of file\n"); status = RM_ERRORENDOFFILE; } usleep(100000); // to prevent high CPU usage } else { if (!context.transcodeEC3toAC3) {#ifndef WITH_BSAC status = RMReadFile(file, buf, bufferSize, &count);#else // WITH_BSAC if(context.audio_opt[0].Codec != AudioDecoder_Codec_BSAC) status = RMReadFile(file, buf, bufferSize, &count); else { RMuint32 val; RMuint8 *bsac_buf = buf; RMuint8 *bsac_bts_buf = context.bsac_bts_buf; bsac_bts_buf = (RMuint8*)(((RMuint32)bsac_bts_buf+3) & (~0x3));//libbsac only work with dword aligned buf status = RMReadFile(file, bsac_bts_buf, 2, &count); //fprintf(stdout, "%ld bytes are read ", count); if (status == RM_ERRORREADFILE || status == RM_ERRORENDOFFILE) goto audio_file_eos; file_offset += count; val = ((RMuint32)bsac_bts_buf[0]<<3) | (((RMuint32)bsac_bts_buf[1]>>5) & 0x07); // get 11 bits frame_length // fprintf(stdout, "Frame length = %lu\n", val); status = RMReadFile(file, bsac_bts_buf+2, val-2, &count); // get one frame data, if (status == RM_ERRORREADFILE) goto audio_file_eos; file_offset += count; bsac_frame_size = val; if(!bsac_get_info_done) { GetBitstreamInfo(bsac_bts_buf, context.audio_opt[0].SampleRate, (int*)&context.bsac_bitrate, (int*)&context.bsac_profile); RMDBGLOG((ENABLE, "MPEG-4 BSAC format\n sample_rate = %ld\t bit_rate = %ld kbps\n Profile = %ld \n", (RMuint32)context.audio_opt[0].SampleRate, (RMuint32)context.bsac_bitrate, (RMuint32)context.bsac_profile)); AllocDecBuff(BSAC_NCH); // BSAC init... bsac_get_info_done = 1; } // !!! One frame bit BSAC bits should be in bsac_bts_buf Mp4AudioDecodeFrame(bsac_bts_buf, context.bsac_bitrate, context.bsac_profile, BSAC_NCH, (BSAC_DSP_Info *)bsac_buf); DMA_buf_size = BSAC_DSP_LENGTH; //fprintf(stdout, "buf available = %ld bytes\n", DMA_buf_size); }#endif // WITH_BSAC } else if (!context.getNewBufferForEC3) status = RMReadFile(file, context.readBuffer, bufferSize, &count); else status = RM_OK; }#ifdef WITH_BSACaudio_file_eos:#endif // WITH_BSAC if (status == RM_ERRORREADFILE) { perror("reading file"); RUAReleaseBuffer(context.pDMA, buf); buf = NULL; goto cleanup; } else if (status == RM_ERRORENDOFFILE) { RMDBGLOG((ENABLE, "end of file\n")); RUAReleaseBuffer(context.pDMA, buf); buf = NULL; break; } else if (status == RM_SKIP_DATA) { RMDBGLOG((DISABLE, "skip data\n")); RUAReleaseBuffer(context.pDMA, buf); buf = NULL; continue; } else if (status != RM_OK) { RMDBGLOG((ENABLE, "unhandled error %s\n", RMstatusToString(status))); RUAReleaseBuffer(context.pDMA, buf); buf = NULL; break; } file_offset += count; if (context.FirstSystemTimeStamp) { RMDBGLOG((ENABLE, "first PTS : %lu\n", context.FirstPTS)); DCCSTCSetTime(dcc_info.pStcSource, context.FirstPTS, 90000); //DCCSTCPlay(dcc_info.pStcSource); context.FirstSystemTimeStamp = FALSE; Info.ValidFields = TIME_STAMP_INFO; Info.TimeStamp = context.FirstPTS; } else { pInfo = NULL; Info_size = 0; } if (RM_PSM_GetState(context.PSMcontext, &(context.dcc_info)) == RM_PSM_Prebuffering) RMDBGPRINT((ENABLE, ".")); if (context.transcodeEC3toAC3) { RMuint32 offset = 0; RMuint32 bufSize = (1<<context.play_opt->dmapool_log2size); RMuint32 sizeLeft = bufSize; RMuint32 frames = 0; if (!context.getNewBufferForEC3) { status = RMEC3SetInputBuffer(context.ec3TranscoderHandle, context.readBuffer, count); if (status == RM_ERROR) { RMDBGLOG((ENABLE, "error preparing data for ec3 transcoding lib\n")); goto cleanup; } else if (status == RM_SKIP_DATA) { RMDBGLOG((ENABLE, "not in sync yet\n")); goto fill_buffer; } else if (status == RM_NEED_MORE_DATA) { RMDBGLOG((ENABLE, "inputBuffer requires more data\n")); goto fill_buffer; } } context.getNewBufferForEC3 = FALSE; while(1) { RMuint32 frameSize = 0; frames++; status = RMEC3GetTranscodedFrame(context.ec3TranscoderHandle, buf + offset, sizeLeft, &frameSize, &count); RMDBGLOG((DISABLE, "status = (%s)\n", RMstatusToString(status))); RMDBGLOG((ENABLE, "[%lu] transcoded size %lu\n", frames, count)); offset += count; sizeLeft -= count; if (status == RM_BUFFERTOOSMALL) { RMDBGLOG((ENABLE, "buffer too small\n")); context.getNewBufferForEC3 = TRUE; break; } else if (status == RM_NEED_MORE_DATA) { RMDBGLOG((ENABLE, "incomplete frame\n")); break; } else if (status != RM_OK) { RMDBGLOG((ENABLE, "no more frames\n")); break; } PROCESS_KEY(TRUE, TRUE); update_hdmi_audio(context.dcc_info, &(context.audio_opt[0])); } RMDBGLOG((ENABLE, "total transcoded size %lu\n", offset)); count = offset; } if (!count) goto fill_buffer; #if DUMP_DATA RMDBGLOG((ENABLE, "dumping %lu bytes\n", count)); fwrite(buf, count, 1, context.saveFile);#else RMDBGLOG((DISABLE, "sending %lu bytes\n", count));#ifdef WITH_BSAC if(context.audio_opt[0].Codec == AudioDecoder_Codec_BSAC) count = DMA_buf_size;#endif //RMDBGLOG((ENABLE, "############## Audio audioInstances = %lu\n", context.audioInstances)); //RMDBGLOG((ENABLE, "############## Audio lsbfirst = %s\n", context.audio_opt->PcmCdaParams.MsbFirst?"FALSE":"TRUE")); // This is just an example to do byte swapping from 16bit little endian to big endian // Note: Apply it to AC3 and DTS test vectors, they are usually in little endian format. // David, 5/9/2007 if(context.audio_opt->Codec != AudioDecoder_Codec_PCM && context.audio_opt->PcmCdaParams.MsbFirst == FALSE) { RMuint32 i; for(i=0; i<count; i+=2) { RMuint8 tmp = buf[i]; buf[i] = buf[i+1]; buf[i+1] = tmp; } } while (DCCMultipleAudioSendData(dcc_info.pMultipleAudioSource, context.pDMA, buf, count, pInfo, Info_size, &lastOKinstance) != RM_OK) { struct RUAEvent e; struct DCCAudioSourceHandle audioHandle; check_prebuf_state(&context, 0); PROCESS_KEY(TRUE, TRUE); update_hdmi_audio(context.dcc_info, &(context.audio_opt[0])); if (lastOKinstance == -1) { fprintf(stderr, "cant wait on unknown instance!!\n"); goto cleanup; } status = DCCMultipleAudioSourceGetSingleDecoderHandleForInstance(dcc_info.pMultipleAudioSource, lastOKinstance, &audioHandle); if (status != RM_OK) goto cleanup; e.ModuleID = audioHandle.moduleID; e.Mask = RUAEVENT_XFER_FIFO_READY; while (RUAWaitForMultipleEvents(dcc_info.pRUA, &e, 1, SENDDATA_TIMEOUT_US, NULL) != RM_OK) { PROCESS_KEY(TRUE, TRUE); fprintf(stderr, "wait for xfer fifo ready\n"); update_hdmi_audio(context.dcc_info, &(context.audio_opt[0])); } } #endif /* Get profiling value */ { RMuint32 profile; struct DCCAudioSourceHandle audioHandle1; DCCMultipleAudioSourceGetSingleDecoderHandleForInstance(dcc_info.pMultipleAudioSource, 0, &audioHandle1); err = RUAGetProperty(dcc_info.pRUA, audioHandle1.moduleID, RMGenericPropertyID_Profile, &profile, sizeof(profile)); if (err == RM_OK) RMDBGLOG((ENABLE,"DSP Usage = %lu%%\n", profile)); } RUAReleaseBuffer(context.pDMA, buf); buf = NULL; } // while(1) check_prebuf_state(&context, 0); switch (context.play_opt->disk_ctrl_state) { case DISK_CONTROL_STATE_DISABLE: case DISK_CONTROL_STATE_SLEEPING: break; case DISK_CONTROL_STATE_RUNNING: if(context.play_opt->disk_ctrl_callback && context.play_opt->disk_ctrl_callback(DISK_CONTROL_ACTION_SLEEP) == RM_OK) context.play_opt->disk_ctrl_state = DISK_CONTROL_STATE_SLEEPING; break; } // in case we're still in pause state, wait for a key PROCESS_KEY(FALSE, TRUE); update_hdmi_audio(context.dcc_info, &(context.audio_opt[0])); //wait_eos: // fix bugct 1956 but will hurt HDD optimisation, find another way fprintf(stderr, "File ready %ld times, waiting for EOS\n", context.NTimes+1); err = WaitForEOS(&context, &context.actions); { RMuint64 stc; DCCSTCGetTime(dcc_info.pStcSource, &stc, 90000); RMDBGLOG((ENABLE, "Timer duration %llu ms\n", stc/90)); } if (err == RM_KEY_WHILE_WAITING_EOS) { RMDBGLOG((ENABLE, "command while waiting for EOS\n")); err = RM_OK; PROCESS_KEY(FALSE, FALSE); update_hdmi_audio(context.dcc_info, &(context.audio_opt[0])); //goto wait_eos; } else break; // EOS } if (context.play_opt->loop_count > 0) context.play_opt->loop_count --; /* if there is another loop, stop devices... */ if ((context.play_opt->loop_count > 0) || (context.play_opt->waitexit != TRUE) || (context.play_opt->infinite_loop)) Stop(&context, RM_DEVICES_AUDIO | RM_DEVICES_STC); context.NTimes++; } while ((context.play_opt->loop_count > 0) || (context.play_opt->infinite_loop)); goto cleanup; //////////////////////////////////////////////////////////////////////// // capture loop //////////////////////////////////////////////////////////////////////// capture_loop: // file capture loop while(1) { err = process_command(context.PSMcontext, &(context.dcc_info), &(context.actions)); if (RMFAILED(err)) { fprintf(stderr, "Error while processing key %d\n", err); break; } if ((context.actions.cmd == RM_QUIT) && (!context.actions.cmdProcessed)) { RMDBGLOG((ENABLE, "Got quit command\n")); break; } update_hdmi_audio(context.dcc_info, &(context.audio_opt[0])); while(RUAReceiveData(dcc_info.pRUA,audio_capture, context.pDMA, &buf, &size,NULL,NULL) != RM_OK) { struct RUAEvent e; e.ModuleID = audio_capture; e.Mask = SOFT_IRQ_EVENT_XFER_RECEIVE_READY; err = RUAWaitForMultipleEvents(dcc_info.pRUA, &e, 1, 1000 /*RECEIVEDATA_TIMEOUT_US*/, NULL); if (RMFAILED(err)){ //RMDBGLOG((ENABLE, "%d, %p 0x%x %d\n", audio_capture, context.pDMA, buf, size)); } } if(!buf) { RMDBGLOG((ENABLE, "error, RUAReceiveData returned no buffer!\n")); continue; }else{ if ((size > 0) && (context.fp_capture >= 0)) { fwrite(buf, size, 1, context.fp_capture); } RUAReleaseBuffer(context.pDMA, buf); } } goto cleanup_2; cleanup: if (file != NULL) RMCloseFile(file);#if DUMP_DATA RMDBGLOG((ENABLE, "\t\t\t***** CLOSE SAVE DATA FILE ****\n")); fclose(context.saveFile);#endif if (context.transcodeEC3toAC3) { if (context.ec3TranscoderHandle) RMEC3CloseTranscoder(context.ec3TranscoderHandle); if (context.readBuffer) RMFree(context.readBuffer); } if( context.play_opt->waitexit ) { if (context.audio_opt[0].AudioIn) { fprintf(stderr, "press q k
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -