/* offset from 0 to register ts v4l2 minors on */ #define CX18_V4L2_ENC_TS_OFFSET 16 /* offset from 0 to register pcm v4l2 minors on */ #define CX18_V4L2_ENC_PCM_OFFSET 24 /* offset from 0 to register yuv v4l2 minors on */ #define CX18_V4L2_ENC_YUV_OFFSET 32
staticint cx18_prep_dev(struct cx18 *cx, int type)
{ struct cx18_stream *s = &cx->streams[type];
u32 cap = cx->v4l2_cap; int num_offset = cx18_stream_info[type].num_offset; int num = cx->instance + cx18_first_minor + num_offset; int err;
/* Check whether the radio is supported */ if (type == CX18_ENC_STREAM_TYPE_RAD && !(cap & V4L2_CAP_RADIO)) return0;
/* Check whether VBI is supported */ if (type == CX18_ENC_STREAM_TYPE_VBI &&
!(cap & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE))) return0;
/* User explicitly selected 0 buffers for these streams, so don't
create them. */ if (cx18_stream_info[type].dma != DMA_NONE &&
cx->stream_buffers[type] == 0) {
CX18_INFO("Disabled %s device\n", cx18_stream_info[type].name); return0;
}
err = cx18_stream_init(cx, type); if (err) return err;
/* Allocate the cx18_dvb struct only for the TS on cards with DTV */ if (type == CX18_ENC_STREAM_TYPE_TS) { if (cx->card->hw_all & CX18_HW_DVB) {
s->dvb = kzalloc(sizeof(struct cx18_dvb), GFP_KERNEL); if (s->dvb == NULL) {
CX18_ERR("Couldn't allocate cx18_dvb structure for %s\n",
s->name); return -ENOMEM;
}
} else { /* Don't need buffers for the TS, if there is no DVB */
s->buffers = 0;
}
}
if (num_offset == -1) return0;
/* initialize the v4l2 video device structure */
snprintf(s->video_dev.name, sizeof(s->video_dev.name), "%s %s",
cx->v4l2_dev.name, s->name);
/* Initialize v4l2 variables and register v4l2 devices */ int cx18_streams_setup(struct cx18 *cx)
{ int type, ret;
/* Setup V4L2 Devices */ for (type = 0; type < CX18_MAX_STREAMS; type++) { /* Prepare device */
ret = cx18_prep_dev(cx, type); if (ret < 0) break;
/* Allocate Stream */
ret = cx18_stream_alloc(&cx->streams[type]); if (ret < 0) break;
} if (type == CX18_MAX_STREAMS) return0;
/* One or more streams could not be initialized. Clean 'em all up. */
cx18_streams_cleanup(cx, 0); return ret;
}
staticint cx18_reg_dev(struct cx18 *cx, int type)
{ struct cx18_stream *s = &cx->streams[type]; int vfl_type = cx18_stream_info[type].vfl_type; constchar *name; int num, ret;
if (type == CX18_ENC_STREAM_TYPE_TS && s->dvb != NULL) {
ret = cx18_dvb_register(s); if (ret < 0) {
CX18_ERR("DVB failed to register\n"); return ret;
}
}
if (s->video_dev.v4l2_dev == NULL) return0;
num = s->video_dev.num;
s->video_dev.device_caps = s->v4l2_dev_caps; /* device capabilities */ /* card number + user defined offset + device offset */ if (type != CX18_ENC_STREAM_TYPE_MPG) { struct cx18_stream *s_mpg = &cx->streams[CX18_ENC_STREAM_TYPE_MPG];
if (s_mpg->video_dev.v4l2_dev)
num = s_mpg->video_dev.num
+ cx18_stream_info[type].num_offset;
}
video_set_drvdata(&s->video_dev, s);
/* Register device. First try the desired minor, then any free one. */
ret = video_register_device_no_warn(&s->video_dev, vfl_type, num); if (ret < 0) {
CX18_ERR("Couldn't register v4l2 device for %s (device node number %d)\n",
s->name, num);
s->video_dev.v4l2_dev = NULL; return ret;
}
name = video_device_node_name(&s->video_dev);
switch (vfl_type) { case VFL_TYPE_VIDEO:
CX18_INFO("Registered device %s for %s (%d x %d.%02d kB)\n",
name, s->name, cx->stream_buffers[type],
cx->stream_buf_size[type] / 1024,
(cx->stream_buf_size[type] * 100 / 1024) % 100); break;
case VFL_TYPE_RADIO:
CX18_INFO("Registered device %s for %s\n", name, s->name); break;
case VFL_TYPE_VBI: if (cx->stream_buffers[type])
CX18_INFO("Registered device %s for %s (%d x %d bytes)\n",
name, s->name, cx->stream_buffers[type],
cx->stream_buf_size[type]); else
CX18_INFO("Registered device %s for %s\n",
name, s->name); break;
}
return0;
}
/* Register v4l2 devices */ int cx18_streams_register(struct cx18 *cx)
{ int type; int err; int ret = 0;
/* Register V4L2 devices */ for (type = 0; type < CX18_MAX_STREAMS; type++) {
err = cx18_reg_dev(cx, type); if (err && ret == 0)
ret = err;
}
if (ret == 0) return0;
/* One or more streams could not be initialized. Clean 'em all up. */
cx18_streams_cleanup(cx, 1); return ret;
}
/* Unregister v4l2 devices */ void cx18_streams_cleanup(struct cx18 *cx, int unregister)
{ struct video_device *vdev; int type;
/* Teardown all streams */ for (type = 0; type < CX18_MAX_STREAMS; type++) {
/* The TS has a cx18_dvb structure, not a video_device */ if (type == CX18_ENC_STREAM_TYPE_TS) { if (cx->streams[type].dvb != NULL) { if (unregister)
cx18_dvb_unregister(&cx->streams[type]);
kfree(cx->streams[type].dvb);
cx->streams[type].dvb = NULL;
cx18_stream_free(&cx->streams[type]);
} continue;
}
/* No struct video_device, but can have buffers allocated */ if (type == CX18_ENC_STREAM_TYPE_IDX) { /* If the module params didn't inhibit IDX ... */ if (cx->stream_buffers[type] != 0) {
cx->stream_buffers[type] = 0; /* *Beforecallingcx18_stream_free(), *checkiftheIDXstreamwasactuallysetup. *Needed,sincethecx18_probe()errorpath *exitsthroughhereaswellasnormalcleanup
*/ if (cx->streams[type].buffers != 0)
cx18_stream_free(&cx->streams[type]);
} continue;
}
/* If struct video_device exists, can have buffers allocated */
vdev = &cx->streams[type].video_dev;
if (vdev->v4l2_dev == NULL) continue;
cx18_stream_free(&cx->streams[type]);
if (type == CX18_ENC_STREAM_TYPE_YUV)
vb2_video_unregister_device(vdev); else
video_unregister_device(vdev);
}
}
staticvoid cx18_vbi_setup(struct cx18_stream *s)
{ struct cx18 *cx = s->cx; int raw = cx18_raw_vbi(cx);
u32 data[CX2341X_MBOX_MAX_DATA]; int lines;
/* Return if the firmware is not running low on MDLs */ if ((atomic_read(&s->q_free.depth) + atomic_read(&s->q_busy.depth)) >=
CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN) return;
/* Return if there are no MDLs to rotate back to the firmware */ if (atomic_read(&s->q_full.depth) < 2) return;
/* Don't give it to the firmware, if we're not running a capture */ if (s->handle == CX18_INVALID_TASK_HANDLE ||
test_bit(CX18_F_S_STOPPING, &s->s_flags) ||
!test_bit(CX18_F_S_STREAMING, &s->s_flags)) return cx18_enqueue(s, mdl, &s->q_free);
q = cx18_enqueue(s, mdl, &s->q_busy); if (q != &s->q_busy) return q; /* The firmware has the max MDLs it can handle */
if (atomic_read(&s->q_free.depth) == 0 ||
atomic_read(&s->q_busy.depth) >= CX18_MAX_FW_MDLS_PER_STREAM) return;
/* Move from q_free to q_busy notifying the firmware, until the limit */ do {
mdl = cx18_dequeue(s, &s->q_free); if (mdl == NULL) break;
q = _cx18_stream_put_mdl_fw(s, mdl);
} while (atomic_read(&s->q_busy.depth) < CX18_MAX_FW_MDLS_PER_STREAM
&& q == &s->q_busy);
}
/* Enable the Video Format Converter for UYVY 4:2:2 support, *ratherthanthedefaultHM12Macroblovk4:2:0support.
*/ if (captype == CAPTURE_CHANNEL_TYPE_YUV) { if (s->pixelformat == V4L2_PIX_FMT_UYVY)
cx18_vapi(cx, CX18_CPU_SET_VFC_PARAM, 2,
s->handle, 1); else /* If in doubt, default to HM12 */
cx18_vapi(cx, CX18_CPU_SET_VFC_PARAM, 2,
s->handle, 0);
}
}
/* you're live! sit back and await interrupts :) */ if (captype != CAPTURE_CHANNEL_TYPE_TS)
atomic_inc(&cx->ana_capturing);
atomic_inc(&cx->tot_capturing); return0;
}
EXPORT_SYMBOL(cx18_start_v4l2_encode_stream);
void cx18_stop_all_captures(struct cx18 *cx)
{ int i;
for (i = CX18_MAX_STREAMS - 1; i >= 0; i--) { struct cx18_stream *s = &cx->streams[i];
if (!cx18_stream_enabled(s)) continue; if (test_bit(CX18_F_S_STREAMING, &s->s_flags))
cx18_stop_v4l2_encode_stream(s, 0);
}
}
int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
{ struct cx18 *cx = s->cx;
if (!cx18_stream_enabled(s)) return -EINVAL;
/* This function assumes that you are allowed to stop the capture
and that we are actually capturing */
CX18_DEBUG_INFO("Stop Capture\n");
if (atomic_read(&cx->tot_capturing) == 0) return0;
if (handle == CX18_INVALID_TASK_HANDLE) return NULL;
for (i = 0; i < CX18_MAX_STREAMS; i++) {
s = &cx->streams[i]; if (s->handle != handle) continue; if (cx18_stream_enabled(s)) return s;
} return NULL;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet am 2026-10-12)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.