📄 read-qt.c
字号:
#include "config.h"#include <stdlib.h>#include <stdio.h>#include <string.h>#include <pthread.h>#include <quicktime/quicktime.h>#include <quicktime/colormodels.h>#include <quicktime/lqt.h>#include "grab-ng.h"#define AUDIO_SIZE (64*1024)/* ----------------------------------------------------------------------- */static int fmtid_to_cmodel[VIDEO_FMT_COUNT] = { [ VIDEO_RGB24 ] = BC_RGB888, [ VIDEO_BGR24 ] = BC_BGR888, [ VIDEO_YUYV ] = BC_YUV422, [ VIDEO_YUV420P ] = BC_YUV420P,};/* ----------------------------------------------------------------------- */struct qt_handle { /* libquicktime handle */ quicktime_t *qt; /* format */ struct ng_video_fmt vfmt; struct ng_audio_fmt afmt; /* misc video */ unsigned char **rows; int rate; /* misc audio */ int channels; int16_t *left,*right; long long bps;};static void* qt_open(char *moviename){ struct qt_handle *h; char *str; int i; if (NULL == (h = malloc(sizeof(*h)))) return NULL; memset(h,0,sizeof(*h)); /* open file */ h->qt = quicktime_open(moviename,1,0); if (NULL == h->qt) { fprintf(stderr,"ERROR: can't open file: %s\n",moviename); free(h); return NULL; } if (ng_debug) { /* print misc info */ fprintf(stderr,"quicktime movie %s:\n",moviename); str = quicktime_get_copyright(h->qt); if (str) fprintf(stderr," copyright: %s\n",str); str = quicktime_get_name(h->qt); if (str) fprintf(stderr," name: %s\n",str); str = quicktime_get_info(h->qt); if (str) fprintf(stderr," info: %s\n",str); /* print video info */ if (quicktime_has_video(h->qt)) { fprintf(stderr," video: %d track(s)\n",quicktime_video_tracks(h->qt)); for (i = 0; i < quicktime_video_tracks(h->qt); i++) { fprintf(stderr, " track #%d\n" " width : %d\n" " height: %d\n" " depth : %d bit\n" " rate : %.2f fps\n" " codec : %s\n", i+1, quicktime_video_width(h->qt,i), quicktime_video_height(h->qt,i), quicktime_video_depth(h->qt,i), quicktime_frame_rate(h->qt,i), quicktime_video_compressor(h->qt,i)); } } /* print audio info */ if (quicktime_has_audio(h->qt)) { fprintf(stderr," audio: %d track(s)\n",quicktime_audio_tracks(h->qt)); for (i = 0; i < quicktime_audio_tracks(h->qt); i++) { fprintf(stderr, " track #%d\n" " rate : %ld Hz\n" " bits : %d\n" " chans : %d\n" " codec : %s\n", i+1, quicktime_sample_rate(h->qt,i), quicktime_audio_bits(h->qt,i), quicktime_track_channels(h->qt,i), quicktime_audio_compressor(h->qt,i)); } } } /* video format */ if (!quicktime_has_video(h->qt)) { if (ng_debug) fprintf(stderr,"qt: no video stream\n"); } else if (!quicktime_supported_video(h->qt,0)) { if (ng_debug) fprintf(stderr,"qt: unsupported video codec\n"); } else { h->vfmt.width = quicktime_video_width(h->qt,0); h->vfmt.height = quicktime_video_height(h->qt,0); h->rate = quicktime_frame_rate(h->qt,0); } /* audio format */ if (!quicktime_has_audio(h->qt)) { if (ng_debug) fprintf(stderr,"qt: no audio stream\n"); } else if (!quicktime_supported_audio(h->qt,0)) { if (ng_debug) fprintf(stderr,"qt: unsupported audio codec\n"); } else { h->channels = quicktime_track_channels(h->qt,0); h->afmt.fmtid = (h->channels > 1) ? AUDIO_S16_NATIVE_STEREO : AUDIO_S16_NATIVE_MONO; h->afmt.rate = quicktime_sample_rate(h->qt,0); } return h;}static struct ng_video_fmt* qt_vfmt(void *handle, int *vfmt, int vn){ struct qt_handle *h = handle; int i; for (i = 0; i < vn; i++) { if (ng_debug) fprintf(stderr,"qt: trying: %d [%s]\n", vfmt[i],ng_vfmt_to_desc[vfmt[i]]); if (0 == fmtid_to_cmodel[vfmt[i]]) continue; if (!quicktime_reads_cmodel(h->qt,fmtid_to_cmodel[vfmt[i]],0)) continue; quicktime_set_cmodel(h->qt, fmtid_to_cmodel[vfmt[i]]); h->vfmt.fmtid = vfmt[i]; break; } h->vfmt.bytesperline = (h->vfmt.width*ng_vfmt_to_depth[h->vfmt.fmtid]) >> 3; return &h->vfmt;}static struct ng_audio_fmt* qt_afmt(void *handle){ struct qt_handle *h = handle; return h->afmt.fmtid ? &h->afmt : NULL;}static struct ng_video_buf* qt_vdata(void *handle, unsigned int drop){ struct qt_handle *h = handle; struct ng_video_buf *buf; unsigned int i; if (quicktime_video_position(h->qt,0) >= quicktime_video_length(h->qt,0)) return NULL; buf = ng_malloc_video_buf(&h->vfmt,h->vfmt.bytesperline*h->vfmt.height); if (!h->rows) h->rows = malloc(h->vfmt.height * sizeof(char*)); switch (fmtid_to_cmodel[h->vfmt.fmtid]) { case BC_RGB888: case BC_BGR888: for (i = 0; i < h->vfmt.height; i++) h->rows[i] = buf->data + h->vfmt.width * 3 * i; break; case BC_YUV422: for (i = 0; i < h->vfmt.height; i++) h->rows[i] = buf->data+ h->vfmt.width * 2 * i; break; case BC_YUV420P: h->rows[0] = buf->data; h->rows[1] = buf->data + h->vfmt.width*h->vfmt.height; h->rows[2] = buf->data + h->vfmt.width*h->vfmt.height*5/4; break; default: BUG_ON(1,"unknown cmodel"); } /* drop frames */ for (i = 0; i < drop; i++) quicktime_read_frame(h->qt,buf->data,0); buf->info.seq = quicktime_video_position(h->qt,0); buf->info.ts = (long long) buf->info.seq * 1000000000 / h->rate; lqt_decode_video(h->qt, h->rows, 0); return buf;}static struct ng_audio_buf* qt_adata(void *handle){ struct qt_handle *h = handle; struct ng_audio_buf *buf; int16_t *dest; long pos; int i; if (quicktime_audio_position(h->qt,0) >= quicktime_audio_length(h->qt,0)) return NULL; buf = ng_malloc_audio_buf(&h->afmt,AUDIO_SIZE); dest = (int16_t*)buf->data; pos = quicktime_audio_position(h->qt,0); buf->info.ts = (long long) pos * 1000000000 / h->afmt.rate; if (h->channels > 1) { /* stereo: two channels => interlaved samples */ if (!h->left) h->left = malloc(AUDIO_SIZE/2); if (!h->right) h->right = malloc(AUDIO_SIZE/2); quicktime_set_audio_position(h->qt,pos,0); quicktime_decode_audio(h->qt,h->left,NULL,AUDIO_SIZE/4,0); quicktime_set_audio_position(h->qt,pos,1); quicktime_decode_audio(h->qt,h->right,NULL,AUDIO_SIZE/4,1); for (i = 0; i < AUDIO_SIZE/4; i++) { dest[2*i+0] = h->left[i]; dest[2*i+1] = h->right[i]; } } else { /* mono */ quicktime_decode_audio(h->qt,dest,NULL,AUDIO_SIZE/2,0); } return buf;}static int64_t qt_frame_time(void *handle){ struct qt_handle *h = handle; return 1000000000 / h->rate;}static int qt_close(void *handle){ struct qt_handle *h = handle; quicktime_close(h->qt); if (h->rows) free(h->rows); free(h); return 0;}/* ----------------------------------------------------------------------- */struct ng_reader qt_reader = { name: "qt", desc: "Apple QuickTime format", magic: { "moov", "mdat" }, moff: { 4, 4 }, mlen: { 4, 4 }, rd_open: qt_open, rd_vfmt: qt_vfmt, rd_afmt: qt_afmt, rd_vdata: qt_vdata, rd_adata: qt_adata, frame_time: qt_frame_time, rd_close: qt_close,};extern void ng_plugin_init(void);void ng_plugin_init(void){ ng_reader_register(NG_PLUGIN_MAGIC,__FILE__,&qt_reader);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -