V4L/DVB (13906): cx18: Start IDX streams automatically as an internal associated...
authorAndy Walls <awalls@radix.net>
Thu, 31 Dec 2009 20:19:25 +0000 (17:19 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Fri, 26 Feb 2010 18:10:30 +0000 (15:10 -0300)
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>
drivers/media/video/cx18/cx18-fileops.c
drivers/media/video/cx18/cx18-streams.c
drivers/media/video/cx18/cx18-streams.h

index c0885c6..b1ad03f 100644 (file)
 
 /* This function tries to claim the stream for a specific file descriptor.
    If no one else is using this stream then the stream is claimed and
-   associated VBI streams are also automatically claimed.
+   associated VBI and IDX streams are also automatically claimed.
    Possible error returns: -EBUSY if someone else has claimed
    the stream or 0 on success. */
 static int cx18_claim_stream(struct cx18_open_id *id, int type)
 {
        struct cx18 *cx = id->cx;
        struct cx18_stream *s = &cx->streams[type];
-       struct cx18_stream *s_vbi;
-       int vbi_type;
+       struct cx18_stream *s_assoc;
+
+       /* Nothing should ever try to directly claim the IDX stream */
+       if (type == CX18_ENC_STREAM_TYPE_IDX) {
+               CX18_WARN("MPEG Index stream cannot be claimed "
+                         "directly, but something tried.\n");
+               return -EINVAL;
+       }
 
        if (test_and_set_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
                /* someone already claimed this stream */
@@ -67,21 +73,27 @@ static int cx18_claim_stream(struct cx18_open_id *id, int type)
        }
        s->id = id->open_id;
 
-       /* CX18_ENC_STREAM_TYPE_MPG needs to claim CX18_ENC_STREAM_TYPE_VBI
-          (provided VBI insertion is on and sliced VBI is selected), for all
-          other streams we're done */
-       if (type == CX18_ENC_STREAM_TYPE_MPG &&
-           cx->vbi.insert_mpeg && !cx18_raw_vbi(cx)) {
-               vbi_type = CX18_ENC_STREAM_TYPE_VBI;
-       } else {
+       /*
+        * CX18_ENC_STREAM_TYPE_MPG needs to claim:
+        * CX18_ENC_STREAM_TYPE_VBI, if VBI insertion is on for sliced VBI, or
+        * CX18_ENC_STREAM_TYPE_IDX, if VBI insertion is off for sliced VBI
+        * (We don't yet fix up MPEG Index entries for our inserted packets).
+        *
+        * For all other streams we're done.
+        */
+       if (type != CX18_ENC_STREAM_TYPE_MPG)
                return 0;
-       }
-       s_vbi = &cx->streams[vbi_type];
 
-       set_bit(CX18_F_S_CLAIMED, &s_vbi->s_flags);
+       s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+       if (cx->vbi.insert_mpeg && !cx18_raw_vbi(cx))
+               s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+       else if (!cx18_stream_enabled(s_assoc))
+               return 0;
+
+       set_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
 
        /* mark that it is used internally */
-       set_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags);
+       set_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags);
        return 0;
 }
 
