Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 181463
b: refs/heads/master
c: 82acdc8
h: refs/heads/master
i:
  181461: d7ae5c1
  181459: 48d69b5
  181455: 0aed9d4
v: v3
  • Loading branch information
Andy Walls authored and Mauro Carvalho Chehab committed Feb 26, 2010
1 parent d7bb39c commit 13434a0
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 14 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ef99179710d6ec04d6783afdf8387523c7087920
refs/heads/master: 82acdc84cc4acc11389bdc648b23b15426d2038c
12 changes: 12 additions & 0 deletions trunk/drivers/media/video/cx18/cx18-driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,18 @@ struct cx18_options {
#define CX18_SLICED_TYPE_WSS_625 (5)
#define CX18_SLICED_TYPE_VPS (7)

/**
* list_entry_is_past_end - check if a previous loop cursor is off list end
* @pos: the type * previously used as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Check if the entry's list_head is the head of the list, thus it's not a
* real entry but was the loop cursor that walked past the end
*/
#define list_entry_is_past_end(pos, head, member) \
(&pos->member == (head))

struct cx18_buffer {
struct list_head list;
dma_addr_t dma_handle;
Expand Down
12 changes: 0 additions & 12 deletions trunk/drivers/media/video/cx18/cx18-fileops.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,18 +392,6 @@ static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
return len;
}

/**
* list_entry_is_past_end - check if a previous loop cursor is off list end
* @pos: the type * previously used as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Check if the entry's list_head is the head of the list, thus it's not a
* real entry but was the loop cursor that walked past the end
*/
#define list_entry_is_past_end(pos, head, member) \
(&pos->member == (head))

static size_t cx18_copy_mdl_to_user(struct cx18_stream *s,
struct cx18_mdl *mdl, char __user *ubuf, size_t ucount)
{
Expand Down
135 changes: 134 additions & 1 deletion trunk/drivers/media/video/cx18/cx18-ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -775,10 +775,143 @@ static int cx18_g_sliced_vbi_cap(struct file *file, void *fh,
return 0;
}

static int _cx18_process_idx_data(struct cx18_buffer *buf,
struct v4l2_enc_idx *idx)
{
int consumed, remaining;
struct v4l2_enc_idx_entry *e_idx;
struct cx18_enc_idx_entry *e_buf;

/* Frame type lookup: 1=I, 2=P, 4=B */
const int mapping[8] = {
-1, V4L2_ENC_IDX_FRAME_I, V4L2_ENC_IDX_FRAME_P,
-1, V4L2_ENC_IDX_FRAME_B, -1, -1, -1
};

/*
* Assumption here is that a buf holds an integral number of
* struct cx18_enc_idx_entry objects and is properly aligned.
* This is enforced by the module options on IDX buffer sizes.
*/
remaining = buf->bytesused - buf->readpos;
consumed = 0;
e_idx = &idx->entry[idx->entries];
e_buf = (struct cx18_enc_idx_entry *) &buf->buf[buf->readpos];

while (remaining >= sizeof(struct cx18_enc_idx_entry) &&
idx->entries < V4L2_ENC_IDX_ENTRIES) {

e_idx->offset = (((u64) le32_to_cpu(e_buf->offset_high)) << 32)
| le32_to_cpu(e_buf->offset_low);

e_idx->pts = (((u64) (le32_to_cpu(e_buf->pts_high) & 1)) << 32)
| le32_to_cpu(e_buf->pts_low);

e_idx->length = le32_to_cpu(e_buf->length);

e_idx->flags = mapping[le32_to_cpu(e_buf->flags) & 0x7];

e_idx->reserved[0] = 0;
e_idx->reserved[1] = 0;

idx->entries++;
e_idx = &idx->entry[idx->entries];
e_buf++;

remaining -= sizeof(struct cx18_enc_idx_entry);
consumed += sizeof(struct cx18_enc_idx_entry);
}

/* Swallow any partial entries at the end, if there are any */
if (remaining > 0 && remaining < sizeof(struct cx18_enc_idx_entry))
consumed += remaining;

buf->readpos += consumed;
return consumed;
}

static int cx18_process_idx_data(struct cx18_stream *s, struct cx18_mdl *mdl,
struct v4l2_enc_idx *idx)
{
if (s->type != CX18_ENC_STREAM_TYPE_IDX)
return -EINVAL;

if (mdl->curr_buf == NULL)
mdl->curr_buf = list_first_entry(&mdl->buf_list,
struct cx18_buffer, list);

if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) {
/*
* For some reason we've exhausted the buffers, but the MDL
* object still said some data was unread.
* Fix that and bail out.
*/
mdl->readpos = mdl->bytesused;
return 0;
}

list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) {

/* Skip any empty buffers in the MDL */
if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused)
continue;

mdl->readpos += _cx18_process_idx_data(mdl->curr_buf, idx);

/* exit when MDL drained or request satisfied */
if (idx->entries >= V4L2_ENC_IDX_ENTRIES ||
mdl->curr_buf->readpos < mdl->curr_buf->bytesused ||
mdl->readpos >= mdl->bytesused)
break;
}
return 0;
}

static int cx18_g_enc_index(struct file *file, void *fh,
struct v4l2_enc_idx *idx)
{
return -EINVAL;
struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
s32 tmp;
struct cx18_mdl *mdl;

if (!cx18_stream_enabled(s)) /* Module options inhibited IDX stream */
return -EINVAL;

/* Compute the best case number of entries we can buffer */
tmp = s->buffers -
s->bufs_per_mdl * CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN;
if (tmp <= 0)
tmp = 1;
tmp = tmp * s->buf_size / sizeof(struct cx18_enc_idx_entry);

/* Fill out the header of the return structure */
idx->entries = 0;
idx->entries_cap = tmp;
memset(idx->reserved, 0, sizeof(idx->reserved));

/* Pull IDX MDLs and buffers from q_full and populate the entries */
do {
mdl = cx18_dequeue(s, &s->q_full);
if (mdl == NULL) /* No more IDX data right now */
break;

/* Extract the Index entry data from the MDL and buffers */
cx18_process_idx_data(s, mdl, idx);
if (mdl->readpos < mdl->bytesused) {
/* We finished with data remaining, push the MDL back */
cx18_push(s, mdl, &s->q_full);
break;
}

/* We drained this MDL, schedule it to go to the firmware */
cx18_enqueue(s, mdl, &s->q_free);

} while (idx->entries < V4L2_ENC_IDX_ENTRIES);

/* Tell the work handler to send free IDX MDLs to the firmware */
cx18_stream_load_fw_queue(s);
return 0;
}

static int cx18_encoder_cmd(struct file *file, void *fh,
Expand Down

0 comments on commit 13434a0

Please sign in to comment.