~ubuntu-branches/ubuntu/jaunty/xvidcap/jaunty-proposed

« back to all changes in this revision

Viewing changes to ffmpeg/libavformat/grab.c

  • Committer: Bazaar Package Importer
  • Author(s): Christian Marillat
  • Date: 2004-08-29 10:53:42 UTC
  • Revision ID: james.westby@ubuntu.com-20040829105342-qgmnry37eadfkoxx
Tags: upstream-1.1.3
ImportĀ upstreamĀ versionĀ 1.1.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Linux video grab interface
 
3
 * Copyright (c) 2000,2001 Fabrice Bellard.
 
4
 *
 
5
 * This library is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU Lesser General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2 of the License, or (at your option) any later version.
 
9
 *
 
10
 * This library is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Lesser General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Lesser General Public
 
16
 * License along with this library; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 */
 
19
#include "avformat.h"
 
20
#include <unistd.h>
 
21
#include <fcntl.h>
 
22
#include <sys/ioctl.h>
 
23
#include <sys/mman.h>
 
24
#include <sys/time.h>
 
25
#define _LINUX_TIME_H 1
 
26
#include <linux/videodev.h>
 
27
#include <time.h>
 
28
 
 
29
typedef struct {
 
30
    int fd;
 
31
    int frame_format; /* see VIDEO_PALETTE_xxx */
 
32
    int use_mmap;
 
33
    int width, height;
 
34
    int frame_rate;
 
35
    int frame_rate_base;
 
36
    int64_t time_frame;
 
37
    int frame_size;
 
38
    struct video_capability video_cap;
 
39
    struct video_audio audio_saved;
 
40
    uint8_t *video_buf;
 
41
    struct video_mbuf gb_buffers;
 
42
    struct video_mmap gb_buf;
 
43
    int gb_frame;
 
44
 
 
45
    /* ATI All In Wonder specific stuff */
 
46
    /* XXX: remove and merge in libavcodec/imgconvert.c */
 
47
    int aiw_enabled;
 
48
    int deint;
 
49
    int halfw;
 
50
    uint8_t *src_mem;
 
51
    uint8_t *lum_m4_mem;
 
52
} VideoData;
 
53
 
 
54
static int aiw_init(VideoData *s);
 
55
static int aiw_read_picture(VideoData *s, uint8_t *data);
 
56
static int aiw_close(VideoData *s);
 
57
 
 
58
static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap)
 