@@ -90,9 +102,17 @@ static int cx18_claim_stream(struct cx18_open_id *id, int type)
 static void cx18_release_stream(struct cx18_stream *s)
 {
        struct cx18 *cx = s->cx;
-       struct cx18_stream *s_vbi;
+       struct cx18_stream *s_assoc;
 
        s->id = -1;
+       if (s->type == CX18_ENC_STREAM_TYPE_IDX) {
+               /*
+                * The IDX stream is only used internally, and can
+                * only be indirectly unclaimed by unclaiming the MPG stream.
+                */
+               return;
+       }
+
        if (s->type == CX18_ENC_STREAM_TYPE_VBI &&
                test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) {
                /* this stream is still in use internally */
@@ -105,24 +125,34 @@ static void cx18_release_stream(struct cx18_stream *s)
 
        cx18_flush_queues(s);
 
-       /* CX18_ENC_STREAM_TYPE_MPG needs to release CX18_ENC_STREAM_TYPE_VBI,
-          for all other streams we're done */
-       if (s->type == CX18_ENC_STREAM_TYPE_MPG)
-               s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
-       else
+       /*
+        * CX18_ENC_STREAM_TYPE_MPG needs to release the
+        * CX18_ENC_STREAM_TYPE_VBI and/or CX18_ENC_STREAM_TYPE_IDX streams.
+        *
+        * For all other streams we're done.
+        */
+       if (s->type != CX18_ENC_STREAM_TYPE_MPG)
                return;
 
-       /* clear internal use flag */
-       if (!test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags)) {
-               /* was already cleared */
-               return;
+       /* Unclaim the associated MPEG Index stream */
+       s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+       if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) {
+               clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
+               cx18_flush_queues(s_assoc);
        }
-       if (s_vbi->id != -1) {
-               /* VBI stream still claimed by a file descriptor */
-               return;
+
+       /* Unclaim the associated VBI stream */
+       s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+       if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) {
+               if (s_assoc->id == -1) {
+                       /*
+                        * The VBI stream is not still claimed by a file
+                        * descriptor, so completely unclaim it.
+                        */
+                       clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
+                       cx18_flush_queues(s_assoc);
+               }
        }
-       clear_bit(CX18_F_S_CLAIMED, &s_vbi->s_flags);
-       cx18_flush_queues(s_vbi);
 }
 
 static void cx18_dualwatch(struct cx18 *cx)
@@ -498,6 +528,7 @@ int cx18_start_capture(struct cx18_open_id *id)
        struct cx18 *cx = id->cx;
        struct cx18_stream *s = &cx->streams[id->type];
        struct cx18_stream *s_vbi;
+       struct cx18_stream *s_idx;
 
        if (s->type == CX18_ENC_STREAM_TYPE_RAD) {
                /* you cannot read from these stream types. */
@@ -516,25 +547,33 @@ int cx18_start_capture(struct cx18_open_id *id)
                return 0;
        }
 
-       /* Start VBI capture if required */
+       /* Start associated VBI or IDX stream capture if required */
        s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
-       if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
-           test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
-           !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
-               /* Note: the CX18_ENC_STREAM_TYPE_VBI is claimed
-                  automatically when the MPG stream is claimed.
-                  We only need to start the VBI capturing. */
-               if (cx18_start_v4l2_encode_stream(s_vbi)) {
-                       CX18_DEBUG_WARN("VBI capture start failed\n");
-
-                       /* Failure, clean up and return an error */
-                       clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
-                       clear_bit(CX18_F_S_STREAMING, &s->s_flags);
-                       /* also releases the associated VBI stream */
-                       cx18_release_stream(s);
-                       return -EIO;
+       s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+       if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
+               /*
+                * The VBI and IDX streams should have been claimed
+                * automatically, if for internal use, when the MPG stream was
+                * claimed.  We only need to start these streams capturing.
+                */
+               if (test_bit(CX18_F_S_INTERNAL_USE, &s_idx->s_flags) &&
+                   !test_and_set_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
+                       if (cx18_start_v4l2_encode_stream(s_idx)) {
+                               CX18_DEBUG_WARN("IDX capture start failed\n");
+                               clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
+                               goto start_failed;
+                       }
+                       CX18_DEBUG_INFO("IDX capture started\n");
+               }
+               if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
+                   !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
+                       if (cx18_start_v4l2_encode_stream(s_vbi)) {
+                               CX18_DEBUG_WARN("VBI capture start failed\n");
+                               clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
+                               goto start_failed;
+                       }
+                       CX18_DEBUG_INFO("VBI insertion started\n");
                }
-               CX18_DEBUG_INFO("VBI insertion started\n");
        }
 
        /* Tell the card to start capturing */
