10 #include <sys/types.h>
19 #include <linux/videodev2.h>
29 #define DEBUG_ATTRIB 1
31 #define LOC QString("V4LChannel[%1](%2): ") \
32 .arg(GetCardID()).arg(GetDevice())
39 device(videodevice), videofd(-1),
40 device_name(), driver_name(),
41 curList(NULL), totalChannels(0),
74 QByteArray ascii_device =
device.toLatin1();
78 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Can't open video device." + ENO);
84 version, capabilities))
86 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to query capabilities." + ENO);
92 has_std_io = !!(capabilities & V4L2_CAP_READWRITE);
94 has_tuner = !!(capabilities & V4L2_CAP_TUNER);
100 LOG(VB_CHANNEL, LOG_INFO,
LOC + QString(
"Device name '%1' driver '%2'.")
103 LOG(VB_CHANNEL, LOG_INFO,
LOC +
104 QString(
"v4l2: stream io: %2 std io: %3 async io: %4 "
105 "tuner %5 sliced vbi %6")
137 return V4L2_STD_PAL_BG;
138 else if (fmt ==
"PAL-D")
139 return V4L2_STD_PAL_D;
140 else if (fmt ==
"PAL-DK")
141 return V4L2_STD_PAL_DK;
142 else if (fmt ==
"PAL-I")
143 return V4L2_STD_PAL_I;
144 else if (fmt ==
"PAL-60")
145 return V4L2_STD_PAL_60;
146 else if (fmt ==
"SECAM")
147 return V4L2_STD_SECAM;
148 else if (fmt ==
"SECAM-D")
149 return V4L2_STD_SECAM_D;
150 else if (fmt ==
"SECAM-DK")
151 return V4L2_STD_SECAM_DK;
152 else if (fmt ==
"PAL-NC")
153 return V4L2_STD_PAL_Nc;
154 else if (fmt ==
"PAL-M")
155 return V4L2_STD_PAL_M;
156 else if (fmt ==
"PAL-N")
157 return V4L2_STD_PAL_N;
158 else if (fmt ==
"NTSC-JP")
159 return V4L2_STD_NTSC_M_JP;
161 else if (fmt.startsWith(
"NTSC"))
162 return V4L2_STD_NTSC;
163 else if (fmt.startsWith(
"ATSC"))
164 return V4L2_STD_NTSC;
165 else if (fmt.startsWith(
"PAL"))
167 return V4L2_STD_NTSC;
172 if (mode == V4L2_STD_NTSC)
174 else if (mode == V4L2_STD_NTSC_M_JP)
176 else if (mode == V4L2_STD_PAL)
178 else if (mode == V4L2_STD_PAL_60)
180 else if (mode == V4L2_STD_PAL_BG)
182 else if (mode == V4L2_STD_PAL_D)
184 else if (mode == V4L2_STD_PAL_DK)
186 else if (mode == V4L2_STD_PAL_I)
188 else if (mode == V4L2_STD_PAL_M)
190 else if (mode == V4L2_STD_PAL_N)
192 else if (mode == V4L2_STD_PAL_Nc)
194 else if (mode == V4L2_STD_SECAM)
196 else if (mode == V4L2_STD_SECAM_D)
199 else if ((V4L2_STD_NTSC_M == mode) ||
200 (V4L2_STD_NTSC_443 == mode) ||
201 (V4L2_STD_NTSC_M_KR == mode))
203 else if ((V4L2_STD_PAL_B == mode) ||
204 (V4L2_STD_PAL_B1 == mode) ||
205 (V4L2_STD_PAL_G == mode) ||
206 (V4L2_STD_PAL_H == mode) ||
207 (V4L2_STD_PAL_D1 == mode) ||
208 (V4L2_STD_PAL_K == mode))
210 else if ((V4L2_STD_SECAM_B == mode) ||
211 (V4L2_STD_SECAM_DK == mode) ||
212 (V4L2_STD_SECAM_G == mode) ||
213 (V4L2_STD_SECAM_H == mode) ||
214 (V4L2_STD_SECAM_K == mode) ||
215 (V4L2_STD_SECAM_K1 == mode) ||
216 (V4L2_STD_SECAM_L == mode) ||
217 (V4L2_STD_SECAM_LC == mode))
219 else if ((V4L2_STD_ATSC == mode) ||
220 (V4L2_STD_ATSC_8_VSB == mode) ||
221 (V4L2_STD_ATSC_16_VSB == mode))
246 LOG(VB_CHANNEL, LOG_INFO, QString(
"Global TVFormat Setting '%1'").arg(fmt));
254 InputMap::const_iterator it;
257 InputNames::const_iterator v4l_it = v4l_inputs.begin();
258 for (; v4l_it != v4l_inputs.end(); ++v4l_it)
260 if (*v4l_it == (*it)->name)
262 (*it)->inputNumV4L = v4l_it.key();
272 LOG(VB_CHANNEL, LOG_INFO,
LOC +
273 QString(
"Input #%1: '%2' schan(%3) tun(%4) v4l2(%6)")
274 .arg(it.key()).arg((*it)->name).arg((*it)->startChanNum)
275 .arg((*it)->tuneToChannel)
301 if ((fmt ==
"Default") || format.isEmpty())
303 InputMap::const_iterator it =
m_inputs.find(inputNum);
308 LOG(VB_CHANNEL, LOG_INFO,
LOC + QString(
"SetFormat(%1) fmt(%2) input(%3)")
309 .arg(format).arg(fmt).arg(inputNum));
331 QString
name = tablename;
332 bool use_default = (name.toLower() ==
"default" || name.isEmpty());
335 char *listname = (
char *)
chanlists[i].name;
338 while (listname != NULL)
348 else if (name == listname)
357 LOG(VB_CHANNEL, LOG_ERR,
358 QString(
"Channel(%1)::SetFreqTable(): Invalid "
359 "frequency table name %2, using %3.").
373 LOG(VB_GENERAL, LOG_ERR,
LOC +
374 QString(
"GetCurrentChannelNum(%1): Failed to find Channel")
383 LOG(VB_CHANNEL, LOG_INFO,
384 QString(
"Channel(%1)::Tune(%2): curList[%3].freq(%4)")
385 .arg(
device).arg(freqid).arg(i)
390 LOG(VB_GENERAL, LOG_ERR,
391 QString(
"Channel(%1)::Tune(%2): Error, failed to find channel.")
392 .arg(
device).arg(freqid));
396 int frequency = (
curList[i].
freq + finetune) * 1000;
398 return Tune(frequency,
"");
420 LOG(VB_CHANNEL, LOG_INFO,
LOC + QString(
"Tune(%1, %2)")
421 .arg(frequency).arg(inputname));
437 bool isTunerCapLow =
false;
438 struct v4l2_modulator mod;
439 memset(&mod, 0,
sizeof(mod));
441 ioctlval = ioctl(
videofd, VIDIOC_G_MODULATOR, &mod);
444 isTunerCapLow = (mod.capability & V4L2_TUNER_CAP_LOW);
445 LOG(VB_CHANNEL, LOG_INFO,
446 QString(
" name: %1").arg((
char *)mod.name));
447 LOG(VB_CHANNEL, LOG_INFO, QString(
"CapLow: %1").arg(isTunerCapLow));
450 struct v4l2_frequency vf;
451 memset(&vf, 0,
sizeof(vf));
454 vf.frequency = (isTunerCapLow) ?
455 ((
int)(frequency / 62.5)) : (frequency / 62500);
457 vf.type = V4L2_TUNER_ANALOG_TV;
459 ioctlval = ioctl(
videofd, VIDIOC_S_FREQUENCY, &vf);
462 LOG(VB_GENERAL, LOG_ERR,
463 QString(
"Channel(%1)::Tune(): Error %2 "
464 "while setting frequency (v2): %3")
468 ioctlval = ioctl(
videofd, VIDIOC_G_FREQUENCY, &vf);
472 LOG(VB_CHANNEL, LOG_INFO,
473 QString(
"Channel(%1)::Tune(): Frequency is now %2")
474 .arg(
device).arg(vf.frequency * 62500));
487 struct v4l2_frequency vf;
488 memset(&vf, 0,
sizeof(vf));
491 vf.type = V4L2_TUNER_ANALOG_TV;
494 int ioctlval = ioctl(
videofd, VIDIOC_G_FREQUENCY, &vf);
497 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Retune failed (1)" + ENO);
502 ioctlval = ioctl(
videofd, VIDIOC_S_FREQUENCY, &vf);
505 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Retune failed (2)" + ENO);
517 "FROM channel, cardinput "
518 "WHERE channum = :CHANNUM AND "
519 " inputname = :INPUTNAME AND "
520 " cardinput.cardid = :CARDID AND "
521 " cardinput.sourceid = channel.sourceid");
523 query.
bindValue(
":INPUTNAME", inputname);
526 QString fmt = QString::null;
529 else if (query.
next())
530 fmt = query.
value(0).toString();
536 InputMap::const_iterator it =
m_inputs.find(inputNum);
537 if (it ==
m_inputs.end() || (*it)->inputNumV4L < 0)
540 int inputNumV4L = (*it)->inputNumV4L;
544 QString(
"SetInputAndFormat(%1, %2) ").arg(inputNum).arg(newFmt);
546 struct v4l2_input input;
547 int ioctlval = ioctl(
videofd, VIDIOC_G_INPUT, &input);
548 bool input_switch = (0 != ioctlval || (
uint)inputNumV4L != input.index);
552 ioctlval = ioctl(
videofd, VIDIOC_G_STD, &cur_vid_mode);
553 bool mode_switch = (0 != ioctlval || new_vid_mode != cur_vid_mode);
554 bool needs_switch = input_switch || mode_switch;
556 LOG(VB_GENERAL, LOG_INFO,
LOC + msg +
"(v4l v2) " +
557 QString(
"input_switch: %1 mode_switch: %2")
558 .arg(input_switch).arg(mode_switch));
562 bool streamingDisabled =
false;
563 int streamType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
566 ioctlval = ioctl(
videofd, VIDIOC_STREAMOFF, &streamType);
569 LOG(VB_GENERAL, LOG_ERR,
LOC + msg +
570 "\n\t\t\twhile disabling streaming (v4l v2)" + ENO);
575 streamingDisabled =
true;
582 ioctlval = ioctl(
videofd, VIDIOC_S_INPUT, &inputNumV4L);
585 LOG(VB_GENERAL, LOG_ERR,
LOC + msg +
586 "\n\t\t\twhile setting input (v4l v2)" + ENO);
594 ioctlval = ioctl(
videofd, VIDIOC_S_STD, &new_vid_mode);
597 LOG(VB_GENERAL, LOG_ERR,
LOC + msg +
598 "\n\t\t\twhile setting format (v4l v2)" + ENO);
604 if (streamingDisabled)
606 ioctlval = ioctl(
videofd, VIDIOC_STREAMON, &streamType);
609 LOG(VB_GENERAL, LOG_ERR,
LOC + msg +
610 "\n\t\t\twhile reenabling streaming (v4l v2)" + ENO);
621 InputMap::const_iterator it =
m_inputs.find(inputnum);
625 QString tuneFreqId = (*it)->tuneToChannel;
626 QString channum = (*it)->startChanNum;
627 QString inputname = (*it)->name;
629 LOG(VB_CHANNEL, LOG_INFO, QString(
"Channel(%1)::SwitchToInput(in %2, '%3')")
630 .arg(
device).arg(inputnum)
631 .arg(setstarting ? channum : QString(
"")));
633 uint mplexid_restriction;
640 bool chanValid = (channum !=
"Undefined") && !channum.isEmpty();
641 if (setstarting && chanValid)
644 if (tmp !=
"Default" && !tmp.isEmpty())
652 LOG(VB_GENERAL, LOG_ERR,
LOC +
"SetInputAndFormat() failed");
660 if (!tuneFreqId.isEmpty() && tuneFreqId !=
"Undefined")
661 ok =
Tune(tuneFreqId, 0);
666 if (setstarting && chanValid)
668 else if (setstarting && !chanValid)
670 LOG(VB_GENERAL, LOG_ERR,
LOC +
671 QString(
"SwitchToInput(in %2, set ch): ").arg(inputnum) +
672 QString(
"\n\t\t\tDefault channel '%1' is not valid.").arg(channum));
681 if (
"brightness" == db_col_name)
682 return V4L2_CID_BRIGHTNESS;
683 else if (
"contrast" == db_col_name)
684 return V4L2_CID_CONTRAST;
685 else if (
"colour" == db_col_name)
686 return V4L2_CID_SATURATION;
687 else if (
"hue" == db_col_name)
698 if (v4l2_attrib == -1)
706 if ((cfield == -1) || (sfield == -1))
709 int field = (cfield + sfield) & 0xFFFF;
712 QString(
"InitPictureAttribute(%1): ").arg(db_col_name, 10);
714 struct v4l2_control ctrl;
715 struct v4l2_queryctrl qctrl;
716 memset(&ctrl, 0,
sizeof(ctrl));
717 memset(&qctrl, 0,
sizeof(qctrl));
719 ctrl.id = qctrl.id = v4l2_attrib;
720 if (ioctl(
videofd, VIDIOC_QUERYCTRL, &qctrl) < 0)
722 LOG(VB_GENERAL, LOG_ERR, loc +
"failed to query controls." + ENO);
726 float new_range = qctrl.maximum - qctrl.minimum;
727 float old_range = 65535 - 0;
728 float scl_range = new_range / old_range;
729 float dfl = (qctrl.default_value - qctrl.minimum) / new_range;
730 int norm_dfl = (0x10000 + (
int)(dfl * old_range) - 32768) & 0xFFFF;
748 field = (cfield + sfield + dfield) & 0xFFFF;
749 int value0 = (
int) ((scl_range * field) + qctrl.minimum);
750 int value1 = min(value0, (
int)qctrl.maximum);
751 ctrl.value = max(value1, (
int)qctrl.minimum);
754 LOG(VB_CHANNEL, LOG_DEBUG, loc + QString(
" %1\n\t\t\t"
755 "[%2,%3] dflt(%4, %5, %6)")
756 .arg(value0).arg(qctrl.minimum, 5).arg(qctrl.maximum, 5)
757 .arg(qctrl.default_value, 5).arg(dfl, 4,
'f', 2)
761 if (ioctl(
videofd, VIDIOC_S_CTRL, &ctrl) < 0)
763 LOG(VB_GENERAL, LOG_ERR, loc +
"failed to set controls" + ENO);
781 if (db_col_name.isEmpty())
793 int val = (cfield + sfield + dfield) & 0xFFFF;
796 LOG(VB_CHANNEL, LOG_DEBUG,
797 QString(
"GetPictureAttribute(%1) -> cdb %2 rdb %3 d %4 -> %5")
798 .arg(db_col_name).arg(cfield).arg(sfield)
799 .arg(dfield).arg(val));
807 struct v4l2_control ctrl;
808 struct v4l2_queryctrl qctrl;
809 memset(&ctrl, 0,
sizeof(ctrl));
810 memset(&qctrl, 0,
sizeof(qctrl));
812 ctrl.id = qctrl.id = v4l2_attrib;
813 if (ioctl(videofd, VIDIOC_QUERYCTRL, &qctrl) < 0)
815 LOG(VB_GENERAL, LOG_ERR,
816 "get_v4l2_attribute_value: failed to query controls (1)" + ENO);
820 if (ioctl(videofd, VIDIOC_G_CTRL, &ctrl) < 0)
822 LOG(VB_GENERAL, LOG_ERR,
823 "get_v4l2_attribute_value: failed to get controls (2)" + ENO);
827 float mult = 65535.0 / (qctrl.maximum - qctrl.minimum);
828 return min(max((
int)(mult * (ctrl.value - qctrl.minimum)), 0), 65525);
833 struct v4l2_control ctrl;
834 struct v4l2_queryctrl qctrl;
835 memset(&ctrl, 0,
sizeof(ctrl));
836 memset(&qctrl, 0,
sizeof(qctrl));
838 ctrl.id = qctrl.id = v4l2_attrib;
839 if (ioctl(videofd, VIDIOC_QUERYCTRL, &qctrl) < 0)
841 LOG(VB_GENERAL, LOG_ERR,
842 "set_v4l2_attribute_value: failed to query control" + ENO);
846 float mult = (qctrl.maximum - qctrl.minimum) / 65535.0;
847 ctrl.value = (
int)(mult * newvalue + qctrl.minimum);
848 ctrl.value = min(ctrl.value, qctrl.maximum);
849 ctrl.value = max(ctrl.value, qctrl.minimum);
851 if (ioctl(videofd, VIDIOC_S_CTRL, &ctrl) < 0)
853 LOG(VB_GENERAL, LOG_ERR,
854 "set_v4l2_attribute_value: failed to set control" + ENO);
868 if (db_col_name.isEmpty())
872 if (v4l2_attrib == -1)
881 int new_value = old_value + ((up) ? 655 : -655);
884 if (V4L2_CID_HUE == v4l2_attrib)
886 new_value = min(max(new_value, 0), 65535);
889 LOG(VB_CHANNEL, LOG_DEBUG,
890 QString(
"ChangePictureAttribute(%1,%2,%3) cur %4 -> new %5")
891 .arg(type).arg(db_col_name).arg(up)
892 .arg(old_value).arg(new_value));
905 int tmp = new_value - old_value + adj_value;
906 tmp = (tmp < 0) ? tmp + 0x10000 : tmp;
907 tmp = (tmp > 0xffff) ? tmp - 0x10000 : tmp;
916 int tmp = new_value - old_value + adj_value;
917 tmp = (tmp < 0) ? tmp + 0x10000 : tmp;
918 tmp = (tmp > 0xffff) ? tmp - 0x10000 : tmp;