liblavplay.c

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

C
2,022
字号
      settings->yuvformat = (env? ((env[0])|(env[1]<<8)|(env[2]<<16)|(env[3]<<24)): SDL_YUY2_OVERLAY);      if (!info->sdl_width) info->sdl_width = editlist->video_width;      if (!info->sdl_height) info->sdl_height = editlist->video_height;      if (!lavplay_SDL_init(info))         return 0;      settings->yuvbuff[0] = (uint8_t *)malloc(editlist->video_width * editlist->video_height * 2);      if (!settings->yuvbuff[0])      {         lavplay_msg (LAVPLAY_MSG_ERROR, info,            "Malloc error, you\'re probably out of memory");         return 0;      }      settings->yuvbuff[1] = settings->yuvbuff[0] + (editlist->video_width * editlist->video_height);      settings->yuvbuff[2] = settings->yuvbuff[0] + (editlist->video_width * editlist->video_height * 3 / 2);# ifdef	HAVE_LIBDV      settings->decoder = dv_decoder_new(0,0,0);      settings->decoder->quality = DV_QUALITY_BEST;# endif   }#endif   if (editlist->has_audio && info->audio)   {      if (audio_init(0, 0, (editlist->audio_chans>1), editlist->audio_bits,         editlist->audio_rate)) /* increase this last argument to test sync */      {         lavplay_msg(LAVPLAY_MSG_ERROR, info,            "Error initializing Audio: %s",audio_strerror());         return 0;      }      settings->audio_buffer_size = audio_get_buffer_size();   }   /* After we have fired up the audio and video threads system (which    * are assisted if we're installed setuid root, we want to set the    * effective user id to the real user id    */   if(seteuid(getuid()) < 0)   {      lavplay_msg(LAVPLAY_MSG_ERROR, info,         "Can't set effective user-id: %s", strerror(errno));      return 0;   }   /* Fill all buffers first */   for(nqueue=0;nqueue<settings->br.count;nqueue++)   {      if (!lavplay_queue_next_frame(info, settings->buff+nqueue* settings->br.size,				    (settings->data_format[nqueue] =				     el_video_frame_data_format(settings->current_frame_num, editlist)),				    0,0,0)) break;   }   /* Choose the correct parameters for playback */   if (!lavplay_mjpeg_get_params(info, &bp))      return 0;   /* set options */   bp.input = 0;   bp.norm = (editlist->video_norm == 'n') ? VIDEO_MODE_NTSC : VIDEO_MODE_PAL;   lavplay_msg(LAVPLAY_MSG_INFO, info,      "Output norm: %s", bp.norm==VIDEO_MODE_NTSC?"NTSC":"PAL");   hn = bp.norm==VIDEO_MODE_NTSC?480:576; /* Height of norm */   if (info->playback_mode != 'S')   {#ifdef HAVE_V4L      /* set correct width of device for hardware       * DC10(+): 768 (PAL/SECAM) or 640 (NTSC), Buz/LML33: 720       */      if (ioctl(settings->video_fd, VIDIOCGCAP, &vc) < 0)      {         lavplay_msg(LAVPLAY_MSG_ERROR, info,            "Error getting device capabilities: %s", strerror(errno));         return 0;      }      /* vc.maxwidth is often reported wrong - let's just keep it broken (sigh) */      if (vc.maxwidth != 768 && vc.maxwidth != 640) vc.maxwidth = 720;      bp.decimation = 0; /* we will set proper params ourselves later on */      if (editlist->video_width > vc.maxwidth || editlist->video_height > hn )      {         /* the video is too big */         lavplay_msg(LAVPLAY_MSG_ERROR, info,            "Video dimensions too large: %ld x %ld, device max = %dx%d",            editlist->video_width, editlist->video_height, vc.maxwidth, hn);         return 0;      }      /* if zoom_to_fit is set, HorDcm is independent of interlacing */      if (info->zoom_to_fit)      {         if (editlist->video_width <= vc.maxwidth/4 )            bp.HorDcm = 4;         else if (editlist->video_width <= vc.maxwidth/2)            bp.HorDcm = 2;         else            bp.HorDcm = 1;      }      if (editlist->video_inter)      {         /* Interlaced video, 2 fields per buffer */         bp.field_per_buff = 2;         bp.TmpDcm = 1;         if (info->zoom_to_fit)         {            if (editlist->video_height <= hn/2)               bp.VerDcm = 2;            else               bp.VerDcm = 1;         }         else         {            /* if zoom_to_fit is not set, we always use decimation 1 */            bp.HorDcm = 1;            bp.VerDcm = 1;         }      }      else      {         /* Not interlaced, 1 field per buffer */         bp.field_per_buff = 1;         bp.TmpDcm = 2;         if (editlist->video_height > hn/2 ||            (!info->zoom_to_fit && editlist->video_width > vc.maxwidth/2))         {            lavplay_msg(LAVPLAY_MSG_ERROR, info,               "Video dimensions (not interlaced) too large: %ld x %ld",               editlist->video_width, editlist->video_height);            if (editlist->video_width > vc.maxwidth/2)                lavplay_msg(LAVPLAY_MSG_ERROR, info,               "Try using the \'zoom-to-fit\'-option");            return 0;         }         if(info->zoom_to_fit)         {            if (editlist->video_height <= hn/4 )               bp.VerDcm = 2;            else               bp.VerDcm = 1;         }         else         {            /* the following is equivalent to decimation 2 in lavrec: */            bp.HorDcm = 2;            bp.VerDcm = 1;         }      }      /* calculate height, width and offsets from the above settings */      bp.quality = 100;      bp.img_width  = bp.HorDcm * editlist->video_width;      bp.img_height = bp.VerDcm * editlist->video_height/bp.field_per_buff;      if (info->horizontal_offset == VALUE_NOT_FILLED)         bp.img_x = (vc.maxwidth - bp.img_width)/2;      else         bp.img_x = info->horizontal_offset;      if (info->vertical_offset == VALUE_NOT_FILLED)         bp.img_y = (hn/2 - bp.img_height)/2;      else         bp.img_y = info->vertical_offset/2;      lavplay_msg(LAVPLAY_MSG_INFO, info,         "Output dimensions: %dx%d+%d+%d",         bp.img_width, bp.img_height*2, bp.img_x, bp.img_y*2);      lavplay_msg(LAVPLAY_MSG_INFO, info,         "Output zoom factors: %d (hor) %d (ver)",         bp.HorDcm,bp.VerDcm*bp.TmpDcm);#else      fprintf(stderr, "No video4linux support!\n");      return 0;#endif   }#ifdef HAVE_SDL   else   {      /* software playback */      lavplay_msg(LAVPLAY_MSG_INFO, info,         "Output dimensions: %ldx%ld",         editlist->video_width, editlist->video_height);   }#endif      /* Set field polarity for interlaced video */   bp.odd_even = (editlist->video_inter==LAV_INTER_TOP_FIRST);   /*if (info->exchange_fields) bp.odd_even = !bp.odd_even; */   /*this is already done by the open_files() function */   /* Set these settings */   if (!lavplay_mjpeg_set_params(info, &bp))      return 0;   if (!lavplay_mjpeg_set_playback_rate(info, editlist->video_fps,       editlist->video_norm=='p'?0:1))      return 0;   return 1;}/****************************************************** * lavplay_playback_cycle() *   the playback cycle ******************************************************/static void lavplay_playback_cycle(lavplay_t *info){   video_playback_stats stats;   video_playback_setup *settings = (video_playback_setup *)info->settings;   EditList *editlist = info->editlist;   struct mjpeg_sync bs;   struct timeval audio_tmstmp;   struct timeval time_now;   double tdiff1, tdiff2;   int n;   int first_free, frame, skipv, skipa, skipi, nvcorr;   long frame_number[256]; /* Must be at least as big as the number of buffers used */   stats.stats_changed = 0;   stats.num_corrs_a = 0;   stats.num_corrs_b = 0;   stats.nqueue = 0;   stats.nsync = 0;   stats.audio = 0;   stats.norm = editlist->video_norm=='n'?1:0;   tdiff1 = 0.;   tdiff2 = 0.;   nvcorr = 0;   /* Queue the buffers read, this triggers video playback */   if (editlist->has_audio && info->audio)   {      audio_start();      stats.audio = 1;   }   for(n=0;n<settings->br.count;n++) /* TODO: maybe br.count-1? */   {      frame_number[n] = settings->current_frame_num;      lavplay_mjpeg_queue_buf(info, n, 1);   }   stats.nqueue = settings->br.count;   while (settings->state != LAVPLAY_STATE_STOP)   {      /* Sync to get a free buffer. We want to have all free buffers,       * which have been played so far. Normally there should be a function       * in the kernel API to get the number of all free buffers.       * I don't want to change this API at the moment, therefore       * we look on the clock to see if there are more buffers ready       */      first_free = stats.nsync;      do      {         if (settings->state == LAVPLAY_STATE_STOP)            goto FINISH;         if (!lavplay_mjpeg_sync_buf(info, &bs))         {            lavplay_change_state(info, LAVPLAY_STATE_STOP);            goto FINISH;         }         frame = bs.frame;         /* Since we queue the frames in order, we have to get them back in order */         if (frame != stats.nsync % settings->br.count)         {            lavplay_msg(LAVPLAY_MSG_ERROR, info,               "**INTERNAL ERROR: Bad frame order on sync: frame = %d, nsync = %d, br.count = %ld",               frame, stats.nsync, settings->br.count);            lavplay_change_state(info, LAVPLAY_STATE_STOP);            goto FINISH;         }         stats.nsync++;         /* Look on clock */         gettimeofday(&time_now, 0);         stats.tdiff = time_now.tv_sec - bs.timestamp.tv_sec +            (time_now.tv_usec - bs.timestamp.tv_usec)*1.e-6;      }      while (stats.tdiff > settings->spvf && (stats.nsync - first_free) < settings->br.count - 1);      if ((stats.nsync - first_free) > settings->br.count - 3)         lavplay_msg(LAVPLAY_MSG_WARNING, info,            "Disk too slow, can not keep pace!");      if (editlist->has_audio && info->audio)      {         audio_get_output_status(&audio_tmstmp, &(stats.num_asamps), &(stats.num_aerr));         if (audio_tmstmp.tv_sec)         {            tdiff1 = settings->spvf * (stats.nsync - nvcorr) -               settings->spas * settings->audio_buffer_size / editlist->audio_bps * stats.num_asamps;            tdiff2 = (bs.timestamp.tv_sec - audio_tmstmp.tv_sec) +               (bs.timestamp.tv_usec - audio_tmstmp.tv_usec) * 1.e-6;         }      }      stats.tdiff = tdiff1 - tdiff2;      /* Fill and queue free buffers again */      for (n=first_free;n<stats.nsync;)      {         /* Audio/Video sync correction */         skipv = 0;         skipa = 0;         skipi = 0;         if (info->sync_correction)         {            if (stats.tdiff > settings->spvf)            {               /* Video is ahead audio */               skipa = 1;               if (info->sync_ins_frames) skipi = 1;               nvcorr++;               stats.num_corrs_a++;               stats.tdiff -= settings->spvf;               stats.stats_changed = 1;            }            if (stats.tdiff < -settings->spvf)            {               /* Video is behind audio */               skipv = 1;               if (!info->sync_skip_frames) skipi = 1;               nvcorr--;               stats.num_corrs_b++;               stats.tdiff += settings->spvf;               stats.stats_changed = 1;            }         }         /* Read one frame, break if EOF is reached */         frame = n % settings->br.count;         frame_number[frame] = settings->current_frame_num;#ifdef HAVE_SDL	 settings->buffer_entry[frame] = editlist->frame_list[settings->current_frame_num];#endif         if (!lavplay_queue_next_frame(info, settings->buff+frame*settings->br.size,				       (settings->data_format[frame] =					el_video_frame_data_format(settings->current_frame_num, editlist)),				       skipv,skipa,skipi))         {            lavplay_change_state(info, LAVPLAY_STATE_STOP);            goto FINISH;         }         if (skipv) continue; /* no frame has been read */         /* Queue the frame */         if (!lavplay_mjpeg_queue_buf(info, frame, 1))         {            lavplay_change_state(info, LAVPLAY_STATE_STOP);            goto FINISH;         }         stats.nqueue++;         n++;      }      /* output statistics */      if (editlist->has_audio && info->audio) stats.audio = settings->audio_mute?0:1;      stats.play_speed = settings->current_playback_speed;      stats.frame = settings->current_frame_num;      if (info->output_statistics)         info->output_statistics(&stats);      stats.stats_changed = 0;   }FINISH:   /* All buffers are queued, sync on the outstanding buffers    * Never try to sync on the last buffer, it is a hostage of    * the codec since it is played over and over again    */   /* NOTE: this causes lockup for some reason - so just leave it */   /*while (stats.nqueue > stats.nsync + 1) */   /*{ */   /*   lavplay_mjpeg_sync_buf(info, &bs); */   /*   stats.nsync++; */   /*} */   /* and we also don't need audio anymore */   if (editlist->has_audio && info->audio)       audio_shutdown();}/****************************************************** * lavplay_playback_thread() *   The main playback thread ******************************************************/st

⌨️ 快捷键说明

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