@@ -547,19 +586,29 @@ int cx18_start_capture(struct cx18_open_id *id)
                return 0;
        }
 
-       /* failure, clean up */
+start_failed:
        CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name);
 
-       /* Note: the CX18_ENC_STREAM_TYPE_VBI is released
-          automatically when the MPG stream is released.
-          We only need to stop the VBI capturing. */
-       if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
-           test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
-               cx18_stop_v4l2_encode_stream(s_vbi, 0);
-               clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
+       /*
+        * The associated VBI and IDX streams for internal use are released
+        * automatically when the MPG stream is released.  We only need to stop
+        * the associated stream.
+        */
+       if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
+               /* Stop the IDX stream which is always for internal use */
+               if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
+                       cx18_stop_v4l2_encode_stream(s_idx, 0);
+                       clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
+               }
+               /* Stop the VBI stream, if only running for internal use */
+               if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
+                   !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
+                       cx18_stop_v4l2_encode_stream(s_vbi, 0);
+                       clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
+               }
        }
        clear_bit(CX18_F_S_STREAMING, &s->s_flags);
-       cx18_release_stream(s);
+       cx18_release_stream(s); /* Also releases associated streams */
        return -EIO;
 }
 
@@ -618,6 +667,8 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
 {
        struct cx18 *cx = id->cx;
        struct cx18_stream *s = &cx->streams[id->type];
+       struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+       struct cx18_stream *s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
 
        CX18_DEBUG_IOCTL("close() of %s\n", s->name);
 
@@ -625,17 +676,19 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
 
        /* Stop capturing */
        if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
-               struct cx18_stream *s_vbi =
-                       &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
-
                CX18_DEBUG_INFO("close stopping capture\n");
-               /* Special case: a running VBI capture for VBI insertion
-                  in the mpeg stream. Need to stop that too. */
-               if (id->type == CX18_ENC_STREAM_TYPE_MPG &&
-                   test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
-                   !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
-                       CX18_DEBUG_INFO("close stopping embedded VBI capture\n");
-                       cx18_stop_v4l2_encode_stream(s_vbi, 0);
+               if (id->type == CX18_ENC_STREAM_TYPE_MPG) {
+                       /* Stop internal use associated VBI and IDX streams */
+                       if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
+                           !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
+                               CX18_DEBUG_INFO("close stopping embedded VBI "
+                                               "capture\n");
+                               cx18_stop_v4l2_encode_stream(s_vbi, 0);
+                       }
+                       if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
+                               CX18_DEBUG_INFO("close stopping IDX capture\n");
+                               cx18_stop_v4l2_encode_stream(s_idx, 0);
+                       }
                }
                if (id->type == CX18_ENC_STREAM_TYPE_VBI &&
                    test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags))
index 304b6bc..9755f44 100644 (file)
@@ -356,13 +356,6 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister)
        }
 }
 
-static inline bool cx18_stream_enabled(struct cx18_stream *s)
-{
-       return s->video_dev || s->dvb.enabled ||
-              (s->type == CX18_ENC_STREAM_TYPE_IDX &&
-               s->cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] != 0);
-}
-
 static void cx18_vbi_setup(struct cx18_stream *s)
 {
        struct cx18 *cx = s->cx;
index 4a01db5..7b36225 100644 (file)
@@ -28,6 +28,13 @@ int cx18_streams_setup(struct cx18 *cx);
 int cx18_streams_register(struct cx18 *cx);
 void cx18_streams_cleanup(struct cx18 *cx, int unregister);
 
+static inline bool cx18_stream_enabled(struct cx18_stream *s)
+{
+       return s->video_dev || s->dvb.enabled ||
+              (s->type == CX18_ENC_STREAM_TYPE_IDX &&
+               s->cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] != 0);
+}
+
 /* Related to submission of mdls to firmware */
 static inline void cx18_stream_load_fw_queue(struct cx18_stream *s)
 {