📄 lqtplay.c
字号:
/******************************************************************************* lqtplay.c libquicktime - A library for reading and writing quicktime/avi/mp4 files. http://libquicktime.sourceforge.net Copyright (C) 2002 Heroine Virtual Ltd. Copyright (C) 2002-2007 Members of the libquicktime project. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA*******************************************************************************/ /* Simple quicktime movie player. - Gerd Knorr <kraxel@bytesex.org>*/#include <quicktime/lqt.h>#include <quicktime/colormodels.h>#include <config.h> // ONLY for the PACKAGE macro. Usually, applications never need // to include config.h#define _(str) dgettext(PACKAGE, str)#include "common.h"#include <X11/Xlib.h>#include <X11/Intrinsic.h>#include <X11/StringDefs.h>#include <X11/Shell.h>#include <X11/Xaw/Simple.h>#include <X11/extensions/XShm.h>#include <X11/extensions/Xv.h>#include <X11/extensions/Xvlib.h>#ifdef HAVE_GL#include <GL/gl.h>#include <GL/glx.h>#endif#include <sys/types.h>#include <sys/time.h>#include <sys/ipc.h>#include <sys/shm.h>#include <sys/ioctl.h>#ifdef HAVE_SYS_SOUNDCARD_H#include <sys/soundcard.h>#else#ifdef HAVE_SOUNDCARD_H#include <soundcard.h>#endif#endif#ifdef HAVE_ALSA#include <alsa/asoundlib.h>#endif#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <fcntl.h>#include <time.h>#include <math.h>#include <errno.h>#include <libintl.h>#include <locale.h>/* File handle */static quicktime_t *qt = NULL;#define COUNT_SAMPLES#define DUMP_TIMECODES#ifdef COUNT_SAMPLESint64_t total_samples_decoded = 0;#endif/* ------------------------------------------------------------------------ *//* X11 code */static XtAppContext app_context;static Widget app_shell;static Display *dpy;static Visual *visual;static XVisualInfo vinfo,*vinfo_list;static XPixmapFormatValues *pf;static Widget simple;static Dimension swidth,sheight;static int xv_port = 0;static int xv_have_YUY2 = 0;static int xv_have_I420 = 0;static int xv_have_YV12 = 0;static int no_mitshm = 0;static int pixmap_bytes = 0;static int x11_byteswap = 0;#ifdef HAVE_GLstatic int use_gl = 0;#endifstatic int xpos = 0;static int ypos = 0;static int oh_width = 0;static unsigned long lut_red[256];static unsigned long lut_green[256];static unsigned long lut_blue[256];#ifdef DUMP_TIMECODESint has_timecodes = 0;uint32_t timecode_flags;int timecode_rate;static void dump_timecode(quicktime_t * file, int track, uint32_t tc) { int hours, minutes, seconds, frames; if(timecode_flags & LQT_TIMECODE_DROP) { int64_t D, M; D = tc / 17982; M = tc % 17982; tc += 18*D + 2*((M - 2) / 1798); } frames = tc % timecode_rate; tc /= timecode_rate; seconds = tc % 60; tc /= 60; minutes = tc % 60; tc /= 60; hours = tc % 24; printf("Timecode: %02d:%02d:%02d.%02d (0x%08x)\n", hours, minutes, seconds, frames, tc); }#endif/* Video stuff */static int qt_cmodel = BC_RGB888;static int qt_cmodels[] = { BC_RGB888, /* Always supported */ /* Placeholders for various YUV formats, set by xv_init */ LQT_COLORMODEL_NONE, LQT_COLORMODEL_NONE, LQT_COLORMODEL_NONE, };#define SWAP2(x) (((x>>8) & 0x00ff) |\ ((x<<8) & 0xff00))#define SWAP4(x) (((x>>24) & 0x000000ff) |\ ((x>>8) & 0x0000ff00) |\ ((x<<8) & 0x00ff0000) |\ ((x<<24) & 0xff000000))static voidx11_lut(unsigned long red_mask, unsigned long green_mask, unsigned long blue_mask, int bytes, int swap){ int rgb_red_bits = 0; int rgb_red_shift = 0; int rgb_green_bits = 0; int rgb_green_shift = 0; int rgb_blue_bits = 0; int rgb_blue_shift = 0; unsigned int i; unsigned int mask; for (i = 0; i < 32; i++) { mask = (1 << i); if (red_mask & mask) rgb_red_bits++; else if (!rgb_red_bits) rgb_red_shift++; if (green_mask & mask) rgb_green_bits++; else if (!rgb_green_bits) rgb_green_shift++; if (blue_mask & mask) rgb_blue_bits++; else if (!rgb_blue_bits) rgb_blue_shift++; } if (rgb_red_bits > 8) for (i = 0; i < 256; i++) lut_red[i] = (i << (rgb_red_bits + rgb_red_shift - 8)); else for (i = 0; i < 256; i++) lut_red[i] = (i >> (8 - rgb_red_bits)) << rgb_red_shift; if (rgb_green_bits > 8) for (i = 0; i < 256; i++) lut_green[i] = (i << (rgb_green_bits + rgb_green_shift - 8)); else for (i = 0; i < 256; i++) lut_green[i] = (i >> (8 - rgb_green_bits)) << rgb_green_shift; if (rgb_blue_bits > 8) for (i = 0; i < 256; i++) lut_blue[i] = (i << (rgb_blue_bits + rgb_blue_shift - 8)); else for (i = 0; i < 256; i++) lut_blue[i] = (i >> (8 - rgb_blue_bits)) << rgb_blue_shift; if (2 == bytes && swap) { for (i = 0; i < 256; i++) { lut_red[i] = SWAP2(lut_red[i]); lut_green[i] = SWAP2(lut_green[i]); lut_blue[i] = SWAP2(lut_blue[i]); } } if (4 == bytes && swap) { for (i = 0; i < 256; i++) { lut_red[i] = SWAP4(lut_red[i]); lut_green[i] = SWAP4(lut_green[i]); lut_blue[i] = SWAP4(lut_blue[i]); } }}static voidrgb_to_lut2(unsigned char *dest, unsigned char *src, int p){ unsigned short *d = (unsigned short*)dest; while (p-- > 0) { *(d++) = lut_red[src[0]] | lut_green[src[1]] | lut_blue[src[2]]; src += 3; }}static voidrgb_to_lut4(unsigned char *dest, unsigned char *src, int p){ unsigned int *d = (unsigned int*)dest; while (p-- > 0) { *(d++) = lut_red[src[0]] | lut_green[src[1]] | lut_blue[src[2]]; src += 3; }}static void x11_init(void){ int i,n; /* get visual info */ visual = DefaultVisualOfScreen(XtScreen(app_shell)); vinfo.visualid = XVisualIDFromVisual(visual); vinfo_list = XGetVisualInfo(dpy, VisualIDMask, &vinfo, &n); vinfo = vinfo_list[0]; if (vinfo.class != TrueColor || vinfo.depth < 15) { fprintf(stderr,_("can't handle visuals != TrueColor, sorry\n")); exit(1); } /* look for default pixmap format */ pf = XListPixmapFormats(dpy,&n); for (i = 0; i < n; i++) if (pf[i].depth == vinfo.depth) pixmap_bytes = pf[i].bits_per_pixel/8; /* byteswapping needed ??? */#ifdef WORDS_BIGENDIAN if (ImageByteOrder(dpy)==LSBFirst) x11_byteswap=1;#else if (ImageByteOrder(dpy)==MSBFirst) x11_byteswap=1;#endif /* init lookup tables */ x11_lut(vinfo.red_mask, vinfo.green_mask, vinfo.blue_mask, pixmap_bytes,x11_byteswap);}static void xv_init(void){ int cmodel_index; unsigned int ver, rel, req, ev, err; int i; unsigned int adaptors; int formats; XvAdaptorInfo *ai; XvImageFormatValues *fo; if (Success != XvQueryExtension(dpy,&ver,&rel,&req,&ev,&err)) return; /* find + lock port */ if (Success != XvQueryAdaptors(dpy,DefaultRootWindow(dpy),&adaptors,&ai)) return; for (i = 0; i < adaptors; i++) { if ((ai[i].type & XvInputMask) && (ai[i].type & XvImageMask)) { if (Success != XvGrabPort(dpy,ai[i].base_id,CurrentTime)) { fprintf(stderr,_("INFO: Xvideo port %ld: is busy, skipping\n"), ai[i].base_id); continue; } xv_port = ai[i].base_id; break; } } if (0 == xv_port) return; /* check image formats */ fo = XvListImageFormats(dpy, xv_port, &formats); for(i = 0; i < formats; i++) { fprintf(stderr, _("INFO: Xvideo port %d: 0x%x (%c%c%c%c) %s"), xv_port, fo[i].id, (fo[i].id) & 0xff, (fo[i].id >> 8) & 0xff, (fo[i].id >> 16) & 0xff, (fo[i].id >> 24) & 0xff, (fo[i].format == XvPacked) ? "packed" : "planar"); if (FOURCC_YUV2 == fo[i].id) { fprintf(stderr," [BC_YUV422]"); xv_have_YUY2 = 1; } if (FOURCC_YV12 == fo[i].id) { fprintf(stderr," [BC_YUV420P]"); xv_have_YV12 = 1; } if (FOURCC_I420 == fo[i].id) { fprintf(stderr," [BC_YUV420P]"); xv_have_I420 = 1; } fprintf(stderr,"\n"); } /* Fill the cmodel array */ cmodel_index = 1; if(xv_have_YUY2) qt_cmodels[cmodel_index++] = BC_YUV422; if(xv_have_YV12 || xv_have_I420) qt_cmodels[cmodel_index++] = BC_YUV420P; }static intcatch_no_mitshm(Display * dpy, XErrorEvent * event){ no_mitshm++; return 0;}static XImage*x11_create_ximage(Display *dpy, int width, int height){ XImage *ximage = NULL; char *ximage_data; XShmSegmentInfo *shminfo = NULL; void *old_handler; if (no_mitshm) goto no_mitshm; old_handler = XSetErrorHandler(catch_no_mitshm); shminfo = malloc(sizeof(XShmSegmentInfo)); memset(shminfo, 0, sizeof(XShmSegmentInfo)); ximage = XShmCreateImage(dpy,vinfo.visual,vinfo.depth, ZPixmap, NULL, shminfo, width, height); if (NULL == ximage) goto shm_error; shminfo->shmid = shmget(IPC_PRIVATE, ximage->bytes_per_line * ximage->height, IPC_CREAT | 0777); if (-1 == shminfo->shmid) { perror("shmget"); goto shm_error; } shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0); if ((void *)-1 == shminfo->shmaddr) { perror("shmat"); goto shm_error; } ximage->data = shminfo->shmaddr; shminfo->readOnly = False; XShmAttach(dpy, shminfo); XSync(dpy, False); if (no_mitshm) goto shm_error; shmctl(shminfo->shmid, IPC_RMID, 0); XSetErrorHandler(old_handler); return ximage;shm_error: if (ximage) { XDestroyImage(ximage); ximage = NULL; } if ((void *)-1 != shminfo->shmaddr && NULL != shminfo->shmaddr) shmdt(shminfo->shmaddr); free(shminfo); XSetErrorHandler(old_handler); no_mitshm = 1; no_mitshm: if (NULL == (ximage_data = malloc(width * height * pixmap_bytes))) { fprintf(stderr,_("out of memory\n")); exit(1); } ximage = XCreateImage(dpy, vinfo.visual, vinfo.depth, ZPixmap, 0, ximage_data, width, height, 8, 0); memset(ximage->data, 0, ximage->bytes_per_line * ximage->height); return ximage;}static XvImage*xv_create_ximage(Display *dpy, int width, int height, int port, int format){ XvImage *xvimage = NULL; char *ximage_data; XShmSegmentInfo *shminfo = NULL; void *old_handler; if (no_mitshm) goto no_mitshm; old_handler = XSetErrorHandler(catch_no_mitshm); shminfo = malloc(sizeof(XShmSegmentInfo)); memset(shminfo, 0, sizeof(XShmSegmentInfo)); xvimage = XvShmCreateImage(dpy, port, format, 0, width, height, shminfo); if (NULL == xvimage) goto shm_error; shminfo->shmid = shmget(IPC_PRIVATE, xvimage->data_size, IPC_CREAT | 0777); if (-1 == shminfo->shmid) { perror("shmget"); goto shm_error;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -