⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 play_capture_hdmi.c

📁 1. 8623L平台
💻 C
📖 第 1 页 / 共 5 页
字号:
		 88200, 768000,  96000,      0, 		 176400, 12000, 192000,      0	};	static const RMuint32 fs_tab_hdmi[16] = {		 44100,      0,  48000,  32000, 		     0,      0,      0,      0, 		 88200, 768000,  96000,      0, 		 176400,     0, 192000,      0	};	RMDBGLOG((FUNCNAME, "%s\n",__func__));		// Sanity checks	if (pHDMI == NULL) return RM_FATALINVALIDPOINTER;	if (pSamplingRate == NULL) return RM_FATALINVALIDPOINTER;		// remember previous SamplingRate	prev_fs = *pSamplingRate;		// default SamplingRate to 0	*pSamplingRate = 0;		// transmission is not in HDMI mode, no audio expected	if (pHDMI->hdmi_mode != capsam_hdmi_mode_HDMI){		printf("XXXXXXXXXXX not HDMI mode\n");		return RM_OK;	}	// chip specific processing	switch (pHDMI->chip) {	case capsam_chip_SiI9031:		// start audio procesing		err = capsam_SiI9031_init_audio_clock(pHDMI->pSiI9031, TRUE, 256);  // TODO		if (RMFAILED(err)) return err;				// read channel status		err = capsam_SiI9031_get_audio_channel_status(pHDMI->pSiI9031, ch_stat);		if (RMFAILED(err)) return err;		fprintf(stderr, "[hdmi] audio channel status [39:0]: %02X.%02X.%02X.%02X.%02X\n", ch_stat[4], ch_stat[3], ch_stat[2], ch_stat[1], ch_stat[0]);				// read N/CTS pair, CTS = (f(TMDS clk) * N) / (128 * f(s))		err = capsam_SiI9031_get_audio_n_cts(pHDMI->pSiI9031, &n, &cts, &fs_n_cts);		if (RMFAILED(err)) return err;		fprintf(stderr, "[hdmi] N/CTS: %lu/%lu\n", n, cts);				break;	case capsam_chip_AD9380:		RMDBGLOG((ENABLE, "XXXXXXXXXXXXXXXXXXXXXXX %s\n",__func__));		err = capsam_AD9380_get_audio_channel_status(pHDMI->pAD9380, ch_stat);		break;	default:		return RM_ERROR;	}		// not consumer use, or not mode 00	if ((ch_stat[0] & 0xC1) != 0x00) return RM_OK;		// extract fs tag from channel status	pclk = ch_stat[3] & 0x0F;		// no audio present	if (pclk == 1) return RM_OK;		if (n && cts) {		// match approximate SamplingRate from pixel clock and N/CTS to nearest valid sample rate		if (fs_n_cts) {			RMuint32 i, fs, fs_mult, fs_mod;			static const RMuint32 fs_base[] = {8000, 11025, 12000, 32000, 44100, 48000};						fprintf(stderr, "[hdmi] Audio fs from N/CTS: %lu (Approx.)\n", fs_n_cts);			fs = fs_n_cts;			for (i = (obey_hdmi ? 3 : 0); i < sizeof(fs_base) / sizeof(RMuint32); i++) {				fs_mult = fs / fs_base[i];				fs_mod = fs % fs_base[i];				if (fs_mod < (fs_base[i] / 8)) {					fs_n_cts = fs_base[i] * fs_mult;					break;				} else if (fs_mod > (fs_base[i] * 7 / 8)) {					fs_mult++;					fs_n_cts = fs_base[i] * fs_mult;					break;				}			}			fprintf(stderr, "[hdmi] Audio fs from N/CTS: %lu\n", fs_n_cts);		}				// SamplingRate from fs tag		*pSamplingRate = obey_hdmi ? fs_tab_hdmi[pclk] : fs_tab[pclk];		if (*pSamplingRate != prev_fs) {			fprintf(stderr, "[hdmi] Audio fs from tag: %s, tag=0x%01lX\n", 				(pclk == 0) ? "44.1 kHz" : 				(pclk == 1) ? "<not indicated>" : 				(pclk == 2) ? "48 kHz" : 				(pclk == 3) ? "32 kHz" : 				(pclk == 4) ? "22.05 kHz <invalid>" : 				(pclk == 5) ? "11.025 kHz <invalid>" : 				(pclk == 6) ? "24 kHz <invalid>" : 				(pclk == 7) ? "16 kHz <invalid>" : 				(pclk == 8) ? "88.2 kHz" : 				(pclk == 9) ? "768 kHz" : 				(pclk == 10) ? "96 kHz" : 				(pclk == 11) ? "<reserved>" : 				(pclk == 12) ? "176.4 kHz" : 				(pclk == 13) ? "12 kHz <invalid>" : 				(pclk == 14) ? "192 kHz" : 				(pclk == 15) ? "<unknown>" : "-", pclk);		}				// mismatch between fs tag and N/CTS, use the latter		if (fs_n_cts && (*pSamplingRate != fs_n_cts)) {			fprintf(stderr, "[hdmi] ERROR: fs tag in channel status does not match frequency from N/CTS PLL!!!\n");			*pSamplingRate = fs_n_cts;		}	} else {		// no audio		*pSamplingRate = 0;	}		if (*pSamplingRate != prev_fs) {		fprintf(stderr, "\n\n\t[hdmi] Audio fs: %lu", *pSamplingRate / 1000);		if (*pSamplingRate % 1000) {			fprintf(stderr, ".%03lu", *pSamplingRate % 1000);		}		fprintf(stderr, " kHz\n\n\n");	}		return RM_OK;}/*** Mode Detection functions ***//* Detect HDMI or DVI mode from the chip, signaling necessary actions */RMstatus capsam_hdmi_detect_mode(	struct capsam_hdmi_instance *pHDMI, 	enum capsam_hdmi_mode *pHDMIMode, 	RMbool *pUpdateAVI,    // need to handle AVI Info Frame again	RMbool *pUpdateAudio,  // need to re-start audio	RMbool *pUpdateVideo)  // need to detect video mode{	RMstatus err;	enum capsam_hdmi_mode hdmi_mode;		switch (pHDMI->chip) {	case capsam_chip_SiI9031:		err = capsam_SiI9031_detect_mode(pHDMI->pSiI9031, &hdmi_mode);		break;	case capsam_chip_AD9380:		err = capsam_AD9380_detect_mode(pHDMI->pAD9380, &hdmi_mode);		break;	default:		err = RM_ERROR;	}	if (RMFAILED(err)) return err;		if (pHDMIMode) *pHDMIMode = hdmi_mode;	if (hdmi_mode != pHDMI->hdmi_mode) {		pHDMI->hdmi_mode = hdmi_mode;		fprintf(stderr, "[hdmi]    %s mode detected\n", (hdmi_mode == capsam_hdmi_mode_HDMI) ? "HDMI" : (hdmi_mode == capsam_hdmi_mode_DVI) ? "DVI" : "unknown");		if (hdmi_mode == capsam_hdmi_mode_HDMI) {			fprintf(stderr, "[hdmi]    re-reading AVI InfoFrame\n");			if (pUpdateAVI) *pUpdateAVI = TRUE;			if (pUpdateAudio) *pUpdateAudio = TRUE;		} else if (hdmi_mode == capsam_hdmi_mode_DVI) {			fprintf(stderr, "[hdmi]    re-detecting video mode\n");			if (pUpdateVideo) *pUpdateVideo = TRUE;		}		switch (pHDMI->chip) {		case capsam_chip_SiI9031:					err = capsam_SiI9031_set_mode(pHDMI->pSiI9031, hdmi_mode);			break;		case capsam_chip_AD9380:			err = RM_OK; // TODO			break;		default:			err = RM_ERROR;			break;		}	}		return err;}/* set up certain capture parameters to match DVI capture mode (RGB888) */RMstatus capsam_hdmi_prepare_dvi_mode(	struct capsam_hdmi_instance *pHDMI, 	enum EMhwlibTVStandard TVStandard, 	RMbool Wide, 	enum EMhwlibColorSpace *pInputColorSpace, 	enum EMhwlibInputColorFormat *pInputColorFormat, 	RMbool *pUpsample422, 	RMuint32 *pZoomX, 	RMuint32 *pZoomY, 	RMuint32 *pZoomW, 	RMuint32 *pZoomH, 	struct EMhwlibAspectRatio *pPictureAspectRatio){	struct EMhwlibAspectRatio PictureAspectRatio;		if (pInputColorSpace) *pInputColorSpace = EMhwlibColorSpace_RGB_0_255;	if (pInputColorFormat) *pInputColorFormat = EMhwlibInputColorFormat_24BPP;	if (pUpsample422) *pUpsample422 = FALSE;	if (pZoomX) *pZoomX = ZOOM_0;	if (pZoomY) *pZoomY = ZOOM_0;	if (pZoomW) *pZoomW = ZOOM_1;	if (pZoomH) *pZoomH = ZOOM_1;		// determine aspect ratio from video mode	if (pPictureAspectRatio) {		capsam_get_aspect_ratio_from_video_mode(			TVStandard, NULL, Wide, 			&(PictureAspectRatio.X), 			&(PictureAspectRatio.Y));		fprintf(stderr, "[hdmi] Aspect Ratio from Video Mode: %lu:%lu\n", PictureAspectRatio.X, PictureAspectRatio.Y);		*pPictureAspectRatio = PictureAspectRatio;	}		return RM_OK;}/*** Info Frame functions ***//*** Reading Info Frames ***//* read an info frame of the specified 'type' from the selected chip *//* set 'version' to a specific requested version, or to 0 for any */RMstatus capsam_hdmi_read_info_frame(	struct capsam_hdmi_instance *pHDMI, 	RMuint8 type, 	RMuint8 version, 	RMuint8 *header, 	RMuint8 *data, 	RMuint32 size, 	RMbool honor_checksum){	RMstatus err;	RMuint32 i, checksum;	RMuint8 offset, next_type = 0;	RMbool checksum_available = TRUE;		RMDBGLOG((FUNCNAME, "%s\n",__func__));	// Sanity checks	if (pHDMI == NULL) return RM_FATALINVALIDPOINTER;		switch (pHDMI->chip) {	case capsam_chip_SiI9031: 		// translate type to SiI9031 offset		err = capsam_SiI9031_get_info_frame_offset(pHDMI->pSiI9031, type, &offset);		if (RMFAILED(err)) return err;				// read the info frame from the chip		err = capsam_SiI9031_read_info_frame(pHDMI->pSiI9031, offset, header, data, size, honor_checksum);		if (RMFAILED(err) || (header[0] && type && (header[0] != type))) {			// not what was expected, try to prepare receive area for the requested type			next_type = type;		} else {			// ISRC1 and ISRC2 share one receive area, alternate between them			if (type == 0x05) {  // ISRC1				if (RMunshiftBool(header[1], 7)) next_type = 0x06;  // expect ISRC2 next			} else if (type == 0x06) {  // ISRC2				next_type = 0x05;  // expect ISRC1 next			}		}				if (next_type) {			// only works for SPD, MPEG, ACP areas, ignore return status			capsam_SiI9031_set_info_frame_receive_type(pHDMI->pSiI9031, offset, next_type);		}		break;	case capsam_chip_AD9380:		err = capsam_AD9380_read_info_frame(pHDMI->pAD9380, type, header, data, size);		checksum_available = FALSE;		break;	default:		err = RM_ERROR;	}	if (RMFAILED(err)){		RMDBGLOG((FUNCNAME, "%s return ERROR \n",__func__));		return err;	}		if(checksum_available){		if (header[0] & 0x80) {			// CEA861 info frame: calculate checksum			checksum = 0;			for (i = 0; i < 3; i++) checksum += header[i];			for (i = 0; i < RMmin((RMuint32)header[2] + 1, size); i++) checksum += data[i];		} else {			// HDMI packet: no checksum			checksum = 0;		}				if (checksum & 0xFF) {			if (header[0]) {				fprintf(stderr, "info frame checksum error at 0x%02X, type 0x%02X: 0x%02lX\n", offset, header[0], checksum & 0xFF);			}			if (honor_checksum) return RM_ERROR;		}		if ((type && (header[0] != type)) || (version && (header[1] != version))) {			if (header[0]) {				RMDBGLOG((ENABLE, "Error, wrong Info Frame Type/Version: 0x%02X/0x%02X\n", header[0], header[1]));				RMDBGPRINT((ENABLE, "type=0x%02lX ", header[0]));				RMDBGPRINT((ENABLE, " ver=0x%02lX ", header[1]));				RMDBGPRINT((ENABLE, " len=0x%02lX ", header[2]));				RMDBGPRINT((ENABLE, " chk=0x%02X ", data[0]));				for (i = 1; i < size; i++) {					RMDBGPRINT((ENABLE, "%4l=0x%02X ", i, data[i]));				}				RMDBGPRINT((ENABLE, "\n"));			}			if (honor_checksum) return RM_ERROR;		}	}	return RM_OK;}/* signal intent to read the next available info frame of the specified 'type' */RMstatus capsam_hdmi_prepare_info_frame(	struct capsam_hdmi_instance *pHDMI, 	RMuint8 type){	RMstatus err;	RMuint8 offset;	RMDBGLOG((FUNCNAME, "%s\n",__func__));		// Sanity checks	if (pHDMI == NULL) return RM_FATALINVALIDPOINTER;		switch (pHDMI->chip) {	case capsam_chip_SiI9031: 		// translate type to SiI9031 offset		err = capsam_SiI9031_get_info_frame_offset(pHDMI->pSiI9031, type, &offset);		if (RMFAILED(err)) return err;		// prepare receive area		err = capsam_SiI9031_set_info_frame_receive_type(pHDMI->pSiI9031, offset, type);		break;	case capsam_chip_AD9380:		err = RM_NOTIMPLEMENTED;  // TODO		break;	default:		err = RM_ERROR;	}		return err;}/*** Parsing Info Frames ***//* parses an AVI data block into a struct capsam_hdmi_avi_info */void capsam_hdmi_parse_avi_struct(RMuint8 *avi_data, struct capsam_hdmi_avi_info *avi){	RMDBGLOG((FUNCNAME, "%s\n",__func__));	avi->valid = TRUE;	avi->color_format = (avi_data[1] >> 5) & 0x03;	avi->active_format = (avi_data[1] & 0x10) | (avi_data[2] & 0x0F);	avi->h_bar = (avi_data[1] & 0x08) ? TRUE : FALSE;	avi->v_bar = (avi_data[1] & 0x04) ? TRUE : FALSE;	avi->scan_info = avi_data[1] & 0x03;	avi->color_space = (avi_data[2] >> 6) & 0x03;	avi->aspect_ratio = (avi_data[2] >> 4) & 0x03;	avi->scaling = avi_data[3] & 0x03;	avi->quantisation = (avi_data[3] >> 2) & 0x03;	avi->ext_col = (avi_data[3] >> 4) & 0x07;	avi->it_content = (avi_data[3] & 0x80) ? TRUE : FALSE;	avi->vic = avi_data[4] & 0x7F;	avi->pixel_rep = avi_data[5] & 0x0F;	avi->top = (avi_data[7] << 8) | avi_data[6];	avi->bottom = (avi_data[9] << 8) | avi_data[8];	avi->left = (avi_data[11] << 8) | avi_data[10];	avi->right = (avi_data[13] << 8) | avi_data[12];}/* debug print of the AVI Info Frame, formatted same as the table in CEA-861 */RMstatus capsam_hdmi_print_avi_info_frame(

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -