mirror of
https://github.com/torvalds/linux.git
synced 2024-11-01 01:31:44 +00:00
[media] gspca_sonixb: Rewrite start of frame detection
Our old start of frame detection code wrongly assumes that the sof marker always lives at the beginning of the frame. At least for the 0c45:602a camera this is not the case. This patch also improves the framerate from 28 fps to 30 fps with the 0c45:6005 and 0c45:6007 Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
d6746d55da
commit
2b3e284a89
@ -56,6 +56,8 @@ struct sd {
|
||||
int prev_avg_lum;
|
||||
int exp_too_low_cnt;
|
||||
int exp_too_high_cnt;
|
||||
int header_read;
|
||||
u8 header[12]; /* Header without sof marker */
|
||||
|
||||
unsigned short exposure;
|
||||
unsigned char gain;
|
||||
@ -1177,13 +1179,10 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
|
||||
sd_init(gspca_dev);
|
||||
}
|
||||
|
||||
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||||
u8 *data, /* isoc packet */
|
||||
int len) /* iso packet length */
|
||||
static u8* find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
|
||||
{
|
||||
int i;
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
struct cam *cam = &gspca_dev->cam;
|
||||
int i, header_size = (sd->bridge == BRIDGE_103) ? 18 : 12;
|
||||
|
||||
/* frames start with:
|
||||
* ff ff 00 c4 c4 96 synchro
|
||||
@ -1194,58 +1193,84 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||||
* ll mm brightness sum outside auto exposure
|
||||
* (xx xx xx xx xx) audio values for snc103
|
||||
*/
|
||||
if (len > 6 && len < 24) {
|
||||
for (i = 0; i < len - 6; i++) {
|
||||
if (data[0 + i] == 0xff
|
||||
&& data[1 + i] == 0xff
|
||||
&& data[2 + i] == 0x00
|
||||
&& data[3 + i] == 0xc4
|
||||
&& data[4 + i] == 0xc4
|
||||
&& data[5 + i] == 0x96) { /* start of frame */
|
||||
int lum = -1;
|
||||
int pkt_type = LAST_PACKET;
|
||||
int fr_h_sz = (sd->bridge == BRIDGE_103) ?
|
||||
18 : 12;
|
||||
|
||||
if (len - i < fr_h_sz) {
|
||||
PDEBUG(D_STREAM, "packet too short to"
|
||||
" get avg brightness");
|
||||
} else if (sd->bridge == BRIDGE_103) {
|
||||
lum = data[i + 9] +
|
||||
(data[i + 10] << 8);
|
||||
} else {
|
||||
lum = data[i + 8] + (data[i + 9] << 8);
|
||||
}
|
||||
/* When exposure changes midway a frame we
|
||||
get a lum of 0 in this case drop 2 frames
|
||||
as the frames directly after an exposure
|
||||
change have an unstable image. Sometimes lum
|
||||
*really* is 0 (cam used in low light with
|
||||
low exposure setting), so do not drop frames
|
||||
if the previous lum was 0 too. */
|
||||
if (lum == 0 && sd->prev_avg_lum != 0) {
|
||||
lum = -1;
|
||||
sd->frames_to_drop = 2;
|
||||
sd->prev_avg_lum = 0;
|
||||
} else
|
||||
sd->prev_avg_lum = lum;
|
||||
atomic_set(&sd->avg_lum, lum);
|
||||
|
||||
if (sd->frames_to_drop) {
|
||||
sd->frames_to_drop--;
|
||||
pkt_type = DISCARD_PACKET;
|
||||
}
|
||||
|
||||
gspca_frame_add(gspca_dev, pkt_type,
|
||||
NULL, 0);
|
||||
data += i + fr_h_sz;
|
||||
len -= i + fr_h_sz;
|
||||
gspca_frame_add(gspca_dev, FIRST_PACKET,
|
||||
data, len);
|
||||
return;
|
||||
for (i = 0; i < len; i++) {
|
||||
switch (sd->header_read) {
|
||||
case 0:
|
||||
if (data[i] == 0xff)
|
||||
sd->header_read++;
|
||||
break;
|
||||
case 1:
|
||||
if (data[i] == 0xff)
|
||||
sd->header_read++;
|
||||
else
|
||||
sd->header_read = 0;
|
||||
break;
|
||||
case 2:
|
||||
if (data[i] == 0x00)
|
||||
sd->header_read++;
|
||||
else if (data[i] != 0xff)
|
||||
sd->header_read = 0;
|
||||
break;
|
||||
case 3:
|
||||
if (data[i] == 0xc4)
|
||||
sd->header_read++;
|
||||
else if (data[i] == 0xff)
|
||||
sd->header_read = 1;
|
||||
else
|
||||
sd->header_read = 0;
|
||||
break;
|
||||
case 4:
|
||||
if (data[i] == 0xc4)
|
||||
sd->header_read++;
|
||||
else if (data[i] == 0xff)
|
||||
sd->header_read = 1;
|
||||
else
|
||||
sd->header_read = 0;
|
||||
break;
|
||||
case 5:
|
||||
if (data[i] == 0x96)
|
||||
sd->header_read++;
|
||||
else if (data[i] == 0xff)
|
||||
sd->header_read = 1;
|
||||
else
|
||||
sd->header_read = 0;
|
||||
break;
|
||||
default:
|
||||
sd->header[sd->header_read - 6] = data[i];
|
||||
sd->header_read++;
|
||||
if (sd->header_read == header_size) {
|
||||
sd->header_read = 0;
|
||||
return data + i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||||
u8 *data, /* isoc packet */
|
||||
int len) /* iso packet length */
|
||||
{
|
||||
int fr_h_sz = 0, lum_offset = 0, len_after_sof = 0;
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
struct cam *cam = &gspca_dev->cam;
|
||||
u8 *sof;
|
||||
|
||||
sof = find_sof(gspca_dev, data, len);
|
||||
if (sof) {
|
||||
if (sd->bridge == BRIDGE_103) {
|
||||
fr_h_sz = 18;
|
||||
lum_offset = 3;
|
||||
} else {
|
||||
fr_h_sz = 12;
|
||||
lum_offset = 2;
|
||||
}
|
||||
|
||||
len_after_sof = len - (sof - data);
|
||||
len = (sof - data) - fr_h_sz;
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
}
|
||||
|
||||
if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
|
||||
/* In raw mode we sometimes get some garbage after the frame
|
||||
@ -1259,6 +1284,33 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
|
||||
}
|
||||
|
||||
gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
|
||||
|
||||
if (sof) {
|
||||
int lum = sd->header[lum_offset] +
|
||||
(sd->header[lum_offset + 1] << 8);
|
||||
|
||||
/* When exposure changes midway a frame we
|
||||
get a lum of 0 in this case drop 2 frames
|
||||
as the frames directly after an exposure
|
||||
change have an unstable image. Sometimes lum
|
||||
*really* is 0 (cam used in low light with
|
||||
low exposure setting), so do not drop frames
|
||||
if the previous lum was 0 too. */
|
||||
if (lum == 0 && sd->prev_avg_lum != 0) {
|
||||
lum = -1;
|
||||
sd->frames_to_drop = 2;
|
||||
sd->prev_avg_lum = 0;
|
||||
} else
|
||||
sd->prev_avg_lum = lum;
|
||||
atomic_set(&sd->avg_lum, lum);
|
||||
|
||||
if (sd->frames_to_drop)
|
||||
sd->frames_to_drop--;
|
||||
else
|
||||
gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
|
||||
|
||||
gspca_frame_add(gspca_dev, FIRST_PACKET, sof, len_after_sof);
|
||||
}
|
||||
}
|
||||
|
||||
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
|
||||
|
Loading…
Reference in New Issue
Block a user