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

📄 ivtv-ioctl.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 4 页
字号:
			{ 0, 0, 0,			  "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12,			  { 0, 0, 0, 0 }			},			{ 1, 0, V4L2_FMT_FLAG_COMPRESSED,			  "MPEG", V4L2_PIX_FMT_MPEG,			  { 0, 0, 0, 0 }			}		};		struct v4l2_fmtdesc *fmt = arg;		enum v4l2_buf_type type = fmt->type;		switch (type) {		case V4L2_BUF_TYPE_VIDEO_CAPTURE:			break;		case V4L2_BUF_TYPE_VIDEO_OUTPUT:			if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))				return -EINVAL;			break;		default:			return -EINVAL;		}		if (fmt->index > 1)			return -EINVAL;		*fmt = formats[fmt->index];		fmt->type = type;		return 0;	}	case VIDIOC_G_INPUT:{		*(int *)arg = itv->active_input;		break;	}	case VIDIOC_S_INPUT:{		int inp = *(int *)arg;		if (inp < 0 || inp >= itv->nof_inputs)			return -EINVAL;		if (inp == itv->active_input) {			IVTV_DEBUG_INFO("Input unchanged\n");			break;		}		if (atomic_read(&itv->capturing) > 0) {			return -EBUSY;		}		IVTV_DEBUG_INFO("Changing input from %d to %d\n",				itv->active_input, inp);		itv->active_input = inp;		/* Set the audio input to whatever is appropriate for the		   input type. */		itv->audio_input = itv->card->video_inputs[inp].audio_index;		/* prevent others from messing with the streams until		   we're finished changing inputs. */		ivtv_mute(itv);		ivtv_video_set_io(itv);		ivtv_audio_set_io(itv);		ivtv_unmute(itv);		break;	}	case VIDIOC_G_OUTPUT:{		if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))			return -EINVAL;		*(int *)arg = itv->active_output;		break;	}	case VIDIOC_S_OUTPUT:{		int outp = *(int *)arg;		struct v4l2_routing route;		if (outp >= itv->card->nof_outputs)			return -EINVAL;		if (outp == itv->active_output) {			IVTV_DEBUG_INFO("Output unchanged\n");			break;		}		IVTV_DEBUG_INFO("Changing output from %d to %d\n",			   itv->active_output, outp);		itv->active_output = outp;		route.input = SAA7127_INPUT_TYPE_NORMAL;		route.output = itv->card->video_outputs[outp].video_output;		ivtv_saa7127(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route);		break;	}	case VIDIOC_G_FREQUENCY:{		struct v4l2_frequency *vf = arg;		if (vf->tuner != 0)			return -EINVAL;		ivtv_call_i2c_clients(itv, cmd, arg);		break;	}	case VIDIOC_S_FREQUENCY:{		struct v4l2_frequency vf = *(struct v4l2_frequency *)arg;		if (vf.tuner != 0)			return -EINVAL;		ivtv_mute(itv);		IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf.frequency);		ivtv_call_i2c_clients(itv, cmd, &vf);		ivtv_unmute(itv);		break;	}	case VIDIOC_ENUMSTD:{		struct v4l2_standard *vs = arg;		int idx = vs->index;		if (idx < 0 || idx >= ARRAY_SIZE(enum_stds))			return -EINVAL;		*vs = (enum_stds[idx].std & V4L2_STD_525_60) ?				ivtv_std_60hz : ivtv_std_50hz;		vs->index = idx;		vs->id = enum_stds[idx].std;		strcpy(vs->name, enum_stds[idx].name);		break;	}	case VIDIOC_G_STD:{		*(v4l2_std_id *) arg = itv->std;		break;	}	case VIDIOC_S_STD: {		v4l2_std_id std = *(v4l2_std_id *) arg;		if ((std & V4L2_STD_ALL) == 0)			return -EINVAL;		if (std == itv->std)			break;		if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||		    atomic_read(&itv->capturing) > 0 ||		    atomic_read(&itv->decoding) > 0) {			/* Switching standard would turn off the radio or mess			   with already running streams, prevent that by			   returning EBUSY. */			return -EBUSY;		}		itv->std = std;		itv->is_60hz = (std & V4L2_STD_525_60) ? 1 : 0;		itv->params.is_50hz = itv->is_50hz = !itv->is_60hz;		itv->params.width = 720;		itv->params.height = itv->is_50hz ? 576 : 480;		itv->vbi.count = itv->is_50hz ? 18 : 12;		itv->vbi.start[0] = itv->is_50hz ? 6 : 10;		itv->vbi.start[1] = itv->is_50hz ? 318 : 273;		if (itv->hw_flags & IVTV_HW_CX25840) {			itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;		}		IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std);		/* Tuner */		ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std);		if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {			/* set display standard */			itv->std_out = std;			itv->is_out_60hz = itv->is_60hz;			itv->is_out_50hz = itv->is_50hz;			ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std_out);			ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);			itv->main_rect.left = itv->main_rect.top = 0;			itv->main_rect.width = 720;			itv->main_rect.height = itv->params.height;			ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,				720, itv->main_rect.height, 0, 0);		}		break;	}	case VIDIOC_S_TUNER: {	/* Setting tuner can only set audio mode */		struct v4l2_tuner *vt = arg;		if (vt->index != 0)			return -EINVAL;		ivtv_call_i2c_clients(itv, VIDIOC_S_TUNER, vt);		break;	}	case VIDIOC_G_TUNER: {		struct v4l2_tuner *vt = arg;		if (vt->index != 0)			return -EINVAL;		memset(vt, 0, sizeof(*vt));		ivtv_call_i2c_clients(itv, VIDIOC_G_TUNER, vt);		if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {			strcpy(vt->name, "ivtv Radio Tuner");			vt->type = V4L2_TUNER_RADIO;		} else {			strcpy(vt->name, "ivtv TV Tuner");			vt->type = V4L2_TUNER_ANALOG_TV;		}		break;	}	case VIDIOC_G_SLICED_VBI_CAP: {		struct v4l2_sliced_vbi_cap *cap = arg;		int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;		int f, l;		enum v4l2_buf_type type = cap->type;		memset(cap, 0, sizeof(*cap));		cap->type = type;		if (type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {			for (f = 0; f < 2; f++) {				for (l = 0; l < 24; l++) {					if (valid_service_line(f, l, itv->is_50hz)) {						cap->service_lines[f][l] = set;					}				}			}			return 0;		}		if (type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {			if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))				return -EINVAL;			if (itv->is_60hz) {				cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;				cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;			} else {				cap->service_lines[0][23] = V4L2_SLICED_WSS_625;				cap->service_lines[0][16] = V4L2_SLICED_VPS;			}			return 0;		}		return -EINVAL;	}	case VIDIOC_G_ENC_INDEX: {		struct v4l2_enc_idx *idx = arg;		struct v4l2_enc_idx_entry *e = idx->entry;		int entries;		int i;		entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %					IVTV_MAX_PGM_INDEX;		if (entries > V4L2_ENC_IDX_ENTRIES)			entries = V4L2_ENC_IDX_ENTRIES;		idx->entries = 0;		for (i = 0; i < entries; i++) {			*e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];			if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {				idx->entries++;				e++;			}		}		itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;		break;	}	case VIDIOC_ENCODER_CMD:	case VIDIOC_TRY_ENCODER_CMD: {		struct v4l2_encoder_cmd *enc = arg;		int try = cmd == VIDIOC_TRY_ENCODER_CMD;		memset(&enc->raw, 0, sizeof(enc->raw));		switch (enc->cmd) {		case V4L2_ENC_CMD_START:			IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");			enc->flags = 0;			if (try)				return 0;			return ivtv_start_capture(id);		case V4L2_ENC_CMD_STOP:			IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");			enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;			if (try)				return 0;			ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);			return 0;		case V4L2_ENC_CMD_PAUSE:			IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");			enc->flags = 0;			if (try)				return 0;			if (!atomic_read(&itv->capturing))				return -EPERM;			if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))				return 0;			ivtv_mute(itv);			ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);			break;		case V4L2_ENC_CMD_RESUME:			IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");			enc->flags = 0;			if (try)				return 0;			if (!atomic_read(&itv->capturing))				return -EPERM;			if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))				return 0;			ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);			ivtv_unmute(itv);			break;		default:			IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);			return -EINVAL;		}		break;	}	case VIDIOC_G_FBUF: {		struct v4l2_framebuffer *fb = arg;		int pixfmt;		static u32 pixel_format[16] = {			V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */			V4L2_PIX_FMT_RGB565,			V4L2_PIX_FMT_RGB555,			V4L2_PIX_FMT_RGB444,			V4L2_PIX_FMT_RGB32,			0,			0,			0,			V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */			V4L2_PIX_FMT_YUV565,			V4L2_PIX_FMT_YUV555,			V4L2_PIX_FMT_YUV444,			V4L2_PIX_FMT_YUV32,			0,			0,			0,		};		memset(fb, 0, sizeof(*fb));		if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))			return -EINVAL;		fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |			V4L2_FBUF_CAP_GLOBAL_ALPHA;		ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);		data[0] |= (read_reg(0x2a00) >> 7) & 0x40;		pixfmt = (data[0] >> 3) & 0xf;		fb->fmt.pixelformat = pixel_format[pixfmt];		fb->fmt.width = itv->osd_rect.width;		fb->fmt.height = itv->osd_rect.height;		fb->base = (void *)itv->osd_video_pbase;		if (itv->osd_chroma_key_state)			fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;		if (itv->osd_global_alpha_state)			fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;		pixfmt &= 7;		/* no local alpha for RGB565 or unknown formats */		if (pixfmt == 1 || pixfmt > 4)			break;		/* 16-bit formats have inverted local alpha */		if (pixfmt == 2 || pixfmt == 3)			fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA;		else			fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;		if (itv->osd_local_alpha_state) {			/* 16-bit formats have inverted local alpha */			if (pixfmt == 2 || pixfmt == 3)				fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;			else				fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;		}		break;	}	case VIDIOC_S_FBUF: {		struct v4l2_framebuffer *fb = arg;		if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))			return -EINVAL;		itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;		itv->osd_local_alpha_state =			(fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;		itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;		ivtv_set_osd_alpha(itv);		break;	}	case VIDIOC_OVERLAY: {		int *on = arg;		if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))			return -EINVAL;		ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, *on != 0);		break;	}	case VIDIOC_LOG_STATUS:	{		int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;		struct v4l2_input vidin;		struct v4l2_audio audin;		int i;		IVTV_INFO("=================  START STATUS CARD #%d  =================\n", itv->num);		IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);		if (itv->hw_flags & IVTV_HW_TVEEPROM) {			struct tveeprom tv;			ivtv_read_eeprom(itv, &tv);		}		ivtv_call_i2c_clients(itv, VIDIOC_LOG_STATUS, NULL);		ivtv_get_input(itv, itv->active_input, &vidin);		ivtv_get_audio_input(itv, itv->audio_input, &audin);		IVTV_INFO("Video Input:  %s\n", vidin.name);		IVTV_INFO("Audio Input:  %s%s\n", audin.name,			(itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");		if (has_output) {			struct v4l2_output vidout;			struct v4l2_audioout audout;			int mode = itv->output_mode;			static const char * const output_modes[5] = {				"None",				"MPEG Streaming",				"YUV Streaming",				"YUV Frames",				"Passthrough",			};			static const char * const audio_modes[5] = {

⌨️ 快捷键说明

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