diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2007-08-23 16:51:07 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-10-09 21:06:49 -0400 |
commit | 559e196a56a5d518181efc1d2fefe0892f4689b4 (patch) | |
tree | 99de577c399d281b6d599ec9a7ba6ddb0a148780 /drivers/media | |
parent | a158f3559334c6314c7876390caffe88c9fdb64d (diff) |
V4L/DVB (6096): ivtv: fix V4L2_ENC_CMD_STOP_AT_GOP_END support
Support for V4L2_ENC_CMD_STOP_AT_GOP_END was broken. While the driver
correctly waited for the card to capture until the GOP was complete,
afterwards the driver buffers were just flushed instead of waiting
for the application to read all the pending data.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/ivtv/ivtv-fileops.c | 37 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-streams.c | 8 |
2 files changed, 26 insertions, 19 deletions
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 170bef61aa62..5b5d6666fa16 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c | |||
@@ -258,19 +258,19 @@ static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, | |||
258 | } | 258 | } |
259 | return buf; | 259 | return buf; |
260 | } | 260 | } |
261 | /* return if file was opened with O_NONBLOCK */ | ||
262 | if (non_block) { | ||
263 | *err = -EAGAIN; | ||
264 | return NULL; | ||
265 | } | ||
266 | 261 | ||
267 | /* return if end of stream */ | 262 | /* return if end of stream */ |
268 | if (s->type != IVTV_DEC_STREAM_TYPE_VBI && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { | 263 | if (s->type != IVTV_DEC_STREAM_TYPE_VBI && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { |
269 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | ||
270 | IVTV_DEBUG_INFO("EOS %s\n", s->name); | 264 | IVTV_DEBUG_INFO("EOS %s\n", s->name); |
271 | return NULL; | 265 | return NULL; |
272 | } | 266 | } |
273 | 267 | ||
268 | /* return if file was opened with O_NONBLOCK */ | ||
269 | if (non_block) { | ||
270 | *err = -EAGAIN; | ||
271 | return NULL; | ||
272 | } | ||
273 | |||
274 | /* wait for more data to arrive */ | 274 | /* wait for more data to arrive */ |
275 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); | 275 | prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); |
276 | /* New buffers might have become available before we were added to the waitqueue */ | 276 | /* New buffers might have become available before we were added to the waitqueue */ |
@@ -378,10 +378,20 @@ static ssize_t ivtv_read(struct ivtv_stream *s, char __user *ubuf, size_t tot_co | |||
378 | int rc; | 378 | int rc; |
379 | 379 | ||
380 | buf = ivtv_get_buffer(s, non_block, &rc); | 380 | buf = ivtv_get_buffer(s, non_block, &rc); |
381 | if (buf == NULL && rc == -EAGAIN && tot_written) | 381 | /* if there is no data available... */ |
382 | break; | 382 | if (buf == NULL) { |
383 | if (buf == NULL) | 383 | /* if we got data, then return that regardless */ |
384 | if (tot_written) | ||
385 | break; | ||
386 | /* EOS condition */ | ||
387 | if (rc == 0) { | ||
388 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | ||
389 | clear_bit(IVTV_F_S_APPL_IO, &s->s_flags); | ||
390 | ivtv_release_stream(s); | ||
391 | } | ||
392 | /* set errno */ | ||
384 | return rc; | 393 | return rc; |
394 | } | ||
385 | rc = ivtv_copy_buf_to_user(s, buf, ubuf + tot_written, tot_count - tot_written); | 395 | rc = ivtv_copy_buf_to_user(s, buf, ubuf + tot_written, tot_count - tot_written); |
386 | if (buf != &itv->vbi.sliced_mpeg_buf) { | 396 | if (buf != &itv->vbi.sliced_mpeg_buf) { |
387 | ivtv_enqueue(s, buf, (buf->readpos == buf->bytesused) ? &s->q_free : &s->q_io); | 397 | ivtv_enqueue(s, buf, (buf->readpos == buf->bytesused) ? &s->q_free : &s->q_io); |
@@ -738,10 +748,11 @@ void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end) | |||
738 | ivtv_stop_v4l2_encode_stream(s, gop_end); | 748 | ivtv_stop_v4l2_encode_stream(s, gop_end); |
739 | } | 749 | } |
740 | } | 750 | } |
741 | clear_bit(IVTV_F_S_APPL_IO, &s->s_flags); | 751 | if (!gop_end) { |
742 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | 752 | clear_bit(IVTV_F_S_APPL_IO, &s->s_flags); |
743 | 753 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | |
744 | ivtv_release_stream(s); | 754 | ivtv_release_stream(s); |
755 | } | ||
745 | } | 756 | } |
746 | 757 | ||
747 | static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts) | 758 | static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts) |
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index e05af62a8cd5..a3296224f821 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c | |||
@@ -719,7 +719,6 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) | |||
719 | struct ivtv *itv = s->itv; | 719 | struct ivtv *itv = s->itv; |
720 | DECLARE_WAITQUEUE(wait, current); | 720 | DECLARE_WAITQUEUE(wait, current); |
721 | int cap_type; | 721 | int cap_type; |
722 | unsigned long then; | ||
723 | int stopmode; | 722 | int stopmode; |
724 | 723 | ||
725 | if (s->v4l2dev == NULL) | 724 | if (s->v4l2dev == NULL) |
@@ -762,14 +761,12 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) | |||
762 | /* when: 0 = end of GOP 1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */ | 761 | /* when: 0 = end of GOP 1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */ |
763 | ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype); | 762 | ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype); |
764 | 763 | ||
765 | then = jiffies; | ||
766 | |||
767 | if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) { | 764 | if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) { |
768 | if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) { | 765 | if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) { |
769 | /* only run these if we're shutting down the last cap */ | 766 | /* only run these if we're shutting down the last cap */ |
770 | unsigned long duration; | 767 | unsigned long duration; |
768 | unsigned long then = jiffies; | ||
771 | 769 | ||
772 | then = jiffies; | ||
773 | add_wait_queue(&itv->eos_waitq, &wait); | 770 | add_wait_queue(&itv->eos_waitq, &wait); |
774 | 771 | ||
775 | set_current_state(TASK_INTERRUPTIBLE); | 772 | set_current_state(TASK_INTERRUPTIBLE); |
@@ -797,10 +794,9 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) | |||
797 | } | 794 | } |
798 | set_current_state(TASK_RUNNING); | 795 | set_current_state(TASK_RUNNING); |
799 | remove_wait_queue(&itv->eos_waitq, &wait); | 796 | remove_wait_queue(&itv->eos_waitq, &wait); |
797 | set_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | ||
800 | } | 798 | } |
801 | 799 | ||
802 | then = jiffies; | ||
803 | |||
804 | /* Handle any pending interrupts */ | 800 | /* Handle any pending interrupts */ |
805 | ivtv_msleep_timeout(100, 1); | 801 | ivtv_msleep_timeout(100, 1); |
806 | } | 802 | } |