59
{
 
60
    VideoData *s = s1->priv_data;
 
61
    AVStream *st;
 
62
    int width, height;
 
63
    int video_fd, frame_size;
 
64
    int ret, frame_rate, frame_rate_base;
 
65
    int desired_palette;
 
66
    struct video_tuner tuner;
 
67
    struct video_audio audio;
 
68
    const char *video_device;
 
69
 
 
70
    if (!ap || ap->width <= 0 || ap->height <= 0 || ap->frame_rate <= 0)
 
71
        return -1;
 
72
    
 
73
    width = ap->width;
 
74
    height = ap->height;
 
75
    frame_rate      = ap->frame_rate;
 
76
    frame_rate_base = ap->frame_rate_base;
 
77
 
 
78
    st = av_new_stream(s1, 0);
 
79
    if (!st)
 
80
        return -ENOMEM;
 
81
 
 
82
    s->width = width;
 
83
    s->height = height;
 
84
    s->frame_rate      = frame_rate;
 
85
    s->frame_rate_base = frame_rate_base;
 
86
 
 
87
    video_device = ap->device;
 
88
    if (!video_device)
 
89
        video_device = "/dev/video";
 
90
    video_fd = open(video_device, O_RDWR);
 
91
    if (video_fd < 0) {
 
92
        perror(video_device);
 
93
        goto fail;
 
94
    }
 
95
    
 
96
    if (ioctl(video_fd,VIDIOCGCAP, &s->video_cap) < 0) {
 
97
        perror("VIDIOCGCAP");
 
98
        goto fail;
 
99
    }
 
100
 
 
101
    if (!(s->video_cap.type & VID_TYPE_CAPTURE)) {
 
102
        fprintf(stderr, "Fatal: grab device does not handle capture\n");
 
103
        goto fail;
 
104
    }
 
105
 
 
106
    desired_palette = -1;
 
107
    if (st->codec.pix_fmt == PIX_FMT_YUV420P) {
 
108
        desired_palette = VIDEO_PALETTE_YUV420P;
 
109
    } else if (st->codec.pix_fmt == PIX_FMT_YUV422) {
 
110
        desired_palette = VIDEO_PALETTE_YUV422;
 
111
    } else if (st->codec.pix_fmt == PIX_FMT_BGR24) {
 
112
        desired_palette = VIDEO_PALETTE_RGB24;
 
113
    }    
 
114
 
 
115
    /* set tv standard */
 
116
    if (ap->standard && !ioctl(video_fd, VIDIOCGTUNER, &tuner)) {
 
117
        if (!strcasecmp(ap->standard, "pal"))
 
118
            tuner.mode = VIDEO_MODE_PAL;
 
119
        else if (!strcasecmp(ap->standard, "secam"))
 
120
            tuner.mode = VIDEO_MODE_SECAM;
 
121
        else
 
122
            tuner.mode = VIDEO_MODE_NTSC;
 
123
        ioctl(video_fd, VIDIOCSTUNER, &tuner);
 
124
    }
 
125
    
 
126
    /* unmute audio */
 
127
    audio.audio = 0;
 
128
    ioctl(video_fd, VIDIOCGAUDIO, &audio);
 
129
    memcpy(&s->audio_saved, &audio, sizeof(audio));
 
130
    audio.flags &= ~VIDEO_AUDIO_MUTE;
 
131
    ioctl(video_fd, VIDIOCSAUDIO, &audio);
 
132
 
 
133
    ret = ioctl(video_fd,VIDIOCGMBUF,&s->gb_buffers);
 
134
    if (ret < 0) {
 
135
        /* try to use read based access */
 
136
        struct video_window win;
 
137
        struct video_picture pict;
 
138
        int val;
 
139
 
 
140
        win.x = 0;
 
141
        win.y = 0;
 
142
        win.width = width;
 
143
        win.height = height;
 
144
        win.chromakey = -1;
 
145
        win.flags = 0;
 
146
 
 
147
        ioctl(video_fd, VIDIOCSWIN, &win);
 
148
 
 
149
        ioctl(video_fd, VIDIOCGPICT, &pict);
 
150
#if 0
 
151
        printf("v4l: colour=%d hue=%d brightness=%d constrast=%d whiteness=%d\n",
 
152
               pict.colour,
 
153
               pict.hue,
 
154
               pict.brightness,
 
155
               pict.contrast,
 
156
               pict.whiteness);
 
157
#endif        
 
158
        /* try to choose a suitable video format */
 
159
        pict.palette = desired_palette;
 
160
        if (desired_palette == -1 || (ret = ioctl(video_fd, VIDIOCSPICT, &pict)) < 0) {
 
161
            pict.palette=VIDEO_PALETTE_YUV420P;
 
162
            ret = ioctl(video_fd, VIDIOCSPICT, &pict);
 
163
            if (ret < 0) {
 
164
                pict.palette=VIDEO_PALETTE_YUV422;
 
165
                ret = ioctl(video_fd, VIDIOCSPICT, &pict);
 
166
                if (ret < 0) {
 
167
                    pict.palette=VIDEO_PALETTE_RGB24;
 
168
                    ret = ioctl(video_fd, VIDIOCSPICT, &pict);
 
169
                    if (ret < 0) 
 
170
                        goto fail1;
 
171
                }
 
172
            }
 
173
        }
 
174
 
 
175
        s->frame_format = pict.palette;
 
176
 
 
177
        val = 1;
 
178
        ioctl(video_fd, VIDIOCCAPTURE, &val);
 
179
 
 
180
        s->time_frame = av_gettime();
 
181
        s->use_mmap = 0;
 
182
        
 
183
        /* ATI All In Wonder automatic activation */
 
184
        if (!strcmp(s->video_cap.name, "Km")) {
 
185
            if (aiw_init(s) < 0)
 
186
                goto fail;
 
187
            s->aiw_enabled = 1;
 
188
            /* force 420P format because convertion from YUV422 to YUV420P
 
189
               is done in this driver (ugly) */
 
190
            s->frame_format = VIDEO_PALETTE_YUV420P;
 
191
        }
 
192
    } else {
 
193
        s->video_buf = mmap(0,s->gb_buffers.size,PROT_READ|PROT_WRITE,MAP_SHARED,video_fd,0);
 
194
        if ((unsigned char*)-1 == s->video_buf) {
 
195
            perror("mmap");
 
196
            goto fail;
 
197
        }
 
198
        s->gb_frame = 0;
 
199
        s->time_frame = av_gettime();
 
200
        
 
201
        /* start to grab the first frame */
 
202
        s->gb_buf.frame = s->gb_frame % s->gb_buffers.frames;
 
203
        s->gb_buf.height = height;
 
204
        s->gb_buf.width = width;
 
205
        s->gb_buf.format = desired_palette;
 
206
 
 
207
        if (desired_palette == -1 || (ret = ioctl(video_fd, VIDIOCMCAPTURE, &s->gb_buf)) < 0) {
 
208
            s->gb_buf.format = VIDEO_PALETTE_YUV420P;
 
209
            
 
210
            ret = ioctl(video_fd, VIDIOCMCAPTURE, &s->gb_buf);
 
211
            if (ret < 0 && errno != EAGAIN) {
 
212
                /* try YUV422 */
 
213
                s->gb_buf.format = VIDEO_PALETTE_YUV422;
 
214
                
 
215
                ret = ioctl(video_fd, VIDIOCMCAPTURE, &s->gb_buf);
 
216
                if (ret < 0 && errno != EAGAIN) {
 
217
                    /* try RGB24 */
 
218
                    s->gb_buf.format = VIDEO_PALETTE_RGB24;
 
219
                    ret = ioctl(video_fd, VIDIOCMCAPTURE, &s->gb_buf);
 
220
                }
 
221
            }
 
222
        }
 
223
        if (ret < 0) {
 
224
            if (errno != EAGAIN) {
 
225
            fail1:
 
226
                fprintf(stderr, "Fatal: grab device does not support suitable format\n");
 
227
            } else {
 
228
                fprintf(stderr,"Fatal: grab device does not receive any video signal\n");
 
229
            }
 
230
            goto fail;
 
231
        }
 
232
        s->frame_format = s->gb_buf.format;
 
233
        s->use_mmap = 1;
 
234
    }
 
235
 
 
236
    switch(s->frame_format) {
 
237
    case VIDEO_PALETTE_YUV420P:
 
238
        frame_size = (width * height * 3) / 2;
 
239
        st->codec.pix_fmt = PIX_FMT_YUV420P;
 
240
        break;
 
241
    case VIDEO_PALETTE_YUV422:
 
242
        frame_size = width * height * 2;
 
243
        st->codec.pix_fmt = PIX_FMT_YUV422;
 
244
        break;
 
245
    case VIDEO_PALETTE_RGB24:
 
246
        frame_size = width * height * 3;
 
247
        st->codec.pix_fmt = PIX_FMT_BGR24; /* NOTE: v4l uses BGR24, not RGB24 ! */
 
248
        break;
 
249
    default:
 
250
        goto fail;
 
251
    }
 
252
    s->fd = video_fd;
 
253
    s->frame_size = frame_size;
 
254
    
 
255
    st->codec.codec_type = CODEC_TYPE_VIDEO;
 
256
    st->codec.codec_id = CODEC_ID_RAWVIDEO;
 
257
    st->codec.width = width;
 
258
    st->codec.height = height;
 
259
    st->codec.frame_rate      = frame_rate;
 
260
    st->codec.frame_rate_base = frame_rate_base;
 
261
    
 
262
    av_set_pts_info(s1, 48, 1, 1000000); /* 48 bits pts in us */
 
263
 
 
264
    return 0;
 
265
 fail:
 
266
    if (video_fd >= 0)
 
267
        close(video_fd);
 
268
    av_free(st);
 
269
    return -EIO;
 
270
}
 
