diff options
author | Andy Walls <awalls@radix.net> | 2009-12-31 15:19:25 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-02-26 13:10:30 -0500 |
commit | 79f3e96018dc55ff7819a6a1ac3740a1d7103589 (patch) | |
tree | 9eae01b9485fee9de877b8263129707ae872241f /drivers/media/video/cx18 | |
parent | e46c54a87e4a6364b0e86b03cb3d00d09ef2f627 (diff) |
V4L/DVB (13906): cx18: Start IDX streams automatically as an internal associated stream
This change starts the IDX stream along with the MPG stream as an internal
use (only) stream much like the VBI stream can be started as an internal use
stream for inserting sliced VBI packets.
The IDX stream is not started automatically with an MPEG strem if the IDX
stream is disabled (no buffers allocated) or if sliced VBI insertion is being
performed by the cx18 driver. The cx18 driver doing sliced VBI insertion
makes the offsets in the IDX stream inaccurate for the final MPEG stream
presented to user space. Since fixing the IDX offsets ourselves is not easy
and we cannot easily do what ivtv does to fix the offsets, we'll make sliced
VBI insertion and MPEG Index capture mutually exclusive for now.
Signed-off-by: Andy Walls <awalls@radix.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx18')
-rw-r--r-- | drivers/media/video/cx18/cx18-fileops.c | 183 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-streams.c | 7 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-streams.h | 7 |
3 files changed, 125 insertions, 72 deletions
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index c0885c69fd89..b1ad03f61019 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c | |||
@@ -37,15 +37,21 @@ | |||
37 | 37 | ||
38 | /* This function tries to claim the stream for a specific file descriptor. | 38 | /* This function tries to claim the stream for a specific file descriptor. |
39 | If no one else is using this stream then the stream is claimed and | 39 | If no one else is using this stream then the stream is claimed and |
40 | associated VBI streams are also automatically claimed. | 40 | associated VBI and IDX streams are also automatically claimed. |
41 | Possible error returns: -EBUSY if someone else has claimed | 41 | Possible error returns: -EBUSY if someone else has claimed |
42 | the stream or 0 on success. */ | 42 | the stream or 0 on success. */ |
43 | static int cx18_claim_stream(struct cx18_open_id *id, int type) | 43 | static int cx18_claim_stream(struct cx18_open_id *id, int type) |
44 | { | 44 | { |
45 | struct cx18 *cx = id->cx; | 45 | struct cx18 *cx = id->cx; |
46 | struct cx18_stream *s = &cx->streams[type]; | 46 | struct cx18_stream *s = &cx->streams[type]; |
47 | struct cx18_stream *s_vbi; | 47 | struct cx18_stream *s_assoc; |
48 | int vbi_type; | 48 | |
49 | /* Nothing should ever try to directly claim the IDX stream */ | ||
50 | if (type == CX18_ENC_STREAM_TYPE_IDX) { | ||
51 | CX18_WARN("MPEG Index stream cannot be claimed " | ||
52 | "directly, but something tried.\n"); | ||
53 | return -EINVAL; | ||
54 | } | ||
49 | 55 | ||
50 | if (test_and_set_bit(CX18_F_S_CLAIMED, &s->s_flags)) { | 56 | if (test_and_set_bit(CX18_F_S_CLAIMED, &s->s_flags)) { |
51 | /* someone already claimed this stream */ | 57 | /* someone already claimed this stream */ |
@@ -67,21 +73,27 @@ static int cx18_claim_stream(struct cx18_open_id *id, int type) | |||
67 | } | 73 | } |
68 | s->id = id->open_id; | 74 | s->id = id->open_id; |
69 | 75 | ||
70 | /* CX18_ENC_STREAM_TYPE_MPG needs to claim CX18_ENC_STREAM_TYPE_VBI | 76 | /* |
71 | (provided VBI insertion is on and sliced VBI is selected), for all | 77 | * CX18_ENC_STREAM_TYPE_MPG needs to claim: |
72 | other streams we're done */ | 78 | * CX18_ENC_STREAM_TYPE_VBI, if VBI insertion is on for sliced VBI, or |
73 | if (type == CX18_ENC_STREAM_TYPE_MPG && | 79 | * CX18_ENC_STREAM_TYPE_IDX, if VBI insertion is off for sliced VBI |
74 | cx->vbi.insert_mpeg && !cx18_raw_vbi(cx)) { | 80 | * (We don't yet fix up MPEG Index entries for our inserted packets). |
75 | vbi_type = CX18_ENC_STREAM_TYPE_VBI; | 81 | * |
76 | } else { | 82 | * For all other streams we're done. |
83 | */ | ||
84 | if (type != CX18_ENC_STREAM_TYPE_MPG) | ||
77 | return 0; | 85 | return 0; |
78 | } | ||
79 | s_vbi = &cx->streams[vbi_type]; | ||
80 | 86 | ||
81 | set_bit(CX18_F_S_CLAIMED, &s_vbi->s_flags); | 87 | s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; |
88 | if (cx->vbi.insert_mpeg && !cx18_raw_vbi(cx)) | ||
89 | s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; | ||
90 | else if (!cx18_stream_enabled(s_assoc)) | ||
91 | return 0; | ||
92 | |||
93 | set_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags); | ||
82 | 94 | ||
83 | /* mark that it is used internally */ | 95 | /* mark that it is used internally */ |
84 | set_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags); | 96 | set_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags); |
85 | return 0; | 97 | return 0; |
86 | } | 98 | } |
87 | 99 | ||
@@ -90,9 +102,17 @@ static int cx18_claim_stream(struct cx18_open_id *id, int type) | |||
90 | static void cx18_release_stream(struct cx18_stream *s) | 102 | static void cx18_release_stream(struct cx18_stream *s) |
91 | { | 103 | { |
92 | struct cx18 *cx = s->cx; | 104 | struct cx18 *cx = s->cx; |
93 | struct cx18_stream *s_vbi; | 105 | struct cx18_stream *s_assoc; |
94 | 106 | ||
95 | s->id = -1; | 107 | s->id = -1; |
108 | if (s->type == CX18_ENC_STREAM_TYPE_IDX) { | ||
109 | /* | ||
110 | * The IDX stream is only used internally, and can | ||
111 | * only be indirectly unclaimed by unclaiming the MPG stream. | ||
112 | */ | ||
113 | return; | ||
114 | } | ||
115 | |||
96 | if (s->type == CX18_ENC_STREAM_TYPE_VBI && | 116 | if (s->type == CX18_ENC_STREAM_TYPE_VBI && |
97 | test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) { | 117 | test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) { |
98 | /* this stream is still in use internally */ | 118 | /* this stream is still in use internally */ |
@@ -105,24 +125,34 @@ static void cx18_release_stream(struct cx18_stream *s) | |||
105 | 125 | ||
106 | cx18_flush_queues(s); | 126 | cx18_flush_queues(s); |
107 | 127 | ||
108 | /* CX18_ENC_STREAM_TYPE_MPG needs to release CX18_ENC_STREAM_TYPE_VBI, | 128 | /* |
109 | for all other streams we're done */ | 129 | * CX18_ENC_STREAM_TYPE_MPG needs to release the |
110 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) | 130 | * CX18_ENC_STREAM_TYPE_VBI and/or CX18_ENC_STREAM_TYPE_IDX streams. |
111 | s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; | 131 | * |
112 | else | 132 | * For all other streams we're done. |
133 | */ | ||
134 | if (s->type != CX18_ENC_STREAM_TYPE_MPG) | ||
113 | return; | 135 | return; |
114 | 136 | ||
115 | /* clear internal use flag */ | 137 | /* Unclaim the associated MPEG Index stream */ |
116 | if (!test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags)) { | 138 | s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; |
117 | /* was already cleared */ | 139 | if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) { |
118 | return; | 140 | clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags); |
141 | cx18_flush_queues(s_assoc); | ||
119 | } | 142 | } |
120 | if (s_vbi->id != -1) { | 143 | |
121 | /* VBI stream still claimed by a file descriptor */ | 144 | /* Unclaim the associated VBI stream */ |
122 | return; | 145 | s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; |
146 | if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) { | ||
147 | if (s_assoc->id == -1) { | ||
148 | /* | ||
149 | * The VBI stream is not still claimed by a file | ||
150 | * descriptor, so completely unclaim it. | ||
151 | */ | ||
152 | clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags); | ||
153 | cx18_flush_queues(s_assoc); | ||
154 | } | ||
123 | } | 155 | } |
124 | clear_bit(CX18_F_S_CLAIMED, &s_vbi->s_flags); | ||
125 | cx18_flush_queues(s_vbi); | ||
126 | } | 156 | } |
127 | 157 | ||
128 | static void cx18_dualwatch(struct cx18 *cx) | 158 | static void cx18_dualwatch(struct cx18 *cx) |
@@ -498,6 +528,7 @@ int cx18_start_capture(struct cx18_open_id *id) | |||
498 | struct cx18 *cx = id->cx; | 528 | struct cx18 *cx = id->cx; |
499 | struct cx18_stream *s = &cx->streams[id->type]; | 529 | struct cx18_stream *s = &cx->streams[id->type]; |
500 | struct cx18_stream *s_vbi; | 530 | struct cx18_stream *s_vbi; |
531 | struct cx18_stream *s_idx; | ||
501 | 532 | ||
502 | if (s->type == CX18_ENC_STREAM_TYPE_RAD) { | 533 | if (s->type == CX18_ENC_STREAM_TYPE_RAD) { |
503 | /* you cannot read from these stream types. */ | 534 | /* you cannot read from these stream types. */ |
@@ -516,25 +547,33 @@ int cx18_start_capture(struct cx18_open_id *id) | |||
516 | return 0; | 547 | return 0; |
517 | } | 548 | } |
518 | 549 | ||
519 | /* Start VBI capture if required */ | 550 | /* Start associated VBI or IDX stream capture if required */ |
520 | s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; | 551 | s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; |
521 | if (s->type == CX18_ENC_STREAM_TYPE_MPG && | 552 | s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; |
522 | test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) && | 553 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) { |
523 | !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) { | 554 | /* |
524 | /* Note: the CX18_ENC_STREAM_TYPE_VBI is claimed | 555 | * The VBI and IDX streams should have been claimed |
525 | automatically when the MPG stream is claimed. | 556 | * automatically, if for internal use, when the MPG stream was |
526 | We only need to start the VBI capturing. */ | 557 | * claimed. We only need to start these streams capturing. |
527 | if (cx18_start_v4l2_encode_stream(s_vbi)) { | 558 | */ |
528 | CX18_DEBUG_WARN("VBI capture start failed\n"); | 559 | if (test_bit(CX18_F_S_INTERNAL_USE, &s_idx->s_flags) && |
529 | 560 | !test_and_set_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) { | |
530 | /* Failure, clean up and return an error */ | 561 | if (cx18_start_v4l2_encode_stream(s_idx)) { |
531 | clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags); | 562 | CX18_DEBUG_WARN("IDX capture start failed\n"); |
532 | clear_bit(CX18_F_S_STREAMING, &s->s_flags); | 563 | clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags); |
533 | /* also releases the associated VBI stream */ | 564 | goto start_failed; |
534 | cx18_release_stream(s); | 565 | } |
535 | return -EIO; | 566 | CX18_DEBUG_INFO("IDX capture started\n"); |
567 | } | ||
568 | if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) && | ||
569 | !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) { | ||
570 | if (cx18_start_v4l2_encode_stream(s_vbi)) { | ||
571 | CX18_DEBUG_WARN("VBI capture start failed\n"); | ||
572 | clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags); | ||
573 | goto start_failed; | ||
574 | } | ||
575 | CX18_DEBUG_INFO("VBI insertion started\n"); | ||
536 | } | 576 | } |
537 | CX18_DEBUG_INFO("VBI insertion started\n"); | ||
538 | } | 577 | } |
539 | 578 | ||
540 | /* Tell the card to start capturing */ | 579 | /* Tell the card to start capturing */ |
@@ -547,19 +586,29 @@ int cx18_start_capture(struct cx18_open_id *id) | |||
547 | return 0; | 586 | return 0; |
548 | } | 587 | } |
549 | 588 | ||
550 | /* failure, clean up */ | 589 | start_failed: |
551 | CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name); | 590 | CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name); |
552 | 591 | ||
553 | /* Note: the CX18_ENC_STREAM_TYPE_VBI is released | 592 | /* |
554 | automatically when the MPG stream is released. | 593 | * The associated VBI and IDX streams for internal use are released |
555 | We only need to stop the VBI capturing. */ | 594 | * automatically when the MPG stream is released. We only need to stop |
556 | if (s->type == CX18_ENC_STREAM_TYPE_MPG && | 595 | * the associated stream. |
557 | test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) { | 596 | */ |
558 | cx18_stop_v4l2_encode_stream(s_vbi, 0); | 597 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) { |
559 | clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags); | 598 | /* Stop the IDX stream which is always for internal use */ |
599 | if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) { | ||
600 | cx18_stop_v4l2_encode_stream(s_idx, 0); | ||
601 | clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags); | ||
602 | } | ||
603 | /* Stop the VBI stream, if only running for internal use */ | ||
604 | if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) && | ||
605 | !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) { | ||
606 | cx18_stop_v4l2_encode_stream(s_vbi, 0); | ||
607 | clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags); | ||
608 | } | ||
560 | } | 609 | } |
561 | clear_bit(CX18_F_S_STREAMING, &s->s_flags); | 610 | clear_bit(CX18_F_S_STREAMING, &s->s_flags); |
562 | cx18_release_stream(s); | 611 | cx18_release_stream(s); /* Also releases associated streams */ |
563 | return -EIO; | 612 | return -EIO; |
564 | } | 613 | } |
565 | 614 | ||
@@ -618,6 +667,8 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end) | |||
618 | { | 667 | { |
619 | struct cx18 *cx = id->cx; | 668 | struct cx18 *cx = id->cx; |
620 | struct cx18_stream *s = &cx->streams[id->type]; | 669 | struct cx18_stream *s = &cx->streams[id->type]; |
670 | struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; | ||
671 | struct cx18_stream *s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX]; | ||
621 | 672 | ||
622 | CX18_DEBUG_IOCTL("close() of %s\n", s->name); | 673 | CX18_DEBUG_IOCTL("close() of %s\n", s->name); |
623 | 674 | ||
@@ -625,17 +676,19 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end) | |||
625 | 676 | ||
626 | /* Stop capturing */ | 677 | /* Stop capturing */ |
627 | if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) { | 678 | if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) { |
628 | struct cx18_stream *s_vbi = | ||
629 | &cx->streams[CX18_ENC_STREAM_TYPE_VBI]; | ||
630 | |||
631 | CX18_DEBUG_INFO("close stopping capture\n"); | 679 | CX18_DEBUG_INFO("close stopping capture\n"); |
632 | /* Special case: a running VBI capture for VBI insertion | 680 | if (id->type == CX18_ENC_STREAM_TYPE_MPG) { |
633 | in the mpeg stream. Need to stop that too. */ | 681 | /* Stop internal use associated VBI and IDX streams */ |
634 | if (id->type == CX18_ENC_STREAM_TYPE_MPG && | 682 | if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) && |
635 | test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) && | 683 | !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) { |
636 | !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) { | 684 | CX18_DEBUG_INFO("close stopping embedded VBI " |
637 | CX18_DEBUG_INFO("close stopping embedded VBI capture\n"); | 685 | "capture\n"); |
638 | cx18_stop_v4l2_encode_stream(s_vbi, 0); | 686 | cx18_stop_v4l2_encode_stream(s_vbi, 0); |
687 | } | ||
688 | if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) { | ||
689 | CX18_DEBUG_INFO("close stopping IDX capture\n"); | ||
690 | cx18_stop_v4l2_encode_stream(s_idx, 0); | ||
691 | } | ||
639 | } | 692 | } |
640 | if (id->type == CX18_ENC_STREAM_TYPE_VBI && | 693 | if (id->type == CX18_ENC_STREAM_TYPE_VBI && |
641 | test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) | 694 | test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) |
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index 304b6bc5121b..9755f4416e96 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c | |||
@@ -356,13 +356,6 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister) | |||
356 | } | 356 | } |
357 | } | 357 | } |
358 | 358 | ||
359 | static inline bool cx18_stream_enabled(struct cx18_stream *s) | ||
360 | { | ||
361 | return s->video_dev || s->dvb.enabled || | ||
362 | (s->type == CX18_ENC_STREAM_TYPE_IDX && | ||
363 | s->cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] != 0); | ||
364 | } | ||
365 | |||
366 | static void cx18_vbi_setup(struct cx18_stream *s) | 359 | static void cx18_vbi_setup(struct cx18_stream *s) |
367 | { | 360 | { |
368 | struct cx18 *cx = s->cx; | 361 | struct cx18 *cx = s->cx; |
diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h index 4a01db5e5a35..7b36225c4abe 100644 --- a/drivers/media/video/cx18/cx18-streams.h +++ b/drivers/media/video/cx18/cx18-streams.h | |||
@@ -28,6 +28,13 @@ int cx18_streams_setup(struct cx18 *cx); | |||
28 | int cx18_streams_register(struct cx18 *cx); | 28 | int cx18_streams_register(struct cx18 *cx); |
29 | void cx18_streams_cleanup(struct cx18 *cx, int unregister); | 29 | void cx18_streams_cleanup(struct cx18 *cx, int unregister); |
30 | 30 | ||
31 | static inline bool cx18_stream_enabled(struct cx18_stream *s) | ||
32 | { | ||
33 | return s->video_dev || s->dvb.enabled || | ||
34 | (s->type == CX18_ENC_STREAM_TYPE_IDX && | ||
35 | s->cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] != 0); | ||
36 | } | ||
37 | |||
31 | /* Related to submission of mdls to firmware */ | 38 | /* Related to submission of mdls to firmware */ |
32 | static inline void cx18_stream_load_fw_queue(struct cx18_stream *s) | 39 | static inline void cx18_stream_load_fw_queue(struct cx18_stream *s) |
33 | { | 40 | { |