liblavplay.c

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

C
2,022
字号
         "SDL Failed to initialise...");      return 0;   }   /* Now initialize SDL */   if (info->soft_full_screen)      settings->screen = SDL_SetVideoMode(info->sdl_width, info->sdl_height, 0,         SDL_HWSURFACE | SDL_FULLSCREEN);   else      settings->screen = SDL_SetVideoMode(info->sdl_width, info->sdl_height, 0,         SDL_HWSURFACE);   if (!settings->screen)   {      lavplay_msg(LAVPLAY_MSG_ERROR, info,         "SDL: Output screen error: %s", SDL_GetError());      return 0;   }   SDL_EventState(SDL_KEYDOWN, SDL_ENABLE);   SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);   /* since IYUV ordering is not supported by Xv accel on maddog's system    *  (Matrox G400 --- although, the alias I420 is, but this is not    *  recognized by SDL), we use YV12 instead, which is identical,    *  except for ordering of Cb and Cr planes...    * we swap those when we copy the data to the display buffer...    */   /* FIXME: Is YUY2 best 422? */   settings->yuv_overlay = SDL_CreateYUVOverlay(editlist->video_width,						editlist->video_height,						settings->yuvformat,						settings->screen);   if (!settings->yuv_overlay)   {      lavplay_msg(LAVPLAY_MSG_ERROR, info,         "SDL: Couldn't create SDL_yuv_overlay: %s", SDL_GetError());      return 0;   }   lavplay_msg(LAVPLAY_MSG_INFO, info,      "SDL YUV overlay: %s", settings->yuv_overlay->hw_overlay ? "hardware" : "software" );#if 0   if(settings->yuv_overlay->pitches[0] != settings->yuv_overlay->pitches[1] ||      settings->yuv_overlay->pitches[0] != settings->yuv_overlay->pitches[2] )   {      lavplay_msg(LAVPLAY_MSG_ERROR, info,         "SDL returned pitches[] = { %d, %d, %d }", settings->yuv_overlay->pitches[0], settings->yuv_overlay->pitches[1], settings->yuv_overlay->pitches[2]);      lavplay_msg(LAVPLAY_MSG_ERROR, info,         "SDL returned non-YUV422 overlay!");      return 0;   }#endif   settings->jpegdims.x = 0; /* This is not going to work with interlaced pics !! */   settings->jpegdims.y = 0;   settings->jpegdims.w = info->sdl_width;   settings->jpegdims.h = info->sdl_height;   /* Lock the screen to test, and to be able to access screen->pixels */   if (!lavplay_SDL_lock(info)) return 0;          /* Draw bands of color on the raw surface, as run indicator for debugging */   sbuffer = (char *)settings->screen->pixels;   for ( i=0; i < settings->screen->h; ++i )    {      memset(sbuffer,(i*255)/settings->screen->h,         settings->screen->w * settings->screen->format->BytesPerPixel);      sbuffer += settings->screen->pitch;   }   /* Set the windows title */   SDL_WM_SetCaption("Lavplay Video Playback", "0000000");     /* unlock, update and wait for the fun to begin */   if (!lavplay_SDL_unlock(info)) return 0;   SDL_UpdateRect(settings->screen, 0, 0, settings->jpegdims.w, settings->jpegdims.h);   return 1;}#endif/****************************************************** * lavplay_mjpeg_software_frame_sync() *   Try to keep in sync with nominal frame rate, *     timestamp frame with actual completion time *     (after any deliberate sleeps etc) * * return value: 1 on success, 0 on error ******************************************************/#ifdef HAVE_SDLstatic void lavplay_mjpeg_software_frame_sync(lavplay_t *info, int frame_periods){   int usec_since_lastframe;   struct timeval now;   struct timespec nsecsleep;   video_playback_setup *settings = (video_playback_setup *)info->settings;   /*EditList *editlist = info->editlist; */   /* I really *wish* the timer was higher res on x86 Linux... 10mSec    * is a *pain*.  Sooo wasteful here...    */   for (;;)   {      gettimeofday( &now, 0 );      usec_since_lastframe = now.tv_usec - settings->lastframe_completion.tv_usec;      if ( usec_since_lastframe< 0)         usec_since_lastframe+= 1000000;      if( now.tv_sec > settings->lastframe_completion.tv_sec+1 )         usec_since_lastframe= 1000000;      if( settings->first_frame ||         frame_periods*settings->usec_per_frame-usec_since_lastframe < (1000000)/HZ )         break;      /* Assume some other process will get a time-slice before       * we do... and hence the worst-case delay of 1/HZ after       * sleep timer expiry will apply. Reasonable since X will       * probably do something...       */      nsecsleep.tv_nsec =          (frame_periods*settings->usec_per_frame-usec_since_lastframe-1000000/HZ)*1000;      nsecsleep.tv_sec = 0;      nanosleep( &nsecsleep, NULL );   }   settings->first_frame = 0;   /* We are done with writing the picture - Now update all surrounding info */   gettimeofday( &(settings->lastframe_completion), 0 );   settings->syncinfo[settings->currently_processed_frame].timestamp = settings->lastframe_completion;}#endif/****************************************************** * lavplay_mjpeg_playback_thread() *   the main (software) video playback thread * * return value: 1 on success, 0 on error ******************************************************/#ifdef HAVE_SDLstatic void *lavplay_mjpeg_playback_thread(void * arg){   lavplay_t *info = (lavplay_t *)arg;   video_playback_setup *settings = (video_playback_setup *)info->settings;   /*EditList *editlist = info->editlist; */   lavplay_msg(LAVPLAY_MSG_DEBUG, info,      "Starting software playback thread");   /* Allow easy shutting down by other processes... */   pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL );   pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL );   while (settings->state != LAVPLAY_STATE_STOP)   {      pthread_mutex_lock(&(settings->valid_mutex));      while (settings->valid[settings->currently_processed_frame] == 0)      {         lavplay_msg(LAVPLAY_MSG_DEBUG, info,            "Playback thread: sleeping for new frames (waiting for frame %d)",             settings->currently_processed_frame);         pthread_cond_wait(&(settings->buffer_filled[settings->currently_processed_frame]),            &(settings->valid_mutex));         if (settings->state == LAVPLAY_STATE_STOP)         {            /* Ok, we shall exit, that's the reason for the wakeup */            lavplay_msg(LAVPLAY_MSG_DEBUG, info,               "Playback thread: was told to exit");            pthread_exit(NULL);         }      }      pthread_mutex_unlock(&(settings->valid_mutex));      /* There is one buffer to play - get ready to rock ! */      if (settings->currently_processed_entry != settings->buffer_entry[settings->currently_processed_frame] &&	  !lavplay_SDL_update(info, settings->buff+settings->currently_processed_frame*settings->br.size,         settings->data_format[settings->currently_processed_frame],         settings->br.size))      {         /* something went wrong - give a warning (don't exit yet) */         lavplay_msg(LAVPLAY_MSG_WARNING, info,            "Error playing a frame");      }      settings->currently_processed_entry = settings->buffer_entry[settings->currently_processed_frame];      /* Synchronise and timestamp current frame after sync */      lavplay_mjpeg_software_frame_sync(info, settings->valid[settings->currently_processed_frame]);      settings->syncinfo[settings->currently_processed_frame].frame = settings->currently_processed_frame;      pthread_mutex_lock(&(settings->valid_mutex));      settings->valid[settings->currently_processed_frame] = 0;      pthread_mutex_unlock(&(settings->valid_mutex));      /* Broadcast & wake up the waiting processes */      pthread_cond_broadcast(&(settings->buffer_done[settings->currently_processed_frame]));      /* Now update the internal variables */      settings->currently_processed_frame = (settings->currently_processed_frame + 1) % settings->br.count;      settings->show_top = (settings->show_top) ? 0 : 1;   }   lavplay_msg(LAVPLAY_MSG_DEBUG, info,      "Playback thread: was told to exit");   pthread_exit(NULL);   return NULL;}#endif/****************************************************** * lavplay_mjpeg_open() *   hardware: opens the device and allocates buffers *   software: inits threads and allocates buffers * * return value: 1 on success, 0 on error ******************************************************/static int lavplay_mjpeg_open(lavplay_t *info){#ifdef HAVE_SDL   int i;#endif   video_playback_setup *settings = (video_playback_setup *)info->settings;   EditList *editlist = info->editlist;   int max_frame_size = editlist->max_frame_size;   lavplay_msg(LAVPLAY_MSG_DEBUG, info,      "Initializing the %s", info->playback_mode=='S'?"threading system":"video device");   switch (info->playback_mode)   {#ifdef HAVE_V4L      case 'H':      case 'C':         /* open video device */         if ((settings->video_fd = open(info->video_dev, O_RDWR)) < 0)         {            lavplay_msg(LAVPLAY_MSG_ERROR, info,               "Error opening %s: %s", info->video_dev, strerror(errno));            return 0;         }         /* Request buffers */         settings->br.count = info->MJPG_numbufs;         if (max_frame_size < 140*1024) max_frame_size = 140*1024;         settings->br.size  = (max_frame_size + 4095)&~4095;         if (ioctl(settings->video_fd, MJPIOC_REQBUFS, &(settings->br)) < 0)         {            lavplay_msg(LAVPLAY_MSG_ERROR, info,               "Error requesting buffers: %s", strerror(errno));            return 0;         }         /* Map the buffers */         settings->buff = mmap(0, settings->br.count * settings->br.size,            PROT_READ | PROT_WRITE, MAP_SHARED, settings->video_fd, 0);         if (settings->buff == MAP_FAILED)         {            lavplay_msg(LAVPLAY_MSG_ERROR, info,               "Error mapping the video buffer: %s", strerror(errno));            return 0;         }         break;#endif#ifdef HAVE_SDL      case 'S':         /* Just allocate MJPG_nbuf buffers */         settings->br.count = info->MJPG_numbufs;         settings->br.size  = (max_frame_size*2 + 4095)&~4095;         settings->buff = (uint8_t *)malloc(settings->br.count * settings->br.size);         if (!settings->buff)         {            lavplay_msg (LAVPLAY_MSG_ERROR, info,               "Malloc error, you\'re probably out of memory");            return 0;         }         pthread_mutex_init(&(settings->valid_mutex), NULL);         pthread_mutex_init(&(settings->syncinfo_mutex), NULL);                /* Invalidate all buffers, and initialize the conditions */         for (i=0;i<MJPEG_MAX_BUF;i++)	 {            settings->valid[i] = 0;            pthread_cond_init(&(settings->buffer_filled[i]), NULL);            pthread_cond_init(&(settings->buffer_done[i]), NULL);            memset(&(settings->syncinfo[i]), 0, sizeof(struct mjpeg_sync));         }         /* Now do the thread magic */         settings->currently_processed_frame = 0;         settings->currently_processed_entry = -1;         settings->show_top = 1; /* start with top frames as default, change with mjpeg_set_params */                if (pthread_create(&(settings->software_playback_thread), NULL,             lavplay_mjpeg_playback_thread, (void *)info))         {            lavplay_msg(LAVPLAY_MSG_ERROR, info,               "Could not create software playback thread");            return 0;         }         break;#endif      default:         lavplay_msg(LAVPLAY_MSG_ERROR, info,            "lavplay_mjpeg_open(): Unknown playback mode (\'%c\')", info->playback_mode);         return 0;   }   settings->usec_per_frame = 0;   return 1;}/****************************************************** * lavplay_mjpeg_get_params() *   get default parameters * * return value: 1 on success, 0 on error ******************************************************/static int lavplay_mjpeg_get_params(lavplay_t *info, struct mjpeg_params *bp){#ifdef HAVE_SDL   int i;#endif#ifdef HAVE_V4L   video_playback_setup *settings = (video_playback_setup *)info->settings;#endif   /*EditList *editlist = info->editlist; */   switch (info->playback_mode)   {#ifdef HAVE_V4L      case 'H':      case 'C':         /* do a MJPIOC_G_PARAMS ioctl to get proper default values */         if (ioctl(settings->video_fd, MJPIOC_G_PARAMS, bp) < 0)         {            lavplay_msg(LAVPLAY_MSG_ERROR, info,               "Error getting video parameters: %s", strerror(errno));            return 0;         }         break;#endif#ifdef HAVE_SDL      case 'S':         /* Set some necessary params */         bp->decimation = 1;         bp->quality = 50; /* default compression factor 8 */         bp->odd_even = 1;         bp->APPn = 0;         bp->APP_len = 0; /* No APPn marker */         for(i=0;i<60;i++) bp->APP_data[i] = 0;         bp->COM_len = 0; /* No COM marker */         for(i=0;i<60;i++) bp->COM_data[i] = 0;         bp->VFIFO_FB = 1;         memset(bp->reserved,0,sizeof(bp->reserved));         break;#endif      default:         lavplay_msg(LAVPLAY_MSG_ERROR, info,            "lavplay_mjpeg_get_params(): Unknown playback mode (\'%c\')", info->playback_mode);         return 0;   }   return 1;}/****************************************************** * lavplay_mjpeg_set_params() *   set the parameters * * return value: 1 on success, 0 on error ******************************************************/static int lavplay_mjpeg_set_params(lavplay_t *info, struct mjpeg_params *bp){   video_playback_setup *settings = (video_playback_setup *)info->settings;   /*EditList *editlist = info->editlist; */  #ifdef HAVE_V4L   if (info->playback_mode == 'H') /* only when doing on-screen (hardware-decoded) output */   {      struct video_window vw;      struct video_capability vc;      int n, screenwidth, screenheight;#ifndef X_DISPLAY_MISSING      XWindowAttributes wts;      Display *dpy;      if (NULL == (dpy = XOpenDisplay(strchr(info->display, ':'))))      {         lavplay_msg(LAVPLAY_MSG_ERROR, info, "Can't open X11 display %s\n", info->display);         return 0;      }#endif      if (ioctl(settings->video_fd, VIDIOCGCAP, &vc) < 0)      {         lavplay_msg(LAVPLAY_MSG_ERROR, info,            "Error getting device capabilities: %s",

⌨️ 快捷键说明

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