271
 
 
272
static int v4l_mm_read_picture(VideoData *s, uint8_t *buf)
 
273
{
 
274
    uint8_t *ptr;
 
275
 
 
276
    /* Setup to capture the next frame */
 
277
    s->gb_buf.frame = (s->gb_frame + 1) % s->gb_buffers.frames;
 
278
    if (ioctl(s->fd, VIDIOCMCAPTURE, &s->gb_buf) < 0) {
 
279
        if (errno == EAGAIN)
 
280
            fprintf(stderr,"Cannot Sync\n");
 
281
        else
 
282
            perror("VIDIOCMCAPTURE");
 
283
        return -EIO;
 
284
    }
 
285
 
 
286
    while (ioctl(s->fd, VIDIOCSYNC, &s->gb_frame) < 0 &&
 
287
           (errno == EAGAIN || errno == EINTR));
 
288
 
 
289
    ptr = s->video_buf + s->gb_buffers.offsets[s->gb_frame];
 
290
    memcpy(buf, ptr, s->frame_size);
 
291
 
 
292
    /* This is now the grabbing frame */
 
293
    s->gb_frame = s->gb_buf.frame;
 
294
 
 
295
    return s->frame_size;
 
296
}
 
297
 
 
298
static int grab_read_packet(AVFormatContext *s1, AVPacket *pkt)
 
299
{
 
300
    VideoData *s = s1->priv_data;
 
301
    int64_t curtime, delay;
 
302
    struct timespec ts;
 
303
    int64_t per_frame = (int64_t_C(1000000) * s->frame_rate_base) / s->frame_rate;
 
304
 
 
305
    /* Calculate the time of the next frame */
 
306
    s->time_frame += per_frame;
 
307
 
 
308
    /* wait based on the frame rate */
 
309
    for(;;) {
 
310
        curtime = av_gettime();
 
311
        delay = s->time_frame - curtime;
 
312
        if (delay <= 0) {
 
313
            if (delay < -per_frame) {
 
314
                /* printf("grabbing is %d frames late (dropping)\n", (int) -(delay / 16666)); */
 
315
                s->time_frame += per_frame;
 
316
            }
 
317
            break;
 
318
        }    
 
319
        ts.tv_sec = delay / 1000000;
 
320
        ts.tv_nsec = (delay % 1000000) * 1000;
 
321
        nanosleep(&ts, NULL);
 
322
    }
 
323
 
 
324
    if (av_new_packet(pkt, s->frame_size) < 0)
 
325
        return -EIO;
 
326
 
 
327
    pkt->pts = curtime & ((1LL << 48) - 1);
 
328
 
 
329
    /* read one frame */
 
330
    if (s->aiw_enabled) {
 
331
        return aiw_read_picture(s, pkt->data);
 
332
    } else if (s->use_mmap) {
 
333
        return v4l_mm_read_picture(s, pkt->data);
 
334
    } else {
 
335
        if (read(s->fd, pkt->data, pkt->size) != pkt->size)
 
336
            return -EIO;
 
337
        return s->frame_size;
 
338
    }
 
339
}
 
340
 
 
341
static int grab_read_close(AVFormatContext *s1)
 
342
{
 
343
    VideoData *s = s1->priv_data;
 
344
 
 
345
    if (s->aiw_enabled)
 
346
        aiw_close(s);
 
347
 
 
348
    if (s->use_mmap)
 
349
        munmap(s->video_buf, s->gb_buffers.size);
 
350
 
 
351
    /* mute audio. we must force it because the BTTV driver does not
 
352
       return its state correctly */
 
353
    s->audio_saved.flags |= VIDEO_AUDIO_MUTE;
 
354
    ioctl(s->fd, VIDIOCSAUDIO, &s->audio_saved);
 
355
 
 
356
    close(s->fd);
 
357
    return 0;
 
358
}
 
