Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /* gcc 2.95.x doesn't compile some c99 constructs ... */
  2 #if __GNUC__ >= 3
  3 
  4 #include "config.h"
  5 
  6 #include <stdlib.h>
  7 #include <stdio.h>
  8 #include <string.h>
  9 #include <pthread.h>
 10 #include <fcntl.h>
 11 #include <errno.h>
 12 #include <unistd.h>
 13 #include <inttypes.h>
 14 #include <sys/mman.h>
 15 
 16 #include <libdv/dv.h>
 17 
 18 #include "grab-ng.h"
 19 
 20 /* ----------------------------------------------------------------------- */
 21 
 22 struct dv_handle {
 23     /* handles */
 24     int fd;
 25     dv_decoder_t  *dec;
 26 
 27     /* mmap()ed data */
 28     unsigned char  *map_start;
 29     unsigned char  *map_ptr;
 30     off_t          map_size;
 31     int            map_frame;
 32 
 33     /* format */
 34     struct ng_video_fmt vfmt;
 35     struct ng_audio_fmt afmt;
 36 
 37     /* misc video */
 38     int rate,vframe,frames;
 39 
 40     /* misc audio */
 41     int aframe,samples;
 42     int16_t *audiobuf[4];
 43 };
 44 
 45 /* ----------------------------------------------------------------------- */
 46 
 47 static enum color_space_e fmtid_to_colorspace[VIDEO_FMT_COUNT] = {
 48     [ 0 ... VIDEO_FMT_COUNT-1 ] = UNSET,
 49     [ VIDEO_YUYV   ] = e_dv_color_yuv,
 50     [ VIDEO_RGB24  ] = e_dv_color_rgb,
 51     [ VIDEO_BGR32  ] = e_dv_color_bgr0,
 52 };
 53 
 54 /* ----------------------------------------------------------------------- */
 55 
 56 static void dv_unmap(struct dv_handle *h)
 57 {
 58     if (!h->map_ptr)
 59         return;
 60     munmap(h->map_start,h->map_size);
 61     h->map_ptr = NULL;
 62 }
 63 
 64 static void dv_map(struct dv_handle *h, int frame)
 65 {
 66     off_t map_offset;
 67     off_t pgsize, size, offset;
 68 
 69     size = h->dec->frame_size;
 70     if (0 == size)
 71         size = 120000; /* NTSC frame size */
 72     offset = frame * size;
 73 
 74     pgsize = getpagesize();
 75     map_offset   = offset & ~(pgsize-1);
 76     h->map_size  = offset - map_offset + size;
 77     h->map_start = mmap(0, h->map_size, PROT_READ, MAP_SHARED,
 78                         h->fd, map_offset);
 79     if (MAP_FAILED == h->map_start) {
 80         perror("mmap");
 81         exit(1);
 82     }
 83     h->map_ptr = h->map_start + (offset - map_offset);
 84 }
 85 
 86 static void dv_fmt(struct dv_handle *h, int *vfmt, int vn)
 87 {
 88     off_t len;
 89     int i;
 90 
 91     /* video format */
 92     for (i = 0; i < vn; i++) {
 93         if (ng_debug)
 94             fprintf(stderr,"dv: trying: %d [%s]\n",
 95                     vfmt[i],ng_vfmt_to_desc[vfmt[i]]);
 96         if (UNSET == fmtid_to_colorspace[vfmt[i]])
 97             continue;
 98         h->vfmt.fmtid = vfmt[i];
 99         break;
100     }
101     h->vfmt.width        = h->dec->width;
102     h->vfmt.height       = h->dec->height;
103     h->vfmt.bytesperline = (h->vfmt.width*ng_vfmt_to_depth[h->vfmt.fmtid]) >> 3;
104     h->rate              = (e_dv_system_625_50 == h->dec->system) ? 25 : 30;
105 
106     /* audio fmt */
107     if (1 == h->dec->audio->num_channels ||
108         2 == h->dec->audio->num_channels) {
109         h->afmt.fmtid = (16 == h->dec->audio->quantization) ?
110             AUDIO_S16_NATIVE_MONO : AUDIO_U8_MONO;
111         if (2 == h->dec->audio->num_channels)
112             h->afmt.fmtid++;
113     }
114     h->afmt.rate = h->dec->audio->frequency;
115     
116     /* movie length (# of frames) */
117     len = lseek(h->fd,0,SEEK_END);
118     h->frames = len / h->dec->frame_size;
119     
120     if (ng_debug) {
121         fprintf(stderr,"dv: len=%lld => %d frames [%" PRId64 "]\n",len,h->frames,
122                 len - (off_t)h->frames * h->dec->frame_size);
123         fprintf(stderr,
124                 "dv: quality=%d system=%d std=%d sampling=%d num_dif_seqs=%d\n"
125                 "dv: height=%d width=%d frame_size=%ld\n",
126                 h->dec->quality, h->dec->system, h->dec->std,
127                 h->dec->sampling, h->dec->num_dif_seqs, h->dec->height,
128                 h->dec->width, h->dec->frame_size);
129         fprintf(stderr, "dv: audio: %d Hz, %d bits, %d channels,"
130                 " emphasis %s\n",
131                 h->dec->audio->frequency,
132                 h->dec->audio->quantization,
133                 h->dec->audio->num_channels,
134                 (h->dec->audio->emphasis ? "on" : "off"));
135     }
136 }
137 
138 /* ----------------------------------------------------------------------- */
139 
140 static void* dv_open(char *moviename)
141 {
142     struct dv_handle *h;
143     
144     if (NULL == (h = malloc(sizeof(*h))))
145         goto oops;
146     memset(h,0,sizeof(*h));
147     h->map_frame = -1;
148 
149     if (-1 == (h->fd = open(moviename,O_RDONLY))) {
150         fprintf(stderr,"dv: open %s: %s\n",moviename,strerror(errno));
151         goto oops;
152     }
153     if (NULL == (h->dec = dv_decoder_new(0,0,0))) {
154         fprintf(stderr,"dv: dv_decoder_new failed\n");
155         goto oops;
156     }
157     h->dec->quality = 3;
158 
159     dv_map(h, 0);
160     if (dv_parse_header(h->dec, h->map_ptr) < 0) {
161         fprintf(stderr,"dv: dv_parse_header failed\n");
162         goto oops;
163     }
164     dv_fmt(h,NULL,0);
165 
166     return h;
167 
168  oops:
169     if (h->dec)
170         dv_decoder_free(h->dec);
171     if (-1 != h->fd)
172         close(h->fd);
173     if (h)
174         free(h);
175     return NULL;
176 }
177 
178 static struct ng_video_fmt* dv_vfmt(void *handle, int *vfmt, int vn)
179 {
180     struct dv_handle *h = handle;
181 
182     dv_fmt(h,vfmt,vn);
183     return &h->vfmt;
184 }
185 
186 static struct ng_audio_fmt* dv_afmt(void *handle)
187 {
188     struct dv_handle *h = handle;
189 
190     return h->afmt.fmtid ? &h->afmt : NULL;
191 }
192 
193 static struct ng_video_buf* dv_vdata(void *handle, unsigned int drop)
194 {
195     struct dv_handle *h = handle;
196     struct ng_video_buf *buf;
197     unsigned char *pixels[3];
198     int pitches[3];
199 
200     h->vframe += drop;
201     if (h->vframe >= h->frames)
202         return NULL;
203     if (ng_debug > 1)
204         fprintf(stderr,"dv: frame %d [drop=%d]\n",h->vframe,drop);
205 
206     dv_unmap(h); dv_map(h, h->vframe);
207     if (dv_parse_header(h->dec, h->map_ptr) < 0) {
208         fprintf(stderr,"dv: dv_parse_header failed\n");
209         return NULL;
210     }
211 
212     buf = ng_malloc_video_buf(&h->vfmt,h->vfmt.bytesperline*h->vfmt.height);
213     switch (h->vfmt.fmtid) {
214     case VIDEO_YUYV:
215         pixels[0]  = buf->data;
216         pitches[0] = buf->fmt.width*2;
217         break;
218     case VIDEO_RGB24:
219         pixels[0]  = buf->data;
220         pitches[0] = buf->fmt.width*3;
221         break;
222     case VIDEO_BGR32:
223         pixels[0]  = buf->data;
224         pitches[0] = buf->fmt.width*4;
225         break;
226     default:
227         BUG_ON(1,"unknown fmtid");
228     }
229 
230     dv_parse_packs(h->dec, h->map_ptr);
231     dv_decode_full_frame(h->dec, h->map_ptr,
232                          fmtid_to_colorspace[h->vfmt.fmtid], 
233                          pixels, pitches);
234     buf->info.seq  = h->vframe;
235     buf->info.ts   = (long long) buf->info.seq * 1000000000 / h->rate;
236     h->vframe++;
237     return buf;
238 }
239 
240 static struct ng_audio_buf* dv_adata(void *handle)
241 {
242     struct dv_handle *h = handle;
243     struct ng_audio_buf *buf;
244     int16_t *dest;
245     int asize, i;
246 
247     if (h->aframe >= h->frames)
248         return NULL;
249 
250     dv_unmap(h); dv_map(h, h->aframe);
251     if (dv_parse_header(h->dec, h->map_ptr) < 0) {
252         fprintf(stderr,"dv: dv_parse_header failed\n");
253         return NULL;
254     }
255 
256     asize = h->dec->audio->samples_this_frame *
257         h->dec->audio->num_channels *
258         h->dec->audio->quantization >> 3;
259     if (ng_debug > 1)
260         fprintf(stderr,"dv: audio %d [samples=%d]\n",h->aframe,
261                 h->dec->audio->samples_this_frame);
262 
263     buf  = ng_malloc_audio_buf(&h->afmt, asize);
264     dest = (int16_t*)buf->data;
265     if (2 == h->dec->audio->num_channels) {
266         if (NULL == h->audiobuf[0])
267             for (i = 0; i < 4; i++)
268                 h->audiobuf[i] = malloc(DV_AUDIO_MAX_SAMPLES*sizeof(int16_t));
269         dv_decode_full_audio(h->dec, h->map_ptr, h->audiobuf);
270         for (i = 0; i < h->dec->audio->samples_this_frame; i++) {
271             dest[2*i+0] = h->audiobuf[0][i];
272             dest[2*i+1] = h->audiobuf[1][i];
273         }
274     }
275     if (1 == h->dec->audio->num_channels)
276         dv_decode_full_audio(h->dec, h->map_ptr, &dest);
277     
278     buf->info.ts = (long long) h->samples * 1000000000 / h->afmt.rate;
279     h->samples += h->dec->audio->samples_this_frame;
280     h->aframe++;
281     return buf;
282 }
283 
284 static int64_t dv_frame_time(void *handle)
285 {
286     struct dv_handle *h = handle;
287 
288     return 1000000000 / h->rate;
289 }
290 
291 static int dv_close(void *handle)
292 {
293     struct dv_handle *h = handle;
294     int i;
295 
296     for (i = 0; i < 4; i++)
297         if (h->audiobuf[i])
298             free(h->audiobuf[i]);
299     dv_unmap(h);
300     dv_decoder_free(h->dec);
301     close(h->fd);
302     free(h);
303     return 0;
304 }
305 
306 /* ----------------------------------------------------------------------- */
307 
308 struct ng_reader dv_reader = {
309     name:       "dv",
310     desc:       "Digital Video",
311 
312     magic:      { "\x1f\x07\x00",  "\x3f\x07\x00" },
313     moff:       {  0,              0x50           },
314     mlen:       {  3,              3              },
315     
316     rd_open:    dv_open,
317     rd_vfmt:    dv_vfmt,
318     rd_afmt:    dv_afmt,
319     rd_vdata:   dv_vdata,
320     rd_adata:   dv_adata,
321     frame_time: dv_frame_time,
322     rd_close:   dv_close,
323 };
324 
325 extern void ng_plugin_init(void);
326 void ng_plugin_init(void)
327 {
328     ng_reader_register(NG_PLUGIN_MAGIC,__FILE__,&dv_reader);
329 }
330 
331 #else /* gcc3 */
332 extern void ng_plugin_init(void);
333 void ng_plugin_init(void) {}
334 #endif /* gcc3 */
335 
  This page was automatically generated by the LXR engine.