Go to the documentation of this file.
4 #include <linux/videodev.h>
8 #include <linux/videodev2.h>
11 #include <sys/ioctl.h>
23 #define TVREC_CARDNUM \
24 ((m_tvrec != nullptr) ? QString::number(m_tvrec->GetInputId()) : "NULL")
26 #define LOC QString("V4LRec[%1](%2): ") \
27 .arg(TVREC_CARDNUM).arg(m_videodevice)
61 if (name ==
"audiodevice")
63 else if (name ==
"vbidevice")
65 else if (name ==
"vbiformat")
73 auto *data =
static_cast<struct
VBIData *
>(data_in);
82 LOG(VB_GENERAL, LOG_DEBUG, QString(
"subtitle page %1.%2")
83 .
arg(vtp->pgno, 0, 16) .arg(vtp->subno, 0, 16));
85 data->foundteletextpage =
true;
86 memcpy(&(
data->teletextpage), vtp,
sizeof(
vt_page));
103 struct VBIData *vbi_cb =
nullptr;
104 struct vbi *pal_tt =
nullptr;
112 pal_tt =
vbi_open(vbidev.constData(),
nullptr, 99, -1);
117 memset(vbi_cb, 0,
sizeof(
VBIData));
124 fd = open(vbidev.constData(), O_RDONLY);
128 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Invalid CC/Teletext mode");
134 LOG(VB_GENERAL, LOG_ERR,
LOC +
142 struct v4l2_format fmt {};
143 fmt.type = V4L2_BUF_TYPE_VBI_CAPTURE;
144 if (0 != ioctl(fd, VIDIOC_G_FMT, &fmt))
147 LOG(VB_RECORD, LOG_INFO,
"V4L2 VBI setup failed, trying v1 ioctl");
149 struct vbi_format old_fmt;
150 memset(&old_fmt, 0,
sizeof(vbi_format));
151 if (ioctl(fd, VIDIOCGVBIFMT, &old_fmt) < 0)
153 LOG(VB_GENERAL, LOG_ERR,
LOC +
154 "Failed to query vbi capabilities (V4L1)");
158 fmt.fmt.vbi.sampling_rate = old_fmt.sampling_rate;
159 fmt.fmt.vbi.offset = 0;
160 fmt.fmt.vbi.samples_per_line = old_fmt.samples_per_line;
161 fmt.fmt.vbi.start[0] = old_fmt.start[0];
162 fmt.fmt.vbi.start[1] = old_fmt.start[1];
163 fmt.fmt.vbi.count[0] = old_fmt.count[0];
164 fmt.fmt.vbi.count[1] = old_fmt.count[1];
165 fmt.fmt.vbi.flags = old_fmt.flags;
166 #else // if !USING_V4L1
167 LOG(VB_RECORD, LOG_ERR,
"V4L2 VBI setup failed");
170 #endif // !USING_V4L1
172 LOG(VB_RECORD, LOG_INFO,
LOC +
173 QString(
"vbi_format rate: %1"
174 "\n\t\t\t offset: %2"
175 "\n\t\t\tsamples_per_line: %3"
176 "\n\t\t\t starts: %4, %5"
177 "\n\t\t\t counts: %6, %7"
178 "\n\t\t\t flags: 0x%8")
179 .
arg(fmt.fmt.vbi.sampling_rate)
180 .arg(fmt.fmt.vbi.offset)
181 .arg(fmt.fmt.vbi.samples_per_line)
182 .arg(fmt.fmt.vbi.start[0])
183 .arg(fmt.fmt.vbi.start[1])
184 .arg(fmt.fmt.vbi.count[0])
185 .arg(fmt.fmt.vbi.count[1])
186 .arg(fmt.fmt.vbi.flags,0,16));
188 width = fmt.fmt.vbi.samples_per_line;
189 start_line = fmt.fmt.vbi.start[0];
190 line_count = fmt.fmt.vbi.count[0];
191 if (line_count != fmt.fmt.vbi.count[1])
193 LOG(VB_GENERAL, LOG_ERR,
LOC +
194 "VBI must have the same number of "
195 "odd and even fields for our decoder");
199 if (start_line > 21 || start_line + line_count < 22)
201 LOG(VB_GENERAL, LOG_ERR,
LOC +
"VBI does not include line 21");
253 unsigned char *buf =
nullptr;
254 unsigned char *ptr =
nullptr;
255 unsigned char *ptr_end =
nullptr;
259 buf = ptr =
new unsigned char[sz];
271 struct timeval tv {0, 5000};
277 int nr = select(
m_vbiFd + 1, &rdset,
nullptr,
nullptr, &tv);
279 LOG(VB_GENERAL, LOG_ERR,
LOC +
"vbi select failed" +
ENO);
284 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"vbi select timed out");
300 ptr = (ret > 0) ? ptr + ret : ptr;
301 if ((ptr_end - ptr) == 0)
303 unsigned char *line21_field1 =
305 unsigned char *line21_field2 =
314 code1 = (0xFFFF==code1) ? -1 : code1;
315 code2 = (0xFFFF==code2) ? -1 : code2;
322 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Reading VBI data" +
ENO);
#define ENO
This can be appended to the LOG args with "+".
def read(device=None, features=[])
volatile bool m_requestHelper
arg(title).arg(filename).arg(doDelete))
bool IsErrored(void) override
Tells us whether an unrecoverable error has been encountered.
struct VBIData * m_palVbiCb
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
static uint Parse(const QString &vbiformat)
void vbi_close(struct vbi *vbi)
void vbi_handler(struct vbi *vbi, int fd)
void SetOption(const QString &name, const QString &value) override
Set an specific option.
if(query.exec() &&query.next())
void CloseVBIDevice(void)
void StopRecording(void) override
StopRecording() signals to the recorder that it should stop recording and exit cleanly.
void SetOption(const QString &name, const QString &value) override
Set an specific option.
virtual bool IsHelperRequested(void) const
int vbi_add_handler(struct vbi *vbi, vbic_handler handler, void *data)
virtual void StopRecording(void)
StopRecording() signals to the recorder that it should stop recording and exit cleanly.
static void vbi_event(void *data_in, struct vt_event *ev)
virtual bool PauseAndWait(int timeout=100)
If m_requestPause is true, sets pause and blocks up to timeout milliseconds or until unpaused,...
VBI608Extractor * m_vbi608
bool isRunning(void) const
virtual void FormatCC(uint, uint)
virtual void FormatTT(struct VBIData *)
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
QString m_audioDeviceName
void vbi_del_handler(struct vbi *vbi, vbic_handler handler, void *data)
QWaitCondition m_unpauseWait
unsigned char data[VT_HEIGHT][VT_WIDTH]
struct vbi * vbi_open(const char *vbi_dev_name, struct cache *ca, int fine_tune, int big_buf)
bool m_requestRecording
True if API call has requested a recording be [re]started.