359
 
 
360
static AVInputFormat video_grab_device_format = {
 
361
    "video4linux",
 
362
    "video grab",
 
363
    sizeof(VideoData),
 
364
    NULL,
 
365
    grab_read_header,
 
366
    grab_read_packet,
 
367
    grab_read_close,
 
368
    .flags = AVFMT_NOFILE,
 
369
};
 
370
 
 
371
/* All in Wonder specific stuff */
 
372
/* XXX: remove and merge in libavcodec/imgconvert.c */
 
373
 
 
374
static int aiw_init(VideoData *s)
 
375
{
 
376
    int width, height;
 
377
 
 
378
    width = s->width;
 
379
    height = s->height;
 
380
 
 
381
    if ((width == s->video_cap.maxwidth && height == s->video_cap.maxheight) ||
 
382
        (width == s->video_cap.maxwidth && height == s->video_cap.maxheight*2) ||
 
383
        (width == s->video_cap.maxwidth/2 && height == s->video_cap.maxheight)) {
 
384
        
 
385
        s->deint=0;
 
386
        s->halfw=0;
 
387
        if (height == s->video_cap.maxheight*2) s->deint=1;
 
388
        if (width == s->video_cap.maxwidth/2) s->halfw=1;
 
389
    } else {
 
390
        fprintf(stderr,"\nIncorrect Grab Size Supplied - Supported Sizes Are:\n");
 
391
        fprintf(stderr," %dx%d  %dx%d %dx%d\n\n",
 
392
                s->video_cap.maxwidth,s->video_cap.maxheight,
 
393
                s->video_cap.maxwidth,s->video_cap.maxheight*2,
 
394
                s->video_cap.maxwidth/2,s->video_cap.maxheight);
 
395
        goto fail;
 
396
    }
 
397
 
 
398
    if (s->halfw == 0) {
 
399
        s->src_mem = av_malloc(s->width*2);
 
400
    } else {
 
401
        s->src_mem = av_malloc(s->width*4);
 
402
    }
 
403
    if (!s->src_mem) goto fail;
 
404
 
 
405
    s->lum_m4_mem = av_malloc(s->width);
 
406
    if (!s->lum_m4_mem)
 
407
        goto fail;
 
408
    return 0;
 
409
 fail:
 
410
    av_freep(&s->src_mem);
 
411
    av_freep(&s->lum_m4_mem);
 
412
    return -1;
 
413
}
 
414
 
 
415
#ifdef HAVE_MMX
 
416
#include "../libavcodec/i386/mmx.h"
 
417
 
 
418
#define LINE_WITH_UV \
 
419
                    movq_m2r(ptr[0],mm0); \
 
420
                    movq_m2r(ptr[8],mm1);  \
 
421
                    movq_r2r(mm0, mm4); \
 
422
                    punpcklbw_r2r(mm1,mm0); \
 
423
                    punpckhbw_r2r(mm1,mm4); \
 
424
                    movq_r2r(mm0,mm5); \
 
425
                    punpcklbw_r2r(mm4,mm0); \
 
426
                    punpckhbw_r2r(mm4,mm5); \
 
427
                    movq_r2r(mm0,mm1); \
 
428
                    punpcklbw_r2r(mm5,mm1); \
 
429
                    movq_r2m(mm1,lum[0]); \
 
430
                    movq_m2r(ptr[16],mm2); \
 
431
                    movq_m2r(ptr[24],mm1); \
 
432
                    movq_r2r(mm2,mm4); \
 
433
                    punpcklbw_r2r(mm1,mm2); \
 
434
                    punpckhbw_r2r(mm1,mm4); \
 
435
                    movq_r2r(mm2,mm3); \
 
436
                    punpcklbw_r2r(mm4,mm2); \
 
437
                    punpckhbw_r2r(mm4,mm3); \
 
438
                    movq_r2r(mm2,mm1); \
 
439
                    punpcklbw_r2r(mm3,mm1); \
 
440
                    movq_r2m(mm1,lum[8]); \
 
441
                    punpckhdq_r2r(mm2,mm0); \
 
442
                    punpckhdq_r2r(mm3,mm5); \
 
443
                    movq_r2m(mm0,cb[0]); \
 
444
                    movq_r2m(mm5,cr[0]);
 
445
 
 
446
#define LINE_NO_UV \
 
447
                    movq_m2r(ptr[0],mm0);\
 
448
                    movq_m2r(ptr[8],mm1);\
 
449
                    movq_r2r(mm0, mm4);\
 
450
                    punpcklbw_r2r(mm1,mm0); \
 
451
                    punpckhbw_r2r(mm1,mm4);\
 
452
                    movq_r2r(mm0,mm5);\
 
453
                    punpcklbw_r2r(mm4,mm0);\
 
454
                    punpckhbw_r2r(mm4,mm5);\
 
455
                    movq_r2r(mm0,mm1);\
 
456
                    punpcklbw_r2r(mm5,mm1);\
 
457
                    movq_r2m(mm1,lum[0]);\
 
458
                    movq_m2r(ptr[16],mm2);\
 
459
                    movq_m2r(ptr[24],mm1);\
 
460
                    movq_r2r(mm2,mm4);\
 
461
                    punpcklbw_r2r(mm1,mm2);\
 
462
                    punpckhbw_r2r(mm1,mm4);\
 
463
                    movq_r2r(mm2,mm3);\
 
