liblavplay.c

来自「Motion JPEG编解码器源代码」· C语言 代码 · 共 2,022 行 · 第 1/5 页

C
2,022
字号
/* * liblavplay - a librarified Linux Audio Video PLAYback * * Copyright (C) 2000 Rainer Johanni <Rainer@Johanni.de> * Extended by:   Gernot Ziegler  <gz@lysator.liu.se> *                Ronald Bultje   <rbultje@ronald.bitfreak.net> *              & many others * * A library for playing back MJPEG video via software MJPEG * decompression (using SDL) or via hardware MJPEG video * devices such as the Pinnacle/Miro DC10(+), Iomega Buz, * the Linux Media Labs LML33, the Matrox Marvel G200, * Matrox Marvel G400 and the Rainbow Runner G-series. *  * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. *  * This program 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 General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. */#include <config.h>#include <stdlib.h>#include <stdarg.h>#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <string.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <sys/time.h>#include <sys/resource.h>#include <sys/wait.h>#ifdef HAVE_V4L#include <sys/vfs.h>#endif#ifndef X_DISPLAY_MISSING#include <X11/Xlib.h>#include <X11/Xutil.h>#endif#ifdef HAVE_SYS_SOUNDCARD_H#include <sys/soundcard.h>#endif#ifdef HAVE_V4L /* Because of some really cool feature in video4linux1, also known as * 'not including sys/types.h and sys/time.h', we had to include it * ourselves. In all their intelligence, these people decided to fix * this in the next version (video4linux2) in such a cool way that it * breaks all compilations of old stuff... * The real problem is actually that linux/time.h doesn't use proper * macro checks before defining types like struct timeval. The proper * fix here is to either fuck the kernel header (which is what we do * by defining _LINUX_TIME_H, an innocent little hack) or by fixing it * upstream, which I'll consider doing later on. If you get compiler * errors here, check your linux/time.h && sys/time.h header setup. */#define _LINUX_TIME_H#include <linux/videodev.h>#else#define VIDEO_MODE_PAL		0#define VIDEO_MODE_NTSC		1#define VIDEO_MODE_SECAM	2#define VIDEO_MODE_AUTO		3#endif#include <videodev_mjpeg.h>#include <pthread.h>#ifdef HAVE_SDL#include <SDL/SDL.h>#endif#include "mjpeg_types.h"#include "liblavplay.h"#include "audiolib.h"/*#include "lav_io.h" *//*#include "editlist.h" */#include "jpegutils.h"#ifdef	HAVE_LIBDV#include <libdv/dv.h>#endif/* Prototypes to avoid compile time warning errors */void frame_YUV422_to_YUV420P(uint8_t **, uint8_t *, int , int );#ifdef HAVE_SDLint frame_planar_to_packed(uint8_t *, uint8_t **, int, int, int, int, int);#endif/* * As far as I (maddog) can tell, this is what is going on with libdv-0.9 *  and the unpacking routine...  *    o Ft/Fb refer to top/bottom scanlines (interleaved) --- each sample *       is implicitly tagged by 't' or 'b' (samples are not mixed between *       fields) *    o Indices on Cb and Cr samples indicate the Y sample with which *       they are co-sited. *    o '^' indicates which samples are preserved by the unpacking * * libdv packs both NTSC 4:1:1 and PAL 4:2:0 into a common frame format of *  packed 4:2:2 pixels as follows: * * ***** NTSC 4:1:1 ***** * *   libdv's 4:2:2-packed representation  (chroma repeated horizontally) * *Ft Y00.Cb00.Y01.Cr00.Y02.Cb00.Y03.Cr00 Y04.Cb04.Y05.Cr04.Y06.Cb04.Y07.Cr04 *    ^    ^   ^    ^   ^    ^   ^    ^   ^    ^   ^    ^   ^    ^   ^    ^ *Fb Y00.Cb00.Y01.Cr00.Y02.Cb00.Y03.Cr00 Y04.Cb04.Y05.Cr04.Y06.Cb04.Y07.Cr04 *    ^    ^   ^    ^   ^    ^   ^    ^   ^    ^   ^    ^   ^    ^   ^    ^ *Ft Y10.Cb10.Y11.Cr10.Y12.Cb10.Y13.Cr10 Y14.Cb14.Y15.Cr14.Y16.Cb14.Y17.Cr14 *    ^        ^        ^        ^        ^        ^        ^        ^     *Fb Y10.Cb10.Y11.Cr10.Y12.Cb10.Y13.Cr10 Y14.Cb14.Y15.Cr14.Y16.Cb14.Y17.Cr14 *    ^        ^        ^        ^        ^        ^        ^        ^     * *    lavtools unpacking into 4:2:0-planar  (note lossiness) * *Ft  Y00.Y01.Y02.Y03.Y04.Y05.Y06.Y07... *Fb  Y00.Y01.Y02.Y03.Y04.Y05.Y06.Y07... *Ft  Y10.Y11.Y12.Y13.Y14.Y15.Y16.Y17... *Fb  Y10.Y11.Y12.Y13.Y14.Y15.Y16.Y17... * *Ft  Cb00.Cb00.Cb04.Cb04...    Cb00,Cb04... are doubled *Fb  Cb00.Cb00.Cb04.Cb04...    Cb10,Cb14... are ignored * *Ft  Cr00.Cr00.Cr04.Cr04... *Fb  Cr00.Cr00.Cr04.Cr04... * *  ***** PAL 4:2:0 ***** * *   libdv's 4:2:2-packed representation  (chroma repeated vertically) * *Ft Y00.Cb00.Y01.Cr10.Y02.Cb02.Y03.Cr12 Y04.Cb04.Y05.Cr14.Y06.Cb06.Y07.Cr16 *    ^    ^   ^    ^   ^    ^   ^    ^   ^    ^   ^    ^   ^    ^   ^    ^ *Fb Y00.Cb00.Y01.Cr10.Y02.Cb02.Y03.Cr12 Y04.Cb04.Y05.Cr14.Y06.Cb06.Y07.Cr16 *    ^    ^   ^    ^   ^    ^   ^    ^   ^    ^   ^    ^   ^    ^   ^    ^ *Ft Y10.Cb00.Y11.Cr10.Y12.Cb02.Y13.Cr12 Y14.Cb04.Y15.Cr14.Y16.Cb06.Y17.Cr16 *    ^        ^        ^        ^        ^        ^        ^        ^     *Fb Y10.Cb00.Y11.Cr10.Y12.Cb02.Y13.Cr12 Y14.Cb04.Y15.Cr14.Y16.Cb06.Y17.Cr16 *    ^        ^        ^        ^        ^        ^        ^        ^     * *    lavtools unpacking into 4:2:0-planar * *Ft  Y00.Y01.Y02.Y03.Y04.Y05.Y06.Y07... *Fb  Y00.Y01.Y02.Y03.Y04.Y05.Y06.Y07... *Ft  Y10.Y11.Y12.Y13.Y14.Y15.Y16.Y17... *Fb  Y10.Y11.Y12.Y13.Y14.Y15.Y16.Y17... * *Ft  Cb00.Cb02.Cb04.Cb06... *Fb  Cb00.Cb02.Cb04.Cb06... * *Ft  Cr10.Cr12.Cr14.Cr16... *Fb  Cr10.Cr12.Cr14.Cr16... * *//* * Unpack libdv's 4:2:2-packed into our 4:2:0-planar, *  treating each interlaced field independently * */void frame_YUV422_to_YUV420P(uint8_t **output, uint8_t *input,			     int width, int height){    int i, j, w2;    uint8_t *y, *cb, *cr;    w2 = width/2;    y = output[0];    cb = output[1];    cr = output[2];    for (i=0; i<height; i+=4) {	/* process two scanlines (one from each field, interleaved) */        /* ...top-field scanline */        for (j=0; j<w2; j++) {            /* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */            *(y++) =  *(input++);            *(cb++) = *(input++);            *(y++) =  *(input++);            *(cr++) = *(input++);        }        /* ...bottom-field scanline */        for (j=0; j<w2; j++) {            /* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */            *(y++) =  *(input++);            *(cb++) = *(input++);            *(y++) =  *(input++);            *(cr++) = *(input++);        }	/* process next two scanlines (one from each field, interleaved) */        /* ...top-field scanline */	for (j=0; j<w2; j++) {	  /* skip every second line for U and V */	  *(y++) = *(input++);	  input++;	  *(y++) = *(input++);	  input++;	}        /* ...bottom-field scanline */	for (j=0; j<w2; j++) {	  /* skip every second line for U and V */	  *(y++) = *(input++);	  input++;	  *(y++) = *(input++);	  input++;	}    }}#define FOURCC_I420 0x30323449#define FOURCC_I422 0x32323449#ifdef HAVE_SDLint frame_planar_to_packed(uint8_t *output, uint8_t **input,			   int width, int height, int ofmt, int ifmt, int interlaced){  uint8_t *y, *u, *v, *sy, *su, *sv, *sye, *su0, *sv0;  int dy, dc, cw, scw, ch, scdv, scdh, ln, sln, px, spx;  ch = height;  cw = scw = width;#define DIV_MAX 4  scdv = scdh = DIV_MAX;  switch (ofmt) {  case SDL_YUY2_OVERLAY:    scdh /= 2;    cw   /= 2;    y = output;     dy = 2;    u = output + 1;    v = output + 3; dc = 4;    break;  case SDL_UYVY_OVERLAY:    scdh /= 2;    cw   /= 2;    y = output + 1; dy = 2;    u = output;    v = output + 2; dc = 4;    break;  case SDL_YVYU_OVERLAY:    scdh /= 2;    cw   /= 2;    y = output;     dy = 2;    u = output + 3;    v = output + 1; dc = 4;    break;  default:    return 1;  }  switch (ifmt) {  case FOURCC_I420:    scdv *= 2;  case FOURCC_I422:    scdh *= 2;    scw  /= 2;    sy  = input[0];    su0 = input[1];    sv0 = input[2];    break;  default:    return 1;  }  sye = sy + (width * height);  while (sy < sye) {    *y = *sy++; y += dy;  }  for (ln = 0; ln < ch; ln++) {    sln = ln * DIV_MAX / scdv;    if (interlaced) {      sln &= ~1;      sln |= (ln & 1);    }    su = su0 + (sln * scw);    sv = sv0 + (sln * scw);    for (px = 0; px < cw; px++) {      spx = px * DIV_MAX / scdh;      *u = su[spx]; u += dc;      *v = sv[spx]; v += dc;    }  }  return 0;}#endif/* On some systems MAP_FAILED seems to be missing */#ifndef MAP_FAILED#define MAP_FAILED ( (caddr_t) -1 )#endif#define MJPEG_MAX_BUF 64#define HZ 100#define VALUE_NOT_FILLED -10000typedef struct {   uint8_t*buff;                              /* the buffer for JPEG frames */   int    video_fd;                           /* the file descriptor for the video device */   struct mjpeg_requestbuffers br;            /* buffer requests */   uint8_t*tmpbuff[2];                        /* buffers for flicker reduction */   double spvf;                               /* seconds per video frame */   int    usec_per_frame;                     /* milliseconds per frame */   int    min_frame_num;                      /* the lowest frame to be played back - normally 0 */   int    max_frame_num;                      /* the latest frame to be played back - normally num_frames - 1 */   int    current_frame_num;                  /* the current frame */   int    current_playback_speed;             /* current playback speed */   long   old_field_len;   int    old_buff_no;   int    currently_processed_frame;          /* changes constantly */   int    currently_synced_frame;             /* changes constantly */   int    show_top;                           /* changes constantly */   int    first_frame;                        /* software sync variable */   struct timeval lastframe_completion;       /* software sync variable */#ifdef HAVE_SDL   SDL_Surface *screen;                       /* the screen object used for software playback */   SDL_Rect jpegdims;                         /* a SDL rectangle */   SDL_Overlay *yuv_overlay;                  /* SDL YUV overlay */   pthread_t software_playback_thread;        /* the thread for software playback */   pthread_mutex_t valid_mutex;   int valid[MJPEG_MAX_BUF];                  /* Non-zero if buffer has been filled - num of frames to be played */   pthread_cond_t buffer_filled[MJPEG_MAX_BUF];   pthread_cond_t buffer_done[MJPEG_MAX_BUF];   pthread_mutex_t syncinfo_mutex;   long buffer_entry[MJPEG_MAX_BUF];   long currently_processed_entry;   int yuvformat;   uint8_t *yuvbuff[3];# ifdef	HAVE_LIBDV   dv_decoder_t *decoder;   int pitches[3];# endif#endif   int data_format[MJPEG_MAX_BUF];   struct mjpeg_sync syncinfo[MJPEG_MAX_BUF]; /* synchronization info */   unsigned long *save_list;                  /* for editing purposes */   long save_list_len;                        /* for editing purposes */   uint8_t abuff[16384];                       /* the audio buffer */   double spas;                               /* seconds per audio sample */   long   audio_buffer_size;                  /* audio stream buffer size */   int    audio_mute;                         /* controls whether to currently play audio or not */   int    state;                              /* playing, paused or stoppped */   pthread_t playback_thread;                 /* the thread for the whole playback-library */} video_playback_setup;/****************************************************** * lavplay_msg() *   simplicity function which will give messages ******************************************************/static void lavplay_msg(int type, lavplay_t *info, const char format[], ...) GNUC_PRINTF(3,4);static void lavplay_msg(int type, lavplay_t *info, const char format[], ...){   char buf[1024];   va_list args;   va_start(args, format);   vsnprintf(buf, sizeof(buf)-1, format, args);   va_end(args);   if (!info) 		/* we can't let errors pass without giving notice */      mjpeg_error("**ERROR: %s", buf);   else if (info->msg_callback)      info->msg_callback(type, buf);   else if (type == LAVPLAY_MSG_ERROR)      mjpeg_error("**ERROR: %s", buf);}/****************************************************** * lavplay_change_state() *   change the state ******************************************************/static void lavplay_change_state(lavplay_t *info, int new_state){   video_playback_setup *settings = (video_playback_setup *)info->settings;   /*EditList *editlist = info->editlist; */   settings->state = new_state;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?