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 #include "config.h"
  2 
  3 #include <stdlib.h>
  4 #include <stdio.h>
  5 #include <string.h>
  6 #include <pthread.h>
  7 #include <quicktime/quicktime.h>
  8 #include <quicktime/colormodels.h>
  9 #include <quicktime/lqt.h>
 10 
 11 #include "grab-ng.h"
 12 
 13 /* ----------------------------------------------------------------------- */
 14 
 15 struct qt_video_priv {
 16     char  fcc[5];
 17     int   yuvsign;
 18     int   libencode;
 19     int   cmodel;
 20 };
 21 
 22 struct qt_audio_priv {
 23     char  fcc[5];
 24     int   libencode;
 25 };
 26 
 27 struct qt_handle {
 28     /* libquicktime handle */
 29     quicktime_t *fh;
 30 
 31     /* format */
 32     struct ng_video_fmt video;
 33     struct ng_audio_fmt audio;
 34 
 35     /* misc */
 36     int lib_video;
 37     int lib_audio;
 38     int yuvsign;
 39     int audio_sample;
 40     unsigned char **rows;
 41     unsigned char *data;
 42 };
 43 
 44 /* ----------------------------------------------------------------------- */
 45 
 46 static void*
 47 qt_open(char *filename, char *dummy,
 48         struct ng_video_fmt *video, const void *priv_video, int fps,
 49         struct ng_audio_fmt *audio, const void *priv_audio)
 50 {
 51     const struct qt_video_priv *pvideo = priv_video;
 52     const struct qt_audio_priv *paudio = priv_audio;
 53     struct qt_handle *h;
 54 
 55     if (NULL == (h = malloc(sizeof(*h))))
 56         return NULL;
 57 
 58     memset(h,0,sizeof(*h));
 59     h->video      = *video;
 60     h->audio      = *audio;
 61     if (h->video.fmtid != VIDEO_NONE) {
 62         h->lib_video  = pvideo->libencode;
 63         h->yuvsign    = pvideo->yuvsign;
 64     }
 65     if (h->audio.fmtid != AUDIO_NONE)
 66         h->lib_audio  = paudio->libencode;
 67 
 68     if (NULL == (h->fh = quicktime_open(filename,0,1))) {
 69         fprintf(stderr,"quicktime_open failed (%s)\n",filename);
 70         goto fail;
 71     }
 72     if (h->lib_video)
 73         if (NULL == (h->rows = malloc(h->video.height * sizeof(char*))))
 74             goto fail;
 75     if (h->yuvsign)
 76         if (NULL == (h->data = malloc(h->video.height * h->video.width * 2)))
 77             goto fail;
 78 
 79     if (h->audio.fmtid != AUDIO_NONE) {
 80         quicktime_set_audio(h->fh,
 81                             ng_afmt_to_channels[h->audio.fmtid],
 82                             h->audio.rate,
 83                             ng_afmt_to_bits[h->audio.fmtid],
 84                             (char*)paudio->fcc);
 85         h->audio_sample = ng_afmt_to_channels[h->audio.fmtid] *
 86             ng_afmt_to_bits[h->audio.fmtid] / 8;
 87         if (h->lib_audio) {
 88             if (!quicktime_supported_audio(h->fh, 0)) {
 89                 fprintf(stderr,"libquicktime: audio codec not supported\n");
 90                 goto fail;
 91             }
 92         }
 93     }
 94     if (h->video.fmtid != VIDEO_NONE) {
 95         quicktime_set_video(h->fh,1,h->video.width,h->video.height,
 96                             (float)fps/1000,(char*)pvideo->fcc);
 97         if (h->lib_video) {
 98             quicktime_set_cmodel(h->fh,pvideo->cmodel);
 99             if (!quicktime_supported_video(h->fh, 0)) {
100                 fprintf(stderr,"libquicktime: video codec not supported\n");
101                 goto fail;
102             }
103         }
104     }
105     quicktime_set_info(h->fh, "Dumme Bemerkungen gibt's hier umsonst.");
106     return h;
107 
108  fail:
109     if (h->rows)
110         free(h->rows);
111     if (h->data)
112         free(h->data);
113     free(h);
114     return NULL;
115 }
116 
117 static int
118 qt_video(void *handle, struct ng_video_buf *buf)
119 {
120     struct qt_handle *h = handle;
121     unsigned int *src,*dest;
122     int rc,i,n;
123 
124     if (h->lib_video) {
125         unsigned int row,len;
126         char *line;
127 
128         /* QuickTime library expects an array of pointers to image rows (RGB) */
129         len = h->video.width * 3;
130         for (row = 0, line = buf->data; row < h->video.height; row++, line += len)
131             h->rows[row] = line;
132         rc = quicktime_encode_video(h->fh, h->rows, 0);
133 
134     } else if (h->yuvsign) {
135         dest = (unsigned int *)h->data;
136         src  = (unsigned int *)buf->data;
137         n    = buf->size / 4;
138         /* U V values are signed but Y R G B values are unsigned. */
139         for (i = 0; i < n; i++) {
140 #if BYTE_ORDER == BIG_ENDIAN
141             *(dest++) = *(src++) ^ 0x00800080;
142 #else
143             *(dest++) = *(src++) ^ 0x80008000;
144 #endif
145         }
146         rc = quicktime_write_frame(h->fh, h->data, buf->size, 0);
147 
148     } else {
149         rc = quicktime_write_frame(h->fh, buf->data, buf->size, 0);
150     }
151     return rc;
152 }
153 
154 static int
155 qt_audio(void *handle, struct ng_audio_buf *buf)
156 {
157     struct qt_handle *h = handle;
158     int16_t *ch[2];
159     
160     if (h->lib_audio) {
161         /* FIXME: works for one channel (mono) only */
162         ch[0] = (int16_t*)buf->data;
163         return quicktime_encode_audio(h->fh, ch, NULL,
164                                       buf->size / h->audio_sample);
165     } else {
166         return quicktime_write_audio(h->fh, buf->data,
167                                      buf->size / h->audio_sample, 0);
168     }
169 }
170 
171 static int
172 qt_close(void *handle)
173 {
174     struct qt_handle *h = handle;
175 
176     quicktime_close(h->fh);
177     if (h->rows)
178         free(h->rows);
179     if (h->data)
180         free(h->data);
181     free(h);
182     return 0;
183 }
184 
185 /* ----------------------------------------------------------------------- */
186 
187 static int cmodels[] = {
188     [BC_BGR888]  = VIDEO_BGR24,
189     [BC_RGB888]  = VIDEO_RGB24,
190     [BC_YUV422]  = VIDEO_YUYV,
191     [BC_YUV422P] = VIDEO_YUV422P,
192     [BC_YUV420P] = VIDEO_YUV420P,
193 };
194 
195 static struct qt_video_priv qt_raw = {
196     fcc:       QUICKTIME_RAW,
197     libencode: 0,
198 };
199 static struct qt_video_priv qt_yuv2 = {
200     fcc:       QUICKTIME_YUV2,
201     yuvsign:   1,
202     libencode: 0,
203 };
204 static struct qt_video_priv qt_yv12 = {
205     fcc:       QUICKTIME_YUV420,
206     libencode: 0,
207 };
208 static struct qt_video_priv qt_jpeg = {
209     fcc:       QUICKTIME_JPEG,
210     libencode: 0,
211 };
212 
213 static const struct ng_format_list qt_vformats[] = {
214     {
215         name:  "raw",
216         ext:   "mov",
217         fmtid: VIDEO_RGB24,
218         priv:  &qt_raw,
219     },{
220         name:  "yuv2",
221         ext:   "mov",
222         fmtid: VIDEO_YUYV,
223         priv:  &qt_yuv2,
224     },{
225         name:  "yv12",
226         ext:   "mov",
227         fmtid: VIDEO_YUV420P,
228         priv:  &qt_yv12,
229     },{
230         name:  "jpeg",
231         ext:   "mov",
232         fmtid: VIDEO_JPEG,
233         priv:  &qt_jpeg,
234     },{
235         /* EOF */
236     }
237 };
238 
239 static struct qt_audio_priv qt_mono8 = {
240     fcc:        QUICKTIME_RAW,
241     libencode:  0,
242 };
243 static struct qt_audio_priv qt_mono16 = {
244     fcc:        QUICKTIME_TWOS,
245     libencode:  0,
246 };
247 static struct qt_audio_priv qt_stereo = {
248     fcc:        QUICKTIME_TWOS,
249     libencode:  0,
250 };
251 static const struct ng_format_list qt_aformats[] = {
252     {
253         name:  "mono8",
254         ext:   "mov",
255         fmtid: AUDIO_U8_MONO,
256         priv:  &qt_mono8,
257     },{
258         name:  "mono16",
259         ext:   "mov",
260         fmtid: AUDIO_S16_BE_MONO,
261         priv:  &qt_mono16,
262     },{
263         name:  "stereo",
264         ext:   "mov",
265         fmtid: AUDIO_S16_BE_STEREO,
266         priv:  &qt_stereo,
267     },{
268         /* EOF */
269     }
270 };
271 
272 struct ng_writer qt_writer = {
273     name:      "qt",
274     desc:      "Apple QuickTime format",
275     combined:  1,
276     video:     qt_vformats,
277     audio:     qt_aformats,
278     wr_open:   qt_open,
279     wr_video:  qt_video,
280     wr_audio:  qt_audio,
281     wr_close:  qt_close,
282 };
283 
284 /* ----------------------------------------------------------------------- */
285 
286 #if 0
287 /* debug only */
288 static void dump_codecs(void)
289 {
290     lqt_codec_info_t **info;
291     int i,j;
292 
293     info = lqt_query_registry(1, 1, 1, 1);
294     for (i = 0; info[i] != NULL; i++) {
295         fprintf(stderr,"lqt: %s codec: %s [%s]\n",
296                 info[i]->type == LQT_CODEC_AUDIO ? "audio" : "video",
297                 info[i]->name,info[i]->long_name);
298         fprintf(stderr,"   encode: %s\n",
299                 info[i]->direction == LQT_DIRECTION_DECODE ? "no" : "yes");
300         fprintf(stderr,"   decode: %s\n",
301                 info[i]->direction == LQT_DIRECTION_ENCODE ? "no" : "yes");
302         for (j = 0; j < info[i]->num_fourccs; j++)
303             fprintf(stderr,"   fcc   : %s\n",info[i]->fourccs[j]);
304         for (j = 0; j < info[i]->num_encoding_colormodels; j++)
305             fprintf(stderr,"   cmodel: %s\n",
306                     lqt_get_colormodel_string(info[i]->encoding_colormodels[j]));
307         fprintf(stderr,"\n");
308     }
309     lqt_destroy_codec_info(info);
310 }
311 #endif
312 
313 static struct ng_format_list*
314 qt_list_add(struct ng_format_list* list,
315          char *name, char *desc, char *ext, int fmtid, void *priv)
316 {
317     int n;
318 
319     for (n = 0; list[n].name != NULL; n++)
320         /* nothing */;
321     list = realloc(list,sizeof(struct ng_format_list)*(n+2));
322     memset(list+n,0,sizeof(struct ng_format_list)*2);
323     list[n].name  = strdup(name);
324     list[n].desc  = strdup(desc);
325     list[n].ext   = strdup(ext);
326     list[n].fmtid = fmtid;
327     list[n].priv  = priv;
328     return list;
329 }
330 
331 static struct ng_format_list* video_list(void)
332 {
333     static int debug = 0;
334     lqt_codec_info_t **info;
335     struct ng_format_list *video;
336     int i,j,k,skip,fmtid;
337     unsigned int cmodel;
338     struct qt_video_priv *vp;
339 
340     /* handle video encoders */
341     video = malloc(sizeof(qt_vformats));
342     memcpy(video,qt_vformats,sizeof(qt_vformats));
343     info = lqt_query_registry(0, 1, 1, 0);
344     for (i = 0; info[i] != NULL; i++) {
345         if (debug) {
346             fprintf(stderr,"\nlqt: %s codec: %s [%s]\n",
347                     info[i]->type == LQT_CODEC_AUDIO ? "audio" : "video",
348                     info[i]->name,info[i]->long_name);
349             for (j = 0; j < info[i]->num_fourccs; j++)
350                 fprintf(stderr,"   fcc   : %s\n",info[i]->fourccs[j]);
351             for (j = 0; j < info[i]->num_encoding_colormodels; j++)
352                 fprintf(stderr,"   cmodel: %d [%s]\n",
353                         info[i]->encoding_colormodels[j],
354                         lqt_get_colormodel_string(info[i]->encoding_colormodels[j]));
355         }
356 
357         /* sanity checks */
358         if (0 == info[i]->num_fourccs) {
359             if (debug)
360                 fprintf(stderr,"   skipping, no fourcc\n");
361             continue;
362         }
363         
364         /* avoid dup entries */
365         skip = 0;
366         for (j = 0; video[j].name != NULL; j++) {
367             const struct qt_video_priv *p = video[j].priv;
368             for (k = 0; k < info[i]->num_fourccs; k++)
369                 if (0 == strcmp(p->fcc,info[i]->fourccs[k]))
370                     skip = 1;
371         }
372         if (skip) {
373             if (debug)
374                 fprintf(stderr,"   skipping, fourcc already in list\n");
375             continue;
376         }
377 
378         /* pick colormodel */
379         fmtid  = VIDEO_NONE;
380         cmodel = 0;
381         for (j = 0; j < info[i]->num_encoding_colormodels; j++) {
382             cmodel = info[i]->encoding_colormodels[j];
383             if (cmodel>= sizeof(cmodels)/sizeof(int))
384                 continue;
385             if (!cmodels[cmodel])
386                 continue;
387             fmtid = cmodels[cmodel];
388             break;
389         }
390         if (VIDEO_NONE == fmtid) {
391             if (debug)
392                 fprintf(stderr,"   skipping, can't handle color model\n");
393             continue;
394         }
395 
396         /* all fine */
397         if (debug)
398             fprintf(stderr,"   ok, using fmtid %d [%s]\n",
399                     fmtid,ng_vfmt_to_desc[fmtid]);
400         vp = malloc(sizeof(*vp));
401         memset(vp,0,sizeof(*vp));
402         strcpy(vp->fcc,info[i]->fourccs[0]);
403         vp->libencode = 1;
404         vp->cmodel    = cmodel;
405         video = qt_list_add(video,vp->fcc,info[i]->long_name,"mov",fmtid,vp);
406     }
407     lqt_destroy_codec_info(info);
408     return video;
409 }
410 
411 static struct ng_format_list* audio_list(void)
412 {
413     static int debug = 0;
414     lqt_codec_info_t **info;
415     struct ng_format_list *audio;
416     int i,j;
417     struct qt_audio_priv *ap;
418 
419     /* handle video encoders */
420     audio = malloc(sizeof(qt_aformats));
421     memcpy(audio,qt_aformats,sizeof(qt_aformats));
422     info = lqt_query_registry(1, 0, 1, 0);
423     for (i = 0; info[i] != NULL; i++) {
424         if (debug) {
425             fprintf(stderr,"\nlqt: %s codec: %s [%s]\n",
426                     info[i]->type == LQT_CODEC_AUDIO ? "audio" : "video",
427                     info[i]->name,info[i]->long_name);
428             for (j = 0; j < info[i]->num_fourccs; j++)
429                 fprintf(stderr,"   fcc   : %s\n",info[i]->fourccs[j]);
430         }
431 
432         /* sanity checks */
433         if (0 == info[i]->num_fourccs) {
434             if (debug)
435                 fprintf(stderr,"   skipping, no fourcc\n");
436             continue;
437         }
438 
439         /* skip uncompressed formats */
440         if (0 == strcmp(info[i]->fourccs[0],QUICKTIME_RAW)  ||
441             0 == strcmp(info[i]->fourccs[0],QUICKTIME_ULAW) ||
442             0 == strcmp(info[i]->fourccs[0],QUICKTIME_IMA4) || /* ??? */
443             0 == strcmp(info[i]->fourccs[0],QUICKTIME_TWOS)) {
444             if (debug)
445                 fprintf(stderr,"   skipping, uncompressed\n");
446             continue;
447         }
448 
449         /* all fine */
450         if (debug)
451             fprintf(stderr,"   ok\n");
452         ap = malloc(sizeof(*ap));
453         memset(ap,0,sizeof(*ap));
454         strcpy(ap->fcc,info[i]->fourccs[0]);
455         ap->libencode = 1;
456         audio = qt_list_add(audio,ap->fcc,info[i]->long_name,"mov",
457                             AUDIO_S16_NATIVE_MONO,ap);
458     }
459     lqt_destroy_codec_info(info);
460     return audio;
461 }
462 
463 extern void ng_plugin_init(void);
464 void ng_plugin_init(void)
465 {
466     qt_writer.video = video_list();
467     qt_writer.audio = audio_list();
468     ng_writer_register(NG_PLUGIN_MAGIC,__FILE__,&qt_writer);
469 }
470 
  This page was automatically generated by the LXR engine.