464
                    punpcklbw_r2r(mm4,mm2);\
 
465
                    punpckhbw_r2r(mm4,mm3);\
 
466
                    movq_r2r(mm2,mm1);\
 
467
                    punpcklbw_r2r(mm3,mm1);\
 
468
                    movq_r2m(mm1,lum[8]);
 
469
 
 
470
#define LINE_WITHUV_AVG \
 
471
                    movq_m2r(ptr[0], mm0);\
 
472
                    movq_m2r(ptr[8], mm1);\
 
473
                    movq_r2r(mm0, mm4);\
 
474
                    punpcklbw_r2r(mm1,mm0);\
 
475
                    punpckhbw_r2r(mm1,mm4);\
 
476
                    movq_r2r(mm0,mm5);\
 
477
                    punpcklbw_r2r(mm4,mm0);\
 
478
                    punpckhbw_r2r(mm4,mm5);\
 
479
                    movq_r2r(mm0,mm1);\
 
480
                    movq_r2r(mm5,mm2);\
 
481
                    punpcklbw_r2r(mm7,mm1);\
 
482
                    punpcklbw_r2r(mm7,mm2);\
 
483
                    paddw_r2r(mm6,mm1);\
 
484
                    paddw_r2r(mm2,mm1);\
 
485
                    psraw_i2r(1,mm1);\
 
486
                    packuswb_r2r(mm7,mm1);\
 
487
                    movd_r2m(mm1,lum[0]);\
 
488
                    movq_m2r(ptr[16],mm2);\
 
489
                    movq_m2r(ptr[24],mm1);\
 
490
                    movq_r2r(mm2,mm4);\
 
491
                    punpcklbw_r2r(mm1,mm2);\
 
492
                    punpckhbw_r2r(mm1,mm4);\
 
493
                    movq_r2r(mm2,mm3);\
 
494
                    punpcklbw_r2r(mm4,mm2);\
 
495
                    punpckhbw_r2r(mm4,mm3);\
 
496
                    movq_r2r(mm2,mm1);\
 
497
                    movq_r2r(mm3,mm4);\
 
498
                    punpcklbw_r2r(mm7,mm1);\
 
499
                    punpcklbw_r2r(mm7,mm4);\
 
500
                    paddw_r2r(mm6,mm1);\
 
501
                    paddw_r2r(mm4,mm1);\
 
502
                    psraw_i2r(1,mm1);\
 
503
                    packuswb_r2r(mm7,mm1);\
 
504
                    movd_r2m(mm1,lum[4]);\
 
505
                    punpckhbw_r2r(mm7,mm0);\
 
506
                    punpckhbw_r2r(mm7,mm2);\
 
507
                    paddw_r2r(mm6,mm0);\
 
508
                    paddw_r2r(mm2,mm0);\
 
509
                    psraw_i2r(1,mm0);\
 
510
                    packuswb_r2r(mm7,mm0);\
 
511
                    punpckhbw_r2r(mm7,mm5);\
 
512
                    punpckhbw_r2r(mm7,mm3);\
 
513
                    paddw_r2r(mm6,mm5);\
 
514
                    paddw_r2r(mm3,mm5);\
 
515
                    psraw_i2r(1,mm5);\
 
516
                    packuswb_r2r(mm7,mm5);\
 
517
                    movd_r2m(mm0,cb[0]);\
 
518
                    movd_r2m(mm5,cr[0]);
 
519
 
 
520
#define LINE_NOUV_AVG \
 
521
                    movq_m2r(ptr[0],mm0);\
 
522
                    movq_m2r(ptr[8],mm1);\
 
523
                    pand_r2r(mm5,mm0);\
 
524
                    pand_r2r(mm5,mm1);\
 
525
                    pmaddwd_r2r(mm6,mm0);\
 
526
                    pmaddwd_r2r(mm6,mm1);\
 
527
                    packssdw_r2r(mm1,mm0);\
 
528
                    paddw_r2r(mm6,mm0);\
 
529
                    psraw_i2r(1,mm0);\
 
530
                    movq_m2r(ptr[16],mm2);\
 
531
                    movq_m2r(ptr[24],mm3);\
 
532
                    pand_r2r(mm5,mm2);\
 
533
                    pand_r2r(mm5,mm3);\
 
534
                    pmaddwd_r2r(mm6,mm2);\
 
535
                    pmaddwd_r2r(mm6,mm3);\
 
536
                    packssdw_r2r(mm3,mm2);\
 
537
                    paddw_r2r(mm6,mm2);\
 
538
                    psraw_i2r(1,mm2);\
 
539
                    packuswb_r2r(mm2,mm0);\
 
540
                    movq_r2m(mm0,lum[0]);
 
541
 
 
542
#define DEINT_LINE_LUM(ptroff) \
 
543
                    movd_m2r(lum_m4[(ptroff)],mm0);\
 
544
                    movd_m2r(lum_m3[(ptroff)],mm1);\
 
545
                    movd_m2r(lum_m2[(ptroff)],mm2);\
 
546
                    movd_m2r(lum_m1[(ptroff)],mm3);\
 
547
                    movd_m2r(lum[(ptroff)],mm4);\
 
548
                    punpcklbw_r2r(mm7,mm0);\
 
549
                    movd_r2m(mm2,lum_m4[(ptroff)]);\
 
550
                    punpcklbw_r2r(mm7,mm1);\
 
