/* DHL_AVCAP_Impl.c PHOENIX Driver HAL library AudioVideo decoding/capture/output implementation Copyright 2006 Digital STREAM Technology, Inc. All Rights Reserved $Id: DHL_AVCAP.c v1.00 2006/04 cafrii Exp $ */ #include "DHL_OSAL.h" #include "DHL_DBG.h" #include "DHL_Demux.h" #include "DHL_AVCAP.h" #include "DHL_AVCAP_Impl.h" #include "DHL_SYS_Impl.h" #include "bsettop.h" //#include "bchp_pcm.h" //#include "bmvd.h" #include "bavc.h" #include "bsettop_rfm.h" #include "bsettop_stream.h" #include "bsettop_smessage.h" #include "bsettop_display_priv.h" #include "bsettop_display.h" #include "bchp_vec_cfg.h" #include "bsettop.h" #include "bstd.h" #include "gist.h" #include "bchp_timer.h" #if COMMENT _______________(){} #endif // ch 3 or ch 4 output signal level // #define DHL_DEFAULT_RFM_VOLUME 70 // cafrii 060427 Callback type ¼±¾ðÀ» header·Î À̵¿. // cafrii 060522 À§Ä¡ À̵¿ tDHL_AVCALLBACK _DHL_AV_UserDataCallback; tDHL_AVCALLBACK _DHL_AV_ImportantVideoChangeCallback; tDHL_AVCALLBACK _DHL_AV_MajorVideoChangeCallback; tDHL_AVCALLBACK _DHL_AV_UserVideoChangeCallback; tDHL_AVCALLBACK _DHL_AV_VideoFreezeEndCallback; tDHL_AVCALLBACK _DHL_AV_DisplayFormatChangeCallback; tDHL_AVCALLBACK _DHL_AV_VideoScrambledCallback; #if COMMENT _______________(){} #endif int _DHL_AVCAP_DebugPrint(int level, char *fmt, ...); #define dprint _DHL_AVCAP_DebugPrint #if COMMENT _______________(){} #endif /* cafrii comment: in 3543, band is fixed as integer '0'. */ static bband_t band=0; static bdisplay_t display; static bdecode_t dhl_decode; static bdecode_window_t window; static bstream_t dhl_stream; static bstream_mpeg dhl_mpeg; //static bgraphics_t graphics; static baudio_decode_t audio; static int video_start = 0; static int audio_start = 0; // each flag represents video/audio playback status. #define DHL_UNUSED_PID 0 //megakiss 2014.06.30 changed the value 0x1fff to 0x0 so that audio only channel with fixed vidoe can be played // video decoder should be run even if audio only channel. // in such case, if video pid is out of range, // decoder not working at all and audio also failed. // so, we specify unused pid number as a default pid. // this should be range of valid pids. #if COMMENT _______________(){} #endif /* cafrii 081218 sequence header ³»¿ë ÀÚüÀÇ ºñ±³´Â MW¿¡¼­ ¼öÇàÇϹǷΠinterrupt ¹ß»ý ¿©ºÎÀ» ¾Ë·ÁÁÙ ¼ö ÀÖ´Â ÀÏ·Ã ¹øÈ£¸¸ Á¦°ø. */ static UINT32 g_dhl_seqhdr_generation_count = 0; BXVD_PictureParameterInfo g_dhl_stream_info; BOOL g_dhl_stream_info_valid; DHL_RESULT dhl_av_get_seq_hdr(tDHL_VideoSeqHdr *pSeq) { //static DHL_VIDEO_SEQHDR *prev_seq_hdr=NULL; BXVD_PictureParameterInfo info_0, *info = &info_0; int i; UINT32 flag; // neverdai ÇØ´çµÇ´Â °ÍÀÌ ¾ø´Â °æ¿ì, °¡Àå °¡±î¿î °ÍÀ¸·Î ġȯÇÑ´Ù. UINT8 arTable[][2]={ {BFMT_AspectRatio_eUnknown, aspectRatioUnknown}, {BFMT_AspectRatio_eSquarePxl, SAR_SquarePixel}, {BFMT_AspectRatio_e4_3, DAR_3_4}, {BFMT_AspectRatio_e16_9, DAR_9_16}, {BFMT_AspectRatio_e221_1, DAR_1_2_21}, {BFMT_AspectRatio_e15_9, DAR_9_16}, }; struct { enum BAVC_FrameRateCode bfrcode; MPEG_FRAME_RATE dhlfrcode; float frame_rate; } frCodeTable[]={ {BAVC_FrameRateCode_eUnknown,0,0}, {BAVC_FrameRateCode_e23_976,FRAMERATE_23_976,24*1000/1001.}, {BAVC_FrameRateCode_e24,FRAMERATE_24,24}, {BAVC_FrameRateCode_e25,FRAMERATE_25,25}, {BAVC_FrameRateCode_e29_97,FRAMERATE_29_97,30*1000/1001.}, {BAVC_FrameRateCode_e30,FRAMERATE_30,30}, {BAVC_FrameRateCode_e50,FRAMERATE_50,50}, {BAVC_FrameRateCode_e59_94,FRAMERATE_59_94,60*1000/1001.}, {BAVC_FrameRateCode_e60, FRAMERATE_60,60}, }; // cafrii 081218 disable interrupt. // to avoid seq hdr interrupt race condition. // flag = DHL_OS_DisableInterrupts(); //if (!g_dhl_stream_info_valid) { // seqhdr not ready yet. // printf("[111]\n\n\n"); // DHL_OS_RestoreInterrupts(flag); // return DHL_FAIL; //} if (pSeq==NULL) { // caller just want to know that seqhdr is ready or not. printf("[222]\n\n\n"); DHL_OS_RestoreInterrupts(flag); return DHL_OK; } *info = g_dhl_stream_info; // copy to local variable to minimize int disable pSeq->generationNumber = g_dhl_seqhdr_generation_count; DHL_OS_RestoreInterrupts(flag); // now, all 'info' is local variable and no worry of race condition. pSeq->horizontal_size=info->ulSourceHorizontalSize; pSeq->vertical_size=info->ulSourceVerticalSize; pSeq->aspect_ratio_information=aspectRatioUnknown; printf("[pSeq->horizontal_size(%d)]\n", pSeq->horizontal_size); printf("[pSeq->vertical_size(%d)]\n", pSeq->vertical_size); for(i=0; ieAspectRatio==arTable[i][0]) { pSeq->aspect_ratio_information=arTable[i][1]; break; } } pSeq->frame_rate_code = 0; for(i=0; ieFrameRateCode==frCodeTable[i].bfrcode) { pSeq->frame_rate_code=frCodeTable[i].dhlfrcode; pSeq->frame_rate=frCodeTable[i].frame_rate; break; } } printf("[pSeq->aspect_ratio_information(%d)]\n", pSeq->aspect_ratio_information); pSeq->bit_rate=0; pSeq->vbv_buffer_size=0; pSeq->constrained_parameter_flag=0; pSeq->MPEG2=0; pSeq->profile_and_level_indication=0; pSeq->progressive_sequence=info->bStreamProgressive; pSeq->chroma_format=0; // pSeq->low_delay=info->bLowDelay; #if 0 if(prev_seq_hdr==NULL) { //óÀ½ prev_seq_hdr=OS_Malloc(sizeof(DHL_VIDEO_SEQHDR)); pSeq->generationNumber=0; memcpy(prev_seq_hdr, pSeq, sizeof(*prev_seq_hdr)); } else { pSeq->generationNumber=prev_seq_hdr->generationNumber; #if 0 //ºñ±³... if(0!=memcmp(prev_seq_hdr, pSeq, sizeof(*prev_seq_hdr))) #else if((prev_seq_hdr->horizontal_size != pSeq->horizontal_size) || (prev_seq_hdr->vertical_size != pSeq->vertical_size) || (prev_seq_hdr->aspect_ratio_information != pSeq->aspect_ratio_information) || (prev_seq_hdr->frame_rate_code != pSeq->frame_rate_code) || (prev_seq_hdr->progressive_sequence != pSeq->progressive_sequence)) #endif { //º¯°æ °ªÀÌ ÀÖÀ½.. pSeq->generationNumber++; memcpy(prev_seq_hdr, pSeq, sizeof(*prev_seq_hdr)); } } printf("===========generatoin number.....(%d)\n", pSeq->generationNumber); #endif // 0 (*_DHL_AV_ImportantVideoChangeCallback)(eDHL_CB_VideoSeqHdr, &pSeq); return DHL_OK; } DHL_RESULT dhl_av_get_seq_hdr_info(void) { static bdecode_status status; tDHL_VideoSeqHdr *pSeq; int framerate; bdecode_get_status(dhl_decode,&status); pSeq->horizontal_size = status.source_width; pSeq->vertical_size = status.source_height; pSeq->aspect_ratio_information = status.video_aspect_ratio; pSeq->frame_rate_code =status.video_framerate; pSeq->MPEG2=status.video_format; if(status.video_framerate == FRAMERATE_25) framerate = 2500; else if(status.video_framerate == FRAMERATE_29_97) framerate = 2997; else if(status.video_framerate == FRAMERATE_30) framerate = 3000; else if(status.video_framerate == FRAMERATE_50) framerate = 5000; else if(status.video_framerate == FRAMERATE_59_94) framerate = 5994; else if(status.video_framerate == FRAMERATE_60) framerate = 6000; pSeq->frame_rate =framerate; pSeq->progressive_sequence = (status.bStreamProgressive) ? 1 : 0; (*_DHL_AV_ImportantVideoChangeCallback)(eDHL_CB_VideoSeqHdr, pSeq); } void dhl_av_disp_stop(BOOL onoff) { if(onoff) { BREG_Write32( GetREG(), BCHP_VEC_CFG_SDSRC_0_SOURCE, 0); } else { BREG_Write32( GetREG(), BCHP_VEC_CFG_SDSRC_0_SOURCE, 1); } } DHL_RESULT dhl_av_video_hide(BOOL bHide) { bdecode_config cfg; bdecode_get_config(dhl_decode,&cfg); if(bHide) cfg.mute=1; else cfg.mute=0; bdecode_set_config(dhl_decode,&cfg); return DHL_OK; } DHL_RESULT dhl_av_video_resize(INT32 x, INT32 y, UINT32 w, UINT32 h) { //TODO video resize°¡ Á¶ÀýµÉ ¼ö ÀÖ´ÂÁö . return DHL_OK; } DHL_RESULT dhl_av_video_freeze(BOOL bFreeze) { //video freeze ±â´É Á¦°øÇÏÁö ¾ÊÀ½. return DHL_OK; } DHL_RESULT dhl_av_get_video_pts(UINT32* p_vid_pts) { bdecode_status status; bdecode_get_status(dhl_decode,&status); *p_vid_pts = status.video_pts; return DHL_OK; } #if COMMENT _______________(){} #endif DHL_RESULT dhl_set_tuner_band(bband_t b) { band=b; return DHL_OK; } //refer to s_video_stream_types[] @ bsettop_decode.c static BAVC_VideoCompressionStd get_bcm_video_format(UINT16 uVidType) { BAVC_VideoCompressionStd bcm_type=BAVC_VideoCompressionStd_eMPEG2; switch(uVidType) { case eDHL_VIDEO_TYPE_MPEG1: bcm_type = BAVC_VideoCompressionStd_eMPEG1; break; case eDHL_VIDEO_TYPE_MPEG2: bcm_type = BAVC_VideoCompressionStd_eMPEG2; break; case eDHL_VIDEO_TYPE_MPEG4P2: bcm_type = BAVC_VideoCompressionStd_eMPEG4Part2; break; case eDHL_VIDEO_TYPE_H263: bcm_type = BAVC_VideoCompressionStd_eH263; break; case eDHL_VIDEO_TYPE_H264: bcm_type = BAVC_VideoCompressionStd_eH264; break; case eDHL_VIDEO_TYPE_VC1: bcm_type = BAVC_VideoCompressionStd_eVC1; break; case eDHL_VIDEO_TYPE_VC1SM: bcm_type = BAVC_VideoCompressionStd_eVC1SimpleMain; break; case eDHL_VIDEO_TYPE_DIVX311: //BKTODO: divx has two codecs: MPEG-4 Part2, H.264/MPEG-4 AVC... bcm_type = BAVC_VideoCompressionStd_eMPEG4Part2;//BAVC_VideoCompressionStd_eH264; break; case eDHL_VIDEO_TYPE_AVS: bcm_type = BAVC_VideoCompressionStd_eAVS; break; case eDHL_VIDEO_TYPE_DC2: bcm_type = BAVC_VideoCompressionStd_eMPEG2; break; default:// bcm_type = BAVC_VideoCompressionStd_eMPEG2; break; } return bcm_type; } /* caller can skip uAudPID at this time. (pid 0 for not specify) later, when dhl_av_audio_start called, pid is checked again and update if it is not set before. */ DHL_RESULT dhl_av_video_start(UINT16 uVidPID, UINT16 uPcrPID, UINT16 uAudPID, UINT16 vid_type ) { bresult berr; //printf("%s: vpid %x ppid %x apid %x vid_type %x\n", __FUNCTION__, uVidPID, uPcrPID, uAudPID, vid_type); if (video_start) { printf("!! video already run. vpid %x, pcr %x, apid %x\n", dhl_mpeg.video[0].pid, dhl_mpeg.pcr_pid, dhl_mpeg.audio[0].pid); bdecode_stop(dhl_decode); video_start = FALSE; } if (uPcrPID == 0) { printf("!! pcr pid invalid. set to 0x%x\n", uVidPID); uPcrPID = uVidPID; } // µ¿½Ã¿¡ audio/video pid µî·ÏÇÑ´Ù. // audio may already be started. so, check existing pid first. dhl_mpeg.video[0].pid = uVidPID; dhl_mpeg.video[0].format = get_bcm_video_format(vid_type); dhl_mpeg.pcr_pid = uPcrPID; // if user specifies audio pid, set it here. // actually, it does nothing but remeber pid values in 'stream'. // if (uAudPID && dhl_mpeg.audio[0].pid == DHL_UNUSED_PID) dhl_mpeg.audio[0].pid=uAudPID; if (dhl_stream) { printf("!! dhl_stream already open. close first\n"); bstream_close(dhl_stream); } dhl_stream = bstream_open(band, &dhl_mpeg); if(dhl_stream == NULL) { printf("\nERR: bstream_open failed\n\n"); return DHL_FAIL_CORE_DRIVER; } if ((berr = bdecode_start(dhl_decode, dhl_stream, window)) != b_ok) { printf("\nERR: bdecode_start failed\n\n"); bstream_close(dhl_stream); dhl_stream = NULL; return DHL_FAIL_CORE_DRIVER; } video_start = TRUE; return DHL_OK; } void dhl_av_video_start_end(UINT16 uVidPID, UINT16 uPcrPID, BOOL bSuccess) { if (bSuccess == FALSE) { printf("%s: video start failed\n", __FUNCTION__); // because we failed in decoding, (because of timeout or user cancel) // we stop bcm_decode. dhl_av_video_stop(uVidPID); } } void dhl_av_video_stop(UINT16 uVidPID) { //printf("%s: vpid %x\n\n\n", __FUNCTION__, uVidPID); if (video_start) { bdecode_stop(dhl_decode); } else printf("!! video not started.\n"); g_dhl_stream_info_valid = FALSE; dhl_mpeg.video[0].pid = DHL_UNUSED_PID; if (audio_start == FALSE) { // nothing run. dhl_mpeg.pcr_pid = 0; printf("\t now, nothing run.\n"); if (dhl_stream) { printf("\t close dhl_stream\n"); bstream_close(dhl_stream); dhl_stream = NULL; } } video_start = FALSE; } BOOL dhl_av_video_decoding_ready(void) { return dhl_av_get_seq_hdr(NULL)==DHL_OK?TRUE:FALSE; } #if COMMENT _______________(){} #endif DHL_RESULT dhl_av_disp_start(void) { return DHL_OK; } /* */ DHL_RESULT dhl_av_change_display_format(tDHL_DispPort output, tDHL_DispFormat format, tDHL_DispARC adjustment) { /*adjustment¸¸ ´ëÀÀÀÌ µÇ¸é µÉ °Í °°À½*/ dhl_av_change_display_adjustment(adjustment, NULL); return DHL_OK; } /* */ DHL_RESULT dhl_av_change_display_adjustment(tDHL_DispARC adj, DHL_WINRECT *rect) { bdisplay_settings settings; bdisplay_get(display, &settings); if(adj == eDHL_ARC_FULLSCREEN) { settings.sd_options = bdisplay_sd_output_options_full; bdisplay_set(display, &settings); } else if(adj == eDHL_ARC_LETTERBOX) { settings.sd_options = bdisplay_sd_output_options_widescreen; bdisplay_set(display, &settings); } else if(adj == eDHL_ARC_ZOOM2) { settings.sd_options = bdisplay_sd_output_options_zoom; bdisplay_set(display, &settings); } else { settings.sd_options = bdisplay_sd_output_options_full; bdisplay_set(display, &settings); } return DHL_OK; } /* it is recommended that audio is muted temporarily. */ void dhl_av_disp_change_rfm(int ch) { extern brfm_t g_sys_rfm; if (ch != 3 && ch != 4) return; if(ch==3) brfm_set_ch3(g_sys_rfm,0); else brfm_set_ch3(g_sys_rfm,1); } #if COMMENT _______________(){} #endif // logical volume level (0 ~ 100). // it is NOT the actual device volume level that is currently set. // if decoder mute is ON, device volume becomes zero, but logical volume is kept unchanged. int g_dhl_audio_volume; // this is boolean value. it tracks current audio mute status. int g_dhl_audio_muted = FALSE; // this is boolean value. it tracks current audio temp mute status. int g_dhl_audio_temp_muted = FALSE; UINT32 dhl_av_audio_frame_count(void) { bresult br; baudio_decode_status status; br = baudio_decode_get_status(audio, &status); if (br != b_ok) return 0; return status.pts; } //refer to s_audio_stream_types @ bdecode_audio_raaga.c static BAVC_AudioCompressionStd get_bcm_audio_format(tDHL_AudioCodingType AudStreamType) { BAVC_AudioCompressionStd aud_type; switch(AudStreamType) { case eDHL_AUDIO_TYPE_AC3: aud_type = BAVC_AudioCompressionStd_eAc3; break; case eDHL_AUDIO_TYPE_DTS: aud_type = BAVC_AudioCompressionStd_eDts; break; case eDHL_AUDIO_TYPE_MPEG_L1: aud_type = BAVC_AudioCompressionStd_eMpegL1; break; case eDHL_AUDIO_TYPE_MPEG_L2: aud_type = BAVC_AudioCompressionStd_eMpegL2; break; case eDHL_AUDIO_TYPE_MPEG_L3: aud_type = BAVC_AudioCompressionStd_eMpegL3; break; //BKTODO: AC3+ #if 0 case eDHL_AUDIO_TYPE_PCM: aud_type = BAVC_AudioCompressionStd_ePcm; break; case eDHL_AUDIO_TYPE_AAC_ADTS: aud_type = BAVC_AudioCompressionStd_eAacAdts; break; case eDHL_AUDIO_TYPE_AAC_LATM: aud_type = BAVC_AudioCompressionStd_eAacPlus; //BKTODO: BAVC_AudioCompressionStd_eAacLoas; break; case eDHL_AUDIO_TYPE_MPEG_1: case eDHL_AUDIO_TYPE_MPEG_2: case eDHL_AUDIO_TYPE_MPEG_4: #endif default: aud_type = BAVC_AudioCompressionStd_eMax;//default: no audio. break; } return aud_type; } /* audio decoder¸¦ ±âµ¿ÇÏ´Â ÇÔ¼ö. BCM¿¡¼­´Â audio, video¸¦ µ¿½Ã¿¡ Stop StartÇÒ¼ö ÀÖ´Â API Á¦°ø */ bstream_mpeg temp_mpeg; DHL_RESULT dhl_av_audio_start(UINT16 uAudPID, UINT16 uPcrPID, tDHL_AudioCodingType AudStreamType) { bresult berr; //printf("%s: apid %x, pcrpid %x\n", __FUNCTION__, uAudPID, uPcrPID); if (audio_start) { printf("!! audio already run. pid %x, pcr %x, vid %x. stop first..\n", dhl_mpeg.audio[0].pid, dhl_mpeg.pcr_pid, dhl_mpeg.video[0].pid); baudio_decode_stop(audio); audio_start = FALSE; } /* if stream is not run, we make new stream and start temporary decode. if stream is already run, we should match audio pid. if matched, its ok! */ //neverdai 080907 audio¸¦ ¹Ù²Ü ¶§ ºñµð¿À°¡ ±ô¹ÚÀÌ´Â ¹®Á¦ ¼öÁ¤ if (video_start == FALSE) { if (dhl_mpeg.pcr_pid != uPcrPID && dhl_mpeg.video[0].pid != DHL_UNUSED_PID) printf("!! pcr for video %x != pcr for audio %x\n", dhl_mpeg.pcr_pid, uPcrPID); // previous dhl_mpeg and stream should be reset. temp_mpeg.video[0].pid = dhl_mpeg.video[0].pid; temp_mpeg.audio[0].pid = uAudPID; temp_mpeg.audio[0].format = get_bcm_audio_format(AudStreamType); temp_mpeg.pcr_pid = uPcrPID; printf("\t stream open: audio %x, pcr %x, video %x\n", temp_mpeg.audio[0].pid, temp_mpeg.pcr_pid, temp_mpeg.video[0].pid); dhl_stream = bstream_open(band, &temp_mpeg); // now, stream and decode is working. update with new parameter. dhl_mpeg = temp_mpeg; } else if(dhl_mpeg.audio[0].pid != uAudPID || dhl_mpeg.pcr_pid != uPcrPID) { #if 0 dhl_stream->dhl_mpeg.audio[0].pid=uAudPID; dhl_stream->dhl_mpeg.pcr_pid=uPcrPID; #else//BK dhl_mpeg.audio[0].pid=uAudPID; dhl_mpeg.pcr_pid=uPcrPID; dhl_mpeg.audio[0].format = get_bcm_audio_format(AudStreamType); bstream_update_mpeg(dhl_stream, &dhl_mpeg); #endif } if ((berr = baudio_decode_start(audio, (void *)1, dhl_stream)) != b_ok) { printf("!! baudio_decode_start err %d\n", berr); return DHL_FAIL_CORE_DRIVER; } // cafrii 081006 add //BKTODO: bstream_force_update_pcr_pid(band, uPcrPID); audio_start = TRUE; return DHL_OK; } /* audio decodingÀÌ ¼º°øÀûÀ¸·Î ¼öÇà µÇ¾ú°Å³ª decodingÀÌ ¾î¶² ÀÌÀ¯·Î ½ÇÆÐÇÑ °æ¿ì µÚó¸® ÇÏ´Â ÇÔ¼ö. */ void dhl_av_audio_start_end(UINT16 uAudPID, UINT16 uPcrPID, BOOL bSuccess) { if (bSuccess == FALSE) { printf("%s: audio start failed\n", __FUNCTION__); // because we failed in decoding, (because of timeout or user cancel) // we stop audio by calling driver api. dhl_av_audio_stop(uAudPID); } } void dhl_av_audio_stop(UINT16 uAudPID) { //printf("[audio stop]%s: pid %x, video_run %d\n\n\n", __FUNCTION__, uAudPID, video_start); if (audio_start) { baudio_decode_stop(audio); } else printf("!! audio not started\n"); if (video_start == FALSE) { // nothing is running now. printf("\t now, nothing run. cur flag: v %d\n", video_start); if (dhl_stream) { printf("\t close stream..\n"); bstream_close(dhl_stream); dhl_stream = NULL; } } else printf("\t video still running\n"); dhl_mpeg.audio[0].pid = DHL_UNUSED_PID; audio_start = FALSE; } /* Audio mute½Ã SPDIF & LR µ¿½Ã Àû¿ë.. todo : µû·Î ºÐ¸®°¡ ÇÊ¿ä? */ DHL_RESULT dhl_av_audio_set_spdif_mode(tDHL_AudioIecOutFormat iecOutputMode) { return DHL_OK; } /* note! decoder mute should work independent to audio volume. */ DHL_RESULT dhl_av_audio_mute_control(tDHL_AudioMutePlace mutePlace, BOOL bMute) { baudio_decode_config config; if (mutePlace == eDHL_AUDIO_MUTE_DECODER) { if (bMute) { // mute on the audio decoder (or pcm engine) g_dhl_audio_muted = TRUE; baudio_decode_get_config(audio, &config); config.mute = (bMute == 0) ? false : true; baudio_decode_set_config(audio, &config); } else { g_dhl_audio_muted = FALSE; if (g_dhl_audio_temp_muted == FALSE) dhl_av_audio_set_volume(g_dhl_audio_volume); } } else if (mutePlace == eDHL_AUDIO_MUTE_GPIO) { // mute on external audio mute logic //BKTODO: dhl_sys_gpio_rw(GPIO_AUDIO_UNMUTE, bMute ? 0 : 1, TRUE); } else { return DHL_FAIL_NOT_AVAILABLE; } return DHL_OK; } DHL_RESULT dhl_av_audio_get_channel_info(BOOL *pbSurround, BOOL *pbStereo) { baudio_decode_config config; *pbSurround=FALSE; *pbStereo=FALSE; baudio_decode_get_config(audio, &config); #if 0//BKTODO:: if(config.acmod>=3) *pbSurround = TRUE; if(config.acmod==2) *pbStereo = TRUE; #endif return DHL_OK; } DHL_RESULT dhl_av_audio_set_delay(int nDelay, int nIecDelay) { return DHL_OK; } #if 0 DHL_RESULT dhl_av_audio_temp_mute(BOOL bMute) { if (bMute) { // mute on the audio decoder (or pcm engine) g_dhl_audio_temp_muted = TRUE; WriteReg32(BCHP_PCM_PB0_VOLUME, 0); } else { g_dhl_audio_temp_muted = FALSE; if (g_dhl_audio_muted == FALSE) dhl_av_audio_set_volume(g_dhl_audio_volume); } return DHL_OK; } #endif /* uVolLvl range is logical volume level and range of 0 ~ 100. */ #define DEVICE_VOL_MIN 0 #define DEVICE_VOL_MAX 32 /*refer to bcm ref. Vol_DB[]*/ #define LOGICAL_VOL_RANGE 100 DHL_RESULT dhl_av_audio_set_volume(UINT16 uVolLvl) { // UINT32 vol; // this is actual device volume. unsigned int level = uVolLvl*(DEVICE_VOL_MAX-DEVICE_VOL_MIN)/LOGICAL_VOL_RANGE; g_dhl_audio_volume = level; baudio_decode_config config; // cafrii 081217 bugfix, consider 'g_dhl_audio_temp_muted' if (g_dhl_audio_muted == FALSE && g_dhl_audio_temp_muted == FALSE) { baudio_decode_get_config(audio, &config); config.mute = false; config.left_volume = config.right_volume = level; baudio_decode_set_config(audio, &config); } return DHL_OK; } #if COMMENT ________________(){} #endif #if 1 // DYNAMIC_AC3_PARAM //#include "mips_sai_ddcd.h" // this header file is conflict on base type definition. /* // mode: Dolby Digital dynamic range compression modes enum { MIPS_SAI_DDCD_COMP_CA, // custom mode, analog dialnorm MIPS_SAI_DDCD_COMP_CD, // custom mode, digital dialnorm MIPS_SAI_DDCD_COMP_LO, // line out mode MIPS_SAI_DDCD_COMP_RF, // RF remod mode MIPS_SAI_DDCD_NUM_COMP_MODES }; // mono_mode: Dolby Digital dual-mono modes enum { MIPS_SAI_DDCD_DM_MODE_ST, // stereo MIPS_SAI_DDCD_DM_MODE_LM, // left mono MIPS_SAI_DDCD_DM_MODE_RM, // right mono MIPS_SAI_DDCD_DM_MODE_MM, // mixed mono MIPS_SAI_DDCD_NUM_DM_MODES }; // stereo_mode: Dolby Digital stereo modes enum { MIPS_SAI_DDCD_ST_MODE_AUTO, // auto-detect MIPS_SAI_DDCD_ST_MODE_LTRT, // dolby surround compatible (Lt/Rt) MIPS_SAI_DDCD_ST_MODE_LORO, // stereo (Lo/Ro) MIPS_SAI_DDCD_NUM_ST_MODES }; */ /* test: dhl_av_audio_set_ac3_params 3 1 0 2 // rf, mono dhl_av_audio_set_ac3_params 3 0 0 2 // rf, stereo dhl_av_audio_set_ac3_params 2 0 0 0 // line */ #define AUD_RESTART_AT_CHG 0 // it is risky to stop audio. // to do this, it should be guaranteed that ac3 task stop completely, but it is difficult. // instead, we provide parameter change on the fly. void dhl_av_audio_set_ac3_params(int mode, int mono, UINT32 mono_mode, UINT32 stereo_mode) { baudio_decode_config config; int changed = FALSE; #if AUD_RESTART_AT_CHG /* need to stop audio in order to set value */ if (audio_start) { printf("audio run. pid %x. stop first..\n", dhl_mpeg.audio[0].pid); baudio_decode_stop(audio); bos_sleep(1000); // should be long enough to consume all PES in ac3 task. who knows? } #endif baudio_decode_get_config(audio, &config); //printf("#### comp %d, mono %d, mmode %d, smode %d, acmod %d\n", // config.comp_mode, config.mono, config.mono_mode, config.stereo_mode, config.acmod); #if 0//BKTODO if (config.comp_mode != mode) { changed = true; config.comp_mode = mode; } if (config.mono != mono) { config.mono = mono; changed = true; } if (config.mono_mode != mono_mode) { config.mono_mode = mono_mode; changed = true; } if (config.stereo_mode != stereo_mode) { config.stereo_mode = stereo_mode; changed = true; } #endif baudio_decode_set_config(audio, &config); #if AUD_RESTART_AT_CHG if (audio_start) { printf("restart audio, pid %x\n", dhl_mpeg.audio[0].pid); baudio_decode_start(audio, (void *)1, dhl_stream); } #endif } #endif // DYNAMIC_AC3_PARAM #if COMMENT ________________(){} #endif DHL_RESULT dhl_av_exec_callback(tDHL_AVCallbackType CBType, DHL_VIDEO_CONTEXT *context, UINT32 param) { switch (CBType) { case eDHL_CB_VideoSeqHdr: // Sequence Haeder Information if (_DHL_AV_ImportantVideoChangeCallback) (*_DHL_AV_ImportantVideoChangeCallback)(CBType, param); break; case eDHL_CB_VideoUserData: // CC User Data Parser if (_DHL_AV_UserDataCallback) (*_DHL_AV_UserDataCallback)(CBType, param); break; case eDHL_CB_FirstVideoShow: if (_DHL_AV_MajorVideoChangeCallback) (*_DHL_AV_MajorVideoChangeCallback)(CBType, param); break; #if 0 //case DHL_CB_NOTIFY_VSTARTING: // g_dhlav.pAvStartingCallBack = (P_DHL_VDC_CALLBACK)pCallBack; // g_dhlav.uStartingUserContext = ClientCntx; // break; //case DHL_CB_NOTIFY_VSTOPPING: // g_dhlav.pAvStoppingCallBack = (P_DHL_VDC_CALLBACK)pCallBack; // g_dhlav.uStoppingUserContext = ClientCntx; // break; //case DHL_CB_NOTIFY_DISPINITIALIZE: // g_dhlav.pDispInitCallBack = (P_DHL_VDC_CALLBACK)pCallBack; // g_dhlav.uDispInitUserContext = ClientCntx; // break; case DHL_CB_NOTIFY_DISPCHANGE: if (_DHL_AV_DisplayFormatChangeCallback) (*_DHL_AV_DisplayFormatChangeCallback)(context, param); break; case DHL_CB_NOTIFY_USERVIDEOCHANGE: if (_DHL_AV_UserVideoChangeCallback) (*_DHL_AV_UserVideoChangeCallback)(context, param); break; case DHL_CB_NOTIFY_VIDEOFREEZEEND: if (_DHL_AV_VideoFreezeEndCallback) (*_DHL_AV_VideoFreezeEndCallback)(context, param); break; case DHL_CB_NOTIFY_VIDEOSCRAMBLED: if (_DHL_AV_VideoScrambledCallback) (*_DHL_AV_VideoScrambledCallback)(context, param); break; #endif default: break; } return DHL_OK; } void test_eia708_cb(unsigned char* data, /* the data buffer, containing data_len valid bytes */ int data_len, /* the number of valid bytes in data */ bool banalog ) { static tDHL_UserData dhl_ud; // DHL_VIDEO_CONTEXT *context=NULL; static unsigned char rcv_ud[CC_BUF_SIZE]; //UINT8 flags; //flags = bos_enter_critical(); if (data_len < 3 || data_len > CC_BUF_SIZE) { printf("%s:%d data_len %d > %d\n",__FUNCTION__,__LINE__,data_len,CC_BUF_SIZE); // bos_exit_critical(flags); return; } //memset(&dhl_ud, 0, sizeof(tDHL_UserData)); memcpy(rcv_ud,data,data_len); dhl_ud.pdata = rcv_ud; dhl_ud.hdr.payload_size = (UINT32)data_len; //bos_exit_critical(flags); (*_DHL_AV_UserDataCallback)(eDHL_CB_VideoUserData, &dhl_ud); } static void test_first_pts_callback() { printf("[test_first_pts_callback!!!]\n"); } static void test_seq_hdr_callback() { printf("[test_seq_hdr_callback!!!]\n"); } static void p_exec_callback(enum bdecode_callback_type cb_type, void *param) { DHL_VIDEO_CONTEXT *context=NULL; //neverdai ½ÇÁ¦·Î »ç¿ëÇÏ´Â °÷ÀÌ ¾øÀ½ // ÀúÀåÀ» ÇØ ³õÁö ¾Ê¾Æ¼­ ÇöÀç·Î¼­´Â Àü´Þ ºÒ°¡´É. // todo: // user param ±â¾ïÇØ¼­ Ãß°¡Çϱâ. UINT32 flag; bdecode_config cfg; tDHL_UserData *dhl_ud; switch(cb_type) { case bdecode_callback_type_userdata : bdecode_get_config(dhl_decode,&cfg); cfg.cc_enabled = 1; cfg.cc_callback = test_eia708_cb; bdecode_set_config(dhl_decode,&cfg); //dhl_av_exec_callback(eDHL_CB_VideoUserData, context, (UINT32)param); break; case bdecode_callback_type_vec_isr : break; case bdecode_callback_type_seq_hdr_isr : printf("===== seq_hdr_isr: count %u\n", g_dhl_seqhdr_generation_count); bdecode_get_config(dhl_decode,&cfg); cfg.seq_hdr_callback = dhl_av_get_seq_hdr_info; bdecode_set_config(dhl_decode,&cfg); //dhl_av_exec_callback(eDHL_CB_VideoSeqHdr, context, (UINT32)param); break; default : ; } } DHL_RESULT dhl_av_register_callback(tDHL_AVCALLBACK pCallBack, tDHL_AVCallbackType CBType) { DHL_RESULT dhlResult = DHL_OK; //printf("DHL_AV_PresetCallback(reg: type %d, fn 0x%x)\n", CBType, pCallBack); switch (CBType) { case eDHL_CB_VideoSeqHdr: //Sequence Haeder Information _DHL_AV_ImportantVideoChangeCallback = (tDHL_AVCALLBACK)pCallBack; bdecode_register_callback(bdecode_callback_type_seq_hdr_isr, p_exec_callback); break; case eDHL_CB_VideoUserData: //CC User Data Parser _DHL_AV_UserDataCallback = (tDHL_AVCALLBACK)pCallBack; bdecode_register_callback(bdecode_callback_type_userdata, p_exec_callback); break; case eDHL_CB_FirstVideoShow: //BKTODO: newcon3...? _DHL_AV_VideoFreezeEndCallback = (tDHL_AVCALLBACK)pCallBack; break; #if 0//BKTODO case DHL_CB_NOTIFY_DISPCHANGE: _DHL_AV_DisplayFormatChangeCallback = (P_DHL_VDC_CALLBACK)pCallBack; break; case DHL_CB_NOTIFY_MAJORCHANGE: _DHL_AV_MajorVideoChangeCallback = (P_DHL_VDC_CALLBACK)pCallBack; break; case DHL_CB_NOTIFY_USERVIDEOCHANGE: _DHL_AV_UserVideoChangeCallback = (P_DHL_VDC_CALLBACK)pCallBack; break; case DHL_CB_NOTIFY_VIDEOSCRAMBLED: _DHL_AV_VideoScrambledCallback = (P_DHL_VDC_CALLBACK)pCallBack; break; #endif default: break; } return dhlResult; } #if 0 // userdata interface is implemented in CCDDI. int g_dhl_ud_dump_count; void dhl_av_userdata_callback(void *param) { BAVC_USERDATA_info *ui = (BAVC_USERDATA_info *)param; #if 0 BAVC_USERDATA_Type_eSeq=1, /* User data coming in the Sequence Header */ BAVC_USERDATA_Type_eGOP, /* User data coming in the Gop Header */ BAVC_USERDATA_Type_ePicture, /* User Data coming in Picture Header */ #endif //if (ui->eUserDataType != BAVC_USERDATA_Type_ePicture) // return; if (g_dhl_ud_dump_count > 0) { #if 0 UINT8 *p = ui->pUserDataBuffer; printf("[UD] %d %d: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", ui->eUserDataType, ui->ui32UserDataBufSize, p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],p[9]); #else printf("*** userdata, type %d, len %d\n", ui->eUserDataType, ui->ui32UserDataBufSize); #endif memdump(ui->pUserDataBuffer, ui->ui32UserDataBufSize, "userdata"); g_dhl_ud_dump_count--; } #if 1 //DHL_AV_ExecuteCallback(DHL_CB_VDC_CCUDP, ??); #endif } void dhl_av_userdata_init() { // bcm driver ³»ÀÇ user data isr ÂÊ¿¡ callbackÀ» µî·ÏÇÑ´Ù. bdecode_register_callback(bdecode_callback_type_userdata, dhl_av_userdata_callback); } /* vbi out µÇ´Â line21 embeddingÀ» on/off ÇÑ´Ù. */ void dhl_av_vbi_enable_output(int enable) { bdecode_config cfg; bdecode_get_config(dhl_decode,&cfg); if (cfg.cc_enabled != enable) { cfg.cc_enabled = (enable == 0) ? 0 : 1; bdecode_set_config(dhl_decode,&cfg); } } #endif // 0 #if COMMENT ________________(){} #endif #if 0 DHL_RESULT dhl_av_command(int param, UINT32 value) { DHL_RESULT dhlResult = DHL_OK; switch (param) { case eDHL_AVCFG_GET_RMM: { void *handle; BMVD_VideoParams video_param; bdecode_get_channel_handle(&handle); BMVD_GetVideoParams(handle, &video_param); *(BOOL *)value = !!video_param.bEnableRMM; } break; default: dhlResult = DHL_FAIL_NOT_IMPLEMENTED; break; } return dhlResult; } #endif #if COMMENT ________________(){} #endif #if DHL_REGISTER_DEUBG_SYMBOLS static DHL_SymbolTable dhl_av_symbols[] = { //DHL_VAR_SYM_ENTRY(g_dhl_ud_dump_count), }; #endif #if COMMENT ________________(){} #endif //DHL_RESULT dhl_playtunerinit(); // ÇÔ¼ö À§Ä¡ À̵¿. // BCM AV Init Code // todo : OpenÇÏ´Â °úÁ¤±îÁö °°ÀÌ ³Ö´Â´Ù. ºÐ¸® ÇÒ°ÍÀÎÁö °í·ÁÇØ º¼°Í. // BCMÀº Init, Open, StartÇÏ´Â °úÁ¤ÀÌ ³ª´©¾îÁ® À־, Á»´õ ±¸ºÐÀÌ ÇÊ¿äÇÔ. Á¤¸® ÇÒ°Í. DHL_RESULT dhl_av_init(void) { bdisplay_settings settings; bdecode_config cfg; #if DHL_REGISTER_DEUBG_SYMBOLS DHL_DBG_RegisterSymbols(dhl_av_symbols, DHL_NUMSYMBOLS(dhl_av_symbols)); #endif display=bdisplay_open(B_ID(0)); // neverdai..comment 080908 TODO : interface¸¦ ÅëÇØ display¸¦ graphic¿¡ Àü´ÞÇÏ´Â °ÍÀÌ ÁÁÀ½ { extern void dhl_set_display(bdisplay_t); dhl_set_display(display); } // graphics = bgraphics_open(B_ID(0),display); dhl_decode=bdecode_open(0); smessage_init(NULL); // cafrii 080910 add. // bapp.c: bapp_init() Âü°íÇÔ. audio = baudio_decode_open(B_ID(0)); window=bdecode_window_open(0, display); bdisplay_get(display,&settings); // DHL_GPIO should be initialized before AV init. #if 0//BKTODO settings.output = dhl_sys_gpio_rw(GPIO_CH34_SW_IN, 0, 0) ? eRFM_CH4 : eRFM_CH3; settings.volume = DHL_DEFAULT_RFM_VOLUME; printf("## RFM switch is ch %d", settings.output == eRFM_CH3 ? 3 : 4); #endif bdisplay_set(display,&settings); bdecode_get_config(dhl_decode,&cfg); cfg.cc_enabled = 1; //cfg.cc_callback = test_eia708_cb; //cfg.first_pts_callback = test_first_pts_callback; cfg.seq_hdr_callback = dhl_av_get_seq_hdr_info; cfg.mute = 0; cfg.widescreen=0; // cfg.static_fields[0] = &s_field_info_0; // cfg.static_fields[1] = &s_field_info_1; bdecode_set_config(dhl_decode,&cfg); bstream_mpeg_init(&dhl_mpeg); // cafrii 080924, use our own reset value. dhl_mpeg.video[0].pid = DHL_UNUSED_PID; dhl_mpeg.audio[0].pid = DHL_UNUSED_PID; return DHL_OK; } DHL_RESULT dhl_av_terminate(void) { return DHL_OK; } #if COMMENT _______________(){} #endif /* Test Code */ #if 0 // RF 81 freq : 567000000 // RF 82 freq : 573000000 // RF 83 freq : 579000000 // RF 84 freq : 585000000 void TestVSB_Tuneinit(int freq) { #if 0 btuner_t tuner; btuner_vsb_params vsb; btuner_vsb_params_init(&vsb, tuner); vsb.mode = btuner_vsb_mode_vsb8; band = btuner_tune_vsb(tuner, freq, &vsb); if (!band) { printf("Can't tuning"); } #endif } /* RF, CH, PCR VID AUD 81 SBS 0x11 0x11 0x14 82 KBS2 0x21 0x21 0x24 83 KBS1 0x21 0x21 0x24 84 MBC 0x11 0x11 0x14 */ void TestVSB_Tuneset(int videopid, int audiopid, int pcrpid) { bstream_mpeg_init(&dhl_mpeg); dhl_mpeg.video[0].pid = videopid; dhl_mpeg.audio[0].pid = audiopid; dhl_mpeg.pcr_pid = pcrpid; dhl_stream = bstream_open(band, &dhl_mpeg); bdecode_start(dhl_decode, dhl_stream,window); } #endif