Esempio n. 1
0
static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
                                    struct cx18_buffer *buf, char __user *ubuf, size_t ucount)
{
    struct cx18 *cx = s->cx;
    size_t len = buf->bytesused - buf->readpos;

    if (len > ucount)
        len = ucount;
    if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG &&
            cx->vbi.sliced_in->service_set && buf != &cx->vbi.sliced_mpeg_buf) {
        const char *start = buf->buf + buf->readpos;
        const char *p = start + 1;
        const u8 *q;
        u8 ch = cx->search_pack_header ? 0xba : 0xe0;
        int stuffing, i;

        while (start + len > p) {
            q = memchr(p, 0, start + len - p);
            if (q == NULL)
                break;
            p = q + 1;
            if ((char *)q + 15 >= buf->buf + buf->bytesused ||
                    q[1] != 0 || q[2] != 1 || q[3] != ch)
                continue;
            if (!cx->search_pack_header) {
                if ((q[6] & 0xc0) != 0x80)
                    continue;
                if (((q[7] & 0xc0) == 0x80 &&
                        (q[9] & 0xf0) == 0x20) ||
                        ((q[7] & 0xc0) == 0xc0 &&
                         (q[9] & 0xf0) == 0x30)) {
                    ch = 0xba;
                    cx->search_pack_header = 1;
                    p = q + 9;
                }
                continue;
            }
            stuffing = q[13] & 7;
            /* all stuffing bytes must be 0xff */
            for (i = 0; i < stuffing; i++)
                if (q[14 + i] != 0xff)
                    break;
            if (i == stuffing &&
                    (q[4] & 0xc4) == 0x44 &&
                    (q[12] & 3) == 3 &&
                    q[14 + stuffing] == 0 &&
                    q[15 + stuffing] == 0 &&
                    q[16 + stuffing] == 1) {
                cx->search_pack_header = 0;
                len = (char *)q - start;
                cx18_setup_sliced_vbi_buf(cx);
                break;
            }
        }
    }
    if (copy_to_user(ubuf, (u8 *)buf->buf + buf->readpos, len)) {
        CX18_DEBUG_WARN("copy %zd bytes to user failed for %s\n",
                        len, s->name);
        return -EFAULT;
    }
    buf->readpos += len;
    if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
            buf != &cx->vbi.sliced_mpeg_buf)
        cx->mpg_data_received += len;
    return len;
}
Esempio n. 2
0
static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
		struct cx18_buffer *buf, char __user *ubuf, size_t ucount)
{
	struct cx18 *cx = s->cx;
	size_t len = buf->bytesused - buf->readpos;

	if (len > ucount)
		len = ucount;
	if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG &&
	    !cx18_raw_vbi(cx) && buf != &cx->vbi.sliced_mpeg_buf) {
		/*
		 * Try to find a good splice point in the PS, just before
		 * an MPEG-2 Program Pack start code, and provide only
		 * up to that point to the user, so it's easy to insert VBI data
		 * the next time around.
		 *
		 * This will not work for an MPEG-2 TS and has only been
		 * verified by analysis to work for an MPEG-2 PS.  Helen Buus
		 * pointed out this works for the CX23416 MPEG-2 DVD compatible
		 * stream, and research indicates both the MPEG 2 SVCD and DVD
		 * stream types use an MPEG-2 PS container.
		 */
		/*
		 * An MPEG-2 Program Stream (PS) is a series of
		 * MPEG-2 Program Packs terminated by an
		 * MPEG Program End Code after the last Program Pack.
		 * A Program Pack may hold a PS System Header packet and any
		 * number of Program Elementary Stream (PES) Packets
		 */
		const char *start = buf->buf + buf->readpos;
		const char *p = start + 1;
		const u8 *q;
		u8 ch = cx->search_pack_header ? 0xba : 0xe0;
		int stuffing, i;

		while (start + len > p) {
			/* Scan for a 0 to find a potential MPEG-2 start code */
			q = memchr(p, 0, start + len - p);
			if (q == NULL)
				break;
			p = q + 1;
			/*
			 * Keep looking if not a
			 * MPEG-2 Pack header start code:  0x00 0x00 0x01 0xba
			 * or MPEG-2 video PES start code: 0x00 0x00 0x01 0xe0
			 */
			if ((char *)q + 15 >= buf->buf + buf->bytesused ||
			    q[1] != 0 || q[2] != 1 || q[3] != ch)
				continue;

			/* If expecting the primary video PES */
			if (!cx->search_pack_header) {
				/* Continue if it couldn't be a PES packet */
				if ((q[6] & 0xc0) != 0x80)
					continue;
				/* Check if a PTS or PTS & DTS follow */
				if (((q[7] & 0xc0) == 0x80 &&  /* PTS only */
				     (q[9] & 0xf0) == 0x20) || /* PTS only */
				    ((q[7] & 0xc0) == 0xc0 &&  /* PTS & DTS */
				     (q[9] & 0xf0) == 0x30)) { /* DTS follows */
					/* Assume we found the video PES hdr */
					ch = 0xba; /* next want a Program Pack*/
					cx->search_pack_header = 1;
					p = q + 9; /* Skip this video PES hdr */
				}
				continue;
			}

			/* We may have found a Program Pack start code */

			/* Get the count of stuffing bytes & verify them */
			stuffing = q[13] & 7;
			/* all stuffing bytes must be 0xff */
			for (i = 0; i < stuffing; i++)
				if (q[14 + i] != 0xff)
					break;
			if (i == stuffing && /* right number of stuffing bytes*/
			    (q[4] & 0xc4) == 0x44 && /* marker check */
			    (q[12] & 3) == 3 &&  /* marker check */
			    q[14 + stuffing] == 0 && /* PES Pack or Sys Hdr */
			    q[15 + stuffing] == 0 &&
			    q[16 + stuffing] == 1) {
				/* We declare we actually found a Program Pack*/
				cx->search_pack_header = 0; /* expect vid PES */
				len = (char *)q - start;
				cx18_setup_sliced_vbi_buf(cx);
				break;
			}
		}
	}
	if (copy_to_user(ubuf, (u8 *)buf->buf + buf->readpos, len)) {
		CX18_DEBUG_WARN("copy %zd bytes to user failed for %s\n",
				len, s->name);
		return -EFAULT;
	}
	buf->readpos += len;
	if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
	    buf != &cx->vbi.sliced_mpeg_buf)
		cx->mpg_data_received += len;
	return len;
}