551
                    punpcklbw_r2r(mm7,mm2);\
 
552
                    punpcklbw_r2r(mm7,mm3);\
 
553
                    punpcklbw_r2r(mm7,mm4);\
 
554
                    psllw_i2r(2,mm1);\
 
555
                    psllw_i2r(1,mm2);\
 
556
                    paddw_r2r(mm6,mm1);\
 
557
                    psllw_i2r(2,mm3);\
 
558
                    paddw_r2r(mm2,mm1);\
 
559
                    paddw_r2r(mm4,mm0);\
 
560
                    paddw_r2r(mm3,mm1);\
 
561
                    psubusw_r2r(mm0,mm1);\
 
562
                    psrlw_i2r(3,mm1);\
 
563
                    packuswb_r2r(mm7,mm1);\
 
564
                    movd_r2m(mm1,lum_m2[(ptroff)]);
 
565
 
 
566
#else
 
567
#include "../libavcodec/dsputil.h"
 
568
 
 
569
#define LINE_WITH_UV \
 
570
                    lum[0]=ptr[0];lum[1]=ptr[2];lum[2]=ptr[4];lum[3]=ptr[6];\
 
571
                    cb[0]=ptr[1];cb[1]=ptr[5];\
 
572
                    cr[0]=ptr[3];cr[1]=ptr[7];\
 
573
                    lum[4]=ptr[8];lum[5]=ptr[10];lum[6]=ptr[12];lum[7]=ptr[14];\
 
574
                    cb[2]=ptr[9];cb[3]=ptr[13];\
 
575
                    cr[2]=ptr[11];cr[3]=ptr[15];\
 
576
                    lum[8]=ptr[16];lum[9]=ptr[18];lum[10]=ptr[20];lum[11]=ptr[22];\
 
577
                    cb[4]=ptr[17];cb[5]=ptr[21];\
 
578
                    cr[4]=ptr[19];cr[5]=ptr[23];\
 
579
                    lum[12]=ptr[24];lum[13]=ptr[26];lum[14]=ptr[28];lum[15]=ptr[30];\
 
580
                    cb[6]=ptr[25];cb[7]=ptr[29];\
 
581
                    cr[6]=ptr[27];cr[7]=ptr[31];
 
582
 
 
583
#define LINE_NO_UV \
 
584
                    lum[0]=ptr[0];lum[1]=ptr[2];lum[2]=ptr[4];lum[3]=ptr[6];\
 
585
                    lum[4]=ptr[8];lum[5]=ptr[10];lum[6]=ptr[12];lum[7]=ptr[14];\
 
586
                    lum[8]=ptr[16];lum[9]=ptr[18];lum[10]=ptr[20];lum[11]=ptr[22];\
 
587
                    lum[12]=ptr[24];lum[13]=ptr[26];lum[14]=ptr[28];lum[15]=ptr[30];
 
588
 
 
589
#define LINE_WITHUV_AVG \
 
590
                    sum=(ptr[0]+ptr[2]+1) >> 1;lum[0]=sum; \
 
591
                    sum=(ptr[4]+ptr[6]+1) >> 1;lum[1]=sum; \
 
592
                    sum=(ptr[1]+ptr[5]+1) >> 1;cb[0]=sum; \
 
593
                    sum=(ptr[3]+ptr[7]+1) >> 1;cr[0]=sum; \
 
594
                    sum=(ptr[8]+ptr[10]+1) >> 1;lum[2]=sum; \
 
595
                    sum=(ptr[12]+ptr[14]+1) >> 1;lum[3]=sum; \
 
596
                    sum=(ptr[9]+ptr[13]+1) >> 1;cb[1]=sum; \
 
597
                    sum=(ptr[11]+ptr[15]+1) >> 1;cr[1]=sum; \
 
598
                    sum=(ptr[16]+ptr[18]+1) >> 1;lum[4]=sum; \
 
599
                    sum=(ptr[20]+ptr[22]+1) >> 1;lum[5]=sum; \
 
600
                    sum=(ptr[17]+ptr[21]+1) >> 1;cb[2]=sum; \
 
601
                    sum=(ptr[19]+ptr[23]+1) >> 1;cr[2]=sum; \
 
602
                    sum=(ptr[24]+ptr[26]+1) >> 1;lum[6]=sum; \
 
603
                    sum=(ptr[28]+ptr[30]+1) >> 1;lum[7]=sum; \
 
604
                    sum=(ptr[25]+ptr[29]+1) >> 1;cb[3]=sum; \
 
605
                    sum=(ptr[27]+ptr[31]+1) >> 1;cr[3]=sum; 
 
606
 
 
607
#define LINE_NOUV_AVG \
 
608
                    sum=(ptr[0]+ptr[2]+1) >> 1;lum[0]=sum; \
 
609
                    sum=(ptr[4]+ptr[6]+1) >> 1;lum[1]=sum; \
 
610
                    sum=(ptr[8]+ptr[10]+1) >> 1;lum[2]=sum; \
 
611
                    sum=(ptr[12]+ptr[14]+1) >> 1;lum[3]=sum; \
 
612
                    sum=(ptr[16]+ptr[18]+1) >> 1;lum[4]=sum; \
 
613
                    sum=(ptr[20]+ptr[22]+1) >> 1;lum[5]=sum; \
 
614
                    sum=(ptr[24]+ptr[26]+1) >> 1;lum[6]=sum; \
 
615
                    sum=(ptr[28]+ptr[30]+1) >> 1;lum[7]=sum; 
 
616
 
 
617
#define DEINT_LINE_LUM(ptroff) \
 
618
                    sum=(-lum_m4[(ptroff)]+(lum_m3[(ptroff)]<<2)+(lum_m2[(ptroff)]<<1)+(lum_m1[(ptroff)]<<2)-lum[(ptroff)]); \
 
619
                    lum_m4[(ptroff)]=lum_m2[(ptroff)];\
 
620
                    lum_m2[(ptroff)]=cm[(sum+4)>>3];\
 
621
                    sum=(-lum_m4[(ptroff)+1]+(lum_m3[(ptroff)+1]<<2)+(lum_m2[(ptroff)+1]<<1)+(lum_m1[(ptroff)+1]<<2)-lum[(ptroff)+1]); \
 
622
                    lum_m4[(ptroff)+1]=lum_m2[(ptroff)+1];\
 
623
                    lum_m2[(ptroff)+1]=cm[(sum+4)>>3];\
 
624
                    sum=(-lum_m4[(ptroff)+2]+(lum_m3[(ptroff)+2]<<2)+(lum_m2[(ptroff)+2]<<1)+(lum_m1[(ptroff)+2]<<2)-lum[(ptroff)+2]); \
 
625
                    lum_m4[(ptroff)+2]=lum_m2[(ptroff)+2];\
 
626
                    lum_m2[(ptroff)+2]=cm[(sum+4)>>3];\
 
627
                    sum=(-lum_m4[(ptroff)+3]+(lum_m3[(ptroff)+3]<<2)+(lum_m2[(ptroff)+3]<<1)+(lum_m1[(ptroff)+3]<<2)-lum[(ptroff)+3]); \
 
628
                    lum_m4[(ptroff)+3]=lum_m2[(ptroff)+3];\
 
629
                    lum_m2[(ptroff)+3]=cm[(sum+4)>>3];
 
630
 
 
631
#endif
 
632
 
 
633
 
 
634
/* Read two fields separately. */
 
635
static int aiw_read_picture(VideoData *s, uint8_t *data)
 
636
{
 
637
    uint8_t *ptr, *lum, *cb, *cr;
 
638
    int h;
 
639
#ifndef HAVE_MMX
 
640
    int sum;
 
641
#endif
 
642
    uint8_t* src = s->src_mem;
 
643
    uint8_t *ptrend = &src[s->width*2];
 
644
    lum=data;
 
645
    cb=&lum[s->width*s->height];
 
646
    cr=&cb[(s->width*s->height)/4];
 
647
    if (s->deint == 0 && s->halfw == 0) {
 
648
        while (read(s->fd,src,s->width*2) < 0) {
 
649
            usleep(100);
 
650
        }
 
651
        for (h = 0; h < s->height-2; h+=2) {
 
652
            for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, cb+=8, cr+=8) {
 
653
                LINE_WITH_UV
 
654
                    }
 
655
            read(s->fd,src,s->width*2);
 
656
            for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16) {
 
657
                LINE_NO_UV
 
658
                    }
 
659
            read(s->fd,src,s->width*2);
 
660
        }
 
661
        /*
 
662
         * Do last two lines
 
663
         */
 
664
        for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, cb+=8, cr+=8) {
 
665
            LINE_WITH_UV
 
666
                }
 
667
        read(s->fd,src,s->width*2);
 
668
        for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16) {
 
669
            LINE_NO_UV
 
670
                }
 
671
        /* drop second field */
 
672
        while (read(s->fd,src,s->width*2) < 0) {
 
673
            usleep(100);
 
674
        }
 
675
        for (h = 0; h < s->height - 1; h++) {
 
676
            read(s->fd,src,s->width*2);
 
677
        }
 
678
    } else if (s->halfw == 1) {
 
679
#ifdef HAVE_MMX
 
680
        mmx_t rounder;
 
681
        mmx_t masker;
 
682
        rounder.uw[0]=1;
 
683
        rounder.uw[1]=1;
 
684
        rounder.uw[2]=1;
 
685
        rounder.uw[3]=1;
 
686
        masker.ub[0]=0xff;
 
687
        masker.ub[1]=0;
 
688
        masker.ub[2]=0xff;
 
689
        masker.ub[3]=0;
 
690
        masker.ub[4]=0xff;
 
691
        masker.ub[5]=0;
 
692
        masker.ub[6]=0xff;
 
693
        masker.ub[7]=0;
 
694
        pxor_r2r(mm7,mm7);
 
695
        movq_m2r(rounder,mm6);
 
696
#endif
 
697
        while (read(s->fd,src,s->width*4) < 0) {
 
698
            usleep(100);
 
699
        }
 
700
        ptrend = &src[s->width*4];
 
701
        for (h = 0; h < s->height-2; h+=2) {
 
702
            for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=8, cb+=4, cr+=4) {
 
703
                LINE_WITHUV_AVG
 
704
                    }
 
705
            read(s->fd,src,s->width*4);
 
706
#ifdef HAVE_MMX
 
707
            movq_m2r(masker,mm5);
 
708
#endif
 
709
            for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=8) {
 
710
                LINE_NOUV_AVG
 
711
                    }
 
712
            read(s->fd,src,s->width*4);
 
713
        }
 
714
        /*
 
715
 * Do last two lines
 
716
 */
 
717
        for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=8, cb+=4, cr+=4) {
 
718
            LINE_WITHUV_AVG
 
719
                }
 
720
        read(s->fd,src,s->width*4);
 
721
#ifdef HAVE_MMX
 
722
        movq_m2r(masker,mm5);
 
723
#endif
 
724
        for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=8) {
 
725
            LINE_NOUV_AVG
 
726
                }
 
727
        /* drop second field */
 
728
        while (read(s->fd,src,s->width*4) < 0) {
 
729
            usleep(100);
 
730
        }
 
731
        for (h = 0; h < s->height - 1; h++) {
 
732
            read(s->fd,src,s->width*4);
 
733
        }
 
734
    } else {
 
735
        uint8_t *lum_m1, *lum_m2, *lum_m3, *lum_m4;
 
736
#ifdef HAVE_MMX
 
737
        mmx_t rounder;
 
738
        rounder.uw[0]=4;
 
739
        rounder.uw[1]=4;
 
740
        rounder.uw[2]=4;
 
741
        rounder.uw[3]=4;
 
742
        movq_m2r(rounder,mm6);
 
743
        pxor_r2r(mm7,mm7);
 
744
#else
 
745
        uint8_t *cm = cropTbl + MAX_NEG_CROP;
 
746
#endif
 
747
 
 
748
        /* read two fields and deinterlace them */
 
749
        while (read(s->fd,src,s->width*2) < 0) {
 
750
            usleep(100);
 
751
        }
 
752
        for (h = 0; h < (s->height/2)-2; h+=2) {
 
753
            for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, cb+=8, cr+=8) {
 
754
                LINE_WITH_UV
 
755
                    }
 
756
            read(s->fd,src,s->width*2);
 
757
            /* skip a luminance line - will be filled in later */
 
758
            lum += s->width;
 
759
            for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, cb+=8, cr+=8) {
 
760
                LINE_WITH_UV
 
761
                    }
 
762
            /* skip a luminance line - will be filled in later */
 
763
            lum += s->width;
 
764
            read(s->fd,src,s->width*2);
 
765
        }
 
766
        /*
 
767
 * Do last two lines
 
768
 */
 
769
        for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, cb+=8, cr+=8) {
 
770
            LINE_WITH_UV
 
771
                }
 
772
        /* skip a luminance line - will be filled in later */
 
773
        lum += s->width;
 
774
        read(s->fd,src,s->width*2);
 
775
        for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, cb+=8, cr+=8) {
 
776
            LINE_WITH_UV
 
777
                }
 
778
        /*
 
779
 *
 
780
 * SECOND FIELD
 
781
 *
 
782
 */
 
783
        lum=&data[s->width];
 
784
        while (read(s->fd,src,s->width*2) < 0) {
 
785
            usleep(10);
 
786
        }
 
787
        /* First (and last) two lines not interlaced */
 
788
        for (h = 0; h < 2; h++) {
 
789
            for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16) {
 
790
                LINE_NO_UV
 
791
                    }
 
792
            read(s->fd,src,s->width*2);
 
793
            /* skip a luminance line */
 
794
            lum += s->width;
 
795
        }
 
796
        lum_m1=&lum[-s->width];
 
797
        lum_m2=&lum_m1[-s->width];
 
798
        lum_m3=&lum_m2[-s->width];
 
799
        memmove(s->lum_m4_mem,&lum_m3[-s->width],s->width);
 
800
        for (; h < (s->height/2)-1; h++) {
 
801
            lum_m4=s->lum_m4_mem;
 
802
            for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16,lum_m1+=16,lum_m2+=16,lum_m3+=16,lum_m4+=16) {
 
803
                LINE_NO_UV
 
804
 
 
805
                    DEINT_LINE_LUM(0)
 
806
                    DEINT_LINE_LUM(4)
 
807
                    DEINT_LINE_LUM(8)
 
808
                    DEINT_LINE_LUM(12)
 
809
                    }
 
810
            read(s->fd,src,s->width*2);
 
811
            /* skip a luminance line */
 
812
            lum += s->width;
 
813
            lum_m1 += s->width;
 
814
            lum_m2 += s->width;
 
815
            lum_m3 += s->width;
 
816
            //                lum_m4 += s->width;
 
817
        }
 
818
        /*
 
819
 * Do last line
 
820
 */
 
821
        lum_m4=s->lum_m4_mem;
 
822
        for (ptr = &src[0]; ptr < ptrend; ptr+=32, lum+=16, lum_m1+=16, lum_m2+=16, lum_m3+=16, lum_m4+=16) {
 
823
            LINE_NO_UV
 
824
 
 
825
                DEINT_LINE_LUM(0)
 
826
                DEINT_LINE_LUM(4)
 
827
                DEINT_LINE_LUM(8)
 
828
                DEINT_LINE_LUM(12)
 
829
                }
 
830
    }
 
831
#ifdef HAVE_MMX
 
832
    emms();
 
833
#endif
 
834
    return s->frame_size;
 
835
}
 
836
 
 
837
static int aiw_close(VideoData *s)
 
838
{
 
839
    av_freep(&s->lum_m4_mem);
 
840
    av_freep(&s->src_mem);
 
841
    return 0;
 
842
}
 
843
 
 
844
int video_grab_init(void)
 
845
{
 
846
    av_register_input_format(&video_grab_device_format);
 
847
    return 0;
 
848
}