Пример #1
0
void xine_event_send (xine_stream_t *stream, const xine_event_t *event) {

  xine_event_queue_t *queue;

  pthread_mutex_lock (&stream->event_queues_lock);

  queue = (xine_event_queue_t *)xine_list_first_content (stream->event_queues);

  while (queue) {
    
    xine_event_t *cevent;

    cevent = malloc (sizeof (xine_event_t));
    cevent->type        = event->type;
    cevent->stream      = stream;
    cevent->data_length = event->data_length;
    if ((event->data_length > 0) && (event->data) ) {
      cevent->data = malloc (event->data_length);
      memcpy (cevent->data, event->data, event->data_length);
    } else {
      cevent->data = NULL;
    }
    gettimeofday (&cevent->tv, NULL);
    
    pthread_mutex_lock (&queue->lock);
    xine_list_append_content (queue->events, cevent);
    pthread_cond_signal (&queue->new_event);
    pthread_mutex_unlock (&queue->lock);

    queue=(xine_event_queue_t *)xine_list_next_content (stream->event_queues);
  }

  pthread_mutex_unlock (&stream->event_queues_lock);
}
Пример #2
0
void xine_cue_point_event(xine_stream_t *stream, int64_t in_cur_time) {
   xine_event_t event;
   int next_time;
   int cur_time;
   int next_freq;
   xine_cue_point_data_t *cue_point;

   event.type=XINE_EVENT_CUE_POINT;
   event.data_length=sizeof(xine_cue_point_data_t);
   cur_time=(in_cur_time-stream->metronom->vpts_offset)/90;
   next_time=stream->org_next_cue_time;
   if (cur_time<next_time) return;
   pthread_mutex_lock (&stream->cue_points_lock);
   cue_point = (xine_cue_point_data_t *) xine_list_first_content(stream->cue_points);
   while (cue_point) {
      if (cue_point->cuetime<=cur_time && cue_point->cuetime>=next_time) {
         event.data=cue_point;
         cue_point->currtime=cur_time;
         xine_event_send(stream,&event);
      } else {
         next_freq=cue_point->frequency-((next_time-cue_point->cuetime) % cue_point->frequency);
         if (next_freq==cue_point->frequency) next_freq=0;
/*         printf("%d, %d, %d\n",next_time,next_freq,(cur_time-next_time));*/
         if (cue_point->frequency!=0 && cue_point->cuetime<cur_time && (next_freq<=(cur_time-next_time))) {
            event.data=cue_point;
            cue_point->currtime=cur_time;
            xine_event_send(stream,&event);
         }
      }
      cue_point = (xine_cue_point_data_t *) xine_list_next_content(stream->cue_points);
   }
   pthread_mutex_unlock (&stream->cue_points_lock);
   xine_recalculate_next_cue_point(stream,in_cur_time);
}
Пример #3
0
void xine_recalculate_next_cue_point(xine_stream_t *stream, int64_t cur_time) {
   xine_cue_point_data_t *cue_point;
   int next_time=0x7FFFFFFF;

   if (cur_time==0) {
      cur_time=stream->xine->clock->get_current_time(stream->xine->clock);
   } 
   cur_time=(cur_time-stream->metronom->vpts_offset)/90;
   
   pthread_mutex_lock (&stream->cue_points_lock);
   cue_point = (xine_cue_point_data_t *) xine_list_first_content (stream->cue_points);

   while (cue_point) {
      if (cue_point->cuetime>cur_time && cue_point->cuetime<next_time) {
         next_time=cue_point->cuetime;
         stream->next_cue_data=cue_point;
      } else {
         if (cue_point->frequency!=0 && cue_point->cuetime<cur_time && (cue_point->frequency-((cur_time-cue_point->cuetime) % cue_point->frequency))<(next_time-cur_time)) {
            next_time=(cue_point->frequency-((cur_time-cue_point->cuetime) % cue_point->frequency))+cur_time;
            stream->next_cue_data=cue_point;
         }
      } /* endif */
      cue_point = (xine_cue_point_data_t *) xine_list_next_content (stream->cue_points);
   }
   pthread_mutex_unlock (&stream->cue_points_lock);
   stream->next_cue_time=(next_time*90)+stream->metronom->vpts_offset;
/*   printf("Now: %Ld Next Cue: %d\n",cur_time,next_time);*/
}
Пример #4
0
void xine_event_dispose_queue (xine_event_queue_t *queue) {

  xine_stream_t      *stream = queue->stream;
  xine_event_t       *event;
  xine_event_t       *qevent;
  xine_event_queue_t *q;
    
  pthread_mutex_lock (&stream->event_queues_lock);

  q = (xine_event_queue_t *) xine_list_first_content (stream->event_queues);

  while (q && (q != queue))
    q = (xine_event_queue_t *) xine_list_next_content (stream->event_queues);

  if (!q) {
    printf ("events: tried to dispose queue which is not in list\n");

    pthread_mutex_unlock (&stream->event_queues_lock);
    return;
  }

  xine_list_delete_current (stream->event_queues);
  pthread_mutex_unlock (&stream->event_queues_lock);

  /* 
   * send quit event 
   */
  qevent = (xine_event_t *)malloc(sizeof(xine_event_t));
  
  qevent->type        = XINE_EVENT_QUIT;
  qevent->stream      = stream;
  qevent->data        = NULL;
  qevent->data_length = 0;
  
  pthread_mutex_lock (&queue->lock);
  xine_list_append_content (queue->events, qevent);
  pthread_cond_signal (&queue->new_event);
  pthread_mutex_unlock (&queue->lock);

  /*
   * join listener thread, if any
   */
  
  if (queue->listener_thread) {
    void *p;
    pthread_join (*queue->listener_thread, &p);
    free (queue->listener_thread);
  }
  
  /*
   * clean up pending events 
   */

  while ( (event = xine_event_get (queue)) ) {
    xine_event_free (event);
  }

  free (queue);
}
Пример #5
0
void xine_event_dispose_cue_point(xine_stream_t *stream, int cuetime, 
                   int frequency) {
   xine_cue_point_data_t *cue_point;

   pthread_mutex_lock (&stream->cue_points_lock);

   cue_point = (xine_cue_point_data_t *) xine_list_first_content (stream->cue_points);

   while (cue_point && ((cue_point->cuetime!=cuetime) ||(cue_point->frequency!=frequency)))
      cue_point = (xine_cue_point_data_t *) xine_list_next_content (stream->cue_points);

   xine_list_delete_current (stream->cue_points);
   pthread_mutex_unlock (&stream->cue_points_lock);

   free(cue_point);
}
Пример #6
0
gboolean
gst_xine_input_init_plugin (GstPlugin * plugin)
{
  GTypeInfo plugin_info = {
    sizeof (GstXineInputClass),
    NULL,
    NULL,
    gst_xine_input_subclass_init,
    NULL,
    NULL,
    sizeof (GstXineInput),
    0,
    gst_xine_input_sub_init,
  };
  plugin_node_t *node;
  GstXineClass *klass;

  klass = g_type_class_ref (GST_TYPE_XINE);

  node = xine_list_first_content (klass->xine->plugin_catalog->input);
  while (node) {
    gchar *plugin_name = g_strdup_printf ("xinesrc_%s", node->info->id);
    gchar *type_name = g_strdup_printf ("GstXineInput%s", node->info->id);
    GType type;

    plugin_info.class_data = node;
    type =
        g_type_register_static (GST_TYPE_XINE_INPUT, type_name, &plugin_info,
        0);
    g_free (type_name);
    if (!gst_element_register (plugin, plugin_name, GST_RANK_MARGINAL, type)) {
      g_free (plugin_name);
      return FALSE;
    }
    g_free (plugin_name);

    node = xine_list_next_content (klass->xine->plugin_catalog->input);
  }

  g_type_class_unref (klass);
  return TRUE;
}
Пример #7
0
static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) {

  vos_t         *this = (vos_t *) img->port;
  int64_t        diff;
  int64_t        cur_vpts;
  int64_t        pic_vpts ;
  int            frames_to_skip;

  img->stream = stream;
  extra_info_merge( img->extra_info, stream->video_decoder_extra_info );
  this->current_width = img->width;
  this->current_height = img->height;
  
  stream->metronom->got_video_frame (stream->metronom, img);
  this->current_duration = img->duration;

  if (!this->grab_only) {

    pic_vpts = img->vpts;
    img->extra_info->vpts = img->vpts;

    cur_vpts = this->clock->get_current_time(this->clock);
    this->last_delivery_pts = cur_vpts;

#ifdef LOG
    printf ("video_out: got image at master vpts %lld. vpts for picture is %lld (pts was %lld)\n",
	    cur_vpts, pic_vpts, img->pts);
#endif

    this->num_frames_delivered++;

    diff = pic_vpts - cur_vpts;
    /* avoid division by zero */
    if( img->duration <= 0 )
      img->duration = 3000;
    
    /* Frame dropping slow start:
     *   The engine starts to drop frames if there is less than frame_drop_limit
     *   frames in advance. There might be a problem just after a seek because
     *   there is no frame in advance yet.
     *   The following code increases progressively the frame_drop_limit (-2 -> 3)
     *   after a seek to give a chance to the engine to display the first frames
     *   smootly before starting to drop frames if the decoder is really too
     *   slow.
     */
    if (stream->first_frame_flag == 2)
      this->frame_drop_cpt = 10;

    if (this->frame_drop_cpt) {
      this->frame_drop_limit = 3 - (this->frame_drop_cpt / 2);
      this->frame_drop_cpt--;
    }
    frames_to_skip = ((-1 * diff) / img->duration + this->frame_drop_limit) * 2;

    if (frames_to_skip<0)
      frames_to_skip = 0;
  } else {
    frames_to_skip = 0;

    if (this->discard_frames) {
#ifdef LOG
      printf ("video_out: i'm in flush mode, not appending this frame to queue\n");
#endif
      return 0;
    }
  }


#ifdef LOG
  printf ("video_out: delivery diff : %lld, current vpts is %lld, %d frames to skip\n",
	  diff, cur_vpts, frames_to_skip);
#endif

  if (!img->bad_frame) {

    /* do not call proc_*() for frames that will be dropped */
    if( !frames_to_skip && !img->proc_called )
      vo_frame_driver_proc(img);
    
    /*
     * put frame into FIFO-Buffer
     */

#ifdef LOG
    printf ("video_out: frame is ok => appending to display buffer\n");
#endif

    /*
     * check for first frame after seek and mark it
     */
    img->is_first = 0;
    pthread_mutex_lock(&this->streams_lock);
    for (stream = xine_list_first_content(this->streams); stream;
         stream = xine_list_next_content(this->streams)) {
      pthread_mutex_lock (&stream->first_frame_lock);
      if (stream->first_frame_flag == 2) {
        stream->first_frame_flag = (this->grab_only)?0:1;
        img->is_first = 1;
#ifdef LOG
        printf ("video_out: get_next_video_frame first_frame_reached\n");
#endif
      }
      pthread_mutex_unlock (&stream->first_frame_lock);
    }
    pthread_mutex_unlock(&this->streams_lock);

    vo_frame_inc_lock( img );
    vo_append_to_img_buf_queue (this->display_img_buf_queue, img);

  } else {
#ifdef LOG
    printf ("video_out: bad_frame\n");
#endif
    pthread_mutex_lock( &stream->current_extra_info_lock );
    extra_info_merge( stream->current_extra_info, img->extra_info );
    pthread_mutex_unlock( &stream->current_extra_info_lock );

    this->num_frames_skipped++;
  }

  /*
   * performance measurement
   */

  if ((this->num_frames_delivered % 200) == 0 && this->num_frames_delivered) {
    int send_event;

    if( (100 * this->num_frames_skipped / this->num_frames_delivered) >
         this->warn_skipped_threshold ||
        (100 * this->num_frames_discarded / this->num_frames_delivered) >
         this->warn_discarded_threshold )
      this->warn_threshold_exceeded++;
    else
      this->warn_threshold_exceeded = 0;

    /* make sure threshold has being consistently exceeded - 5 times in a row
     * (that is, this is not just a small burst of dropped frames).
     */
    send_event = (this->warn_threshold_exceeded == 5 && 
                  !this->warn_threshold_event_sent);
    this->warn_threshold_event_sent += send_event;

    pthread_mutex_lock(&this->streams_lock);
    for (stream = xine_list_first_content(this->streams); stream;
         stream = xine_list_next_content(this->streams)) {
      stream->stream_info[XINE_STREAM_INFO_SKIPPED_FRAMES] =
        1000 * this->num_frames_skipped / this->num_frames_delivered;
      stream->stream_info[XINE_STREAM_INFO_DISCARDED_FRAMES] =
        1000 * this->num_frames_discarded / this->num_frames_delivered;

      /* we send XINE_EVENT_DROPPED_FRAMES to frontend to warn that
       * number of skipped or discarded frames is too high.
       */
      if( send_event ) {
         xine_event_t          event;
         xine_dropped_frames_t data;

         event.type        = XINE_EVENT_DROPPED_FRAMES;
         event.stream      = stream;
         event.data        = &data;
         event.data_length = sizeof(data);
         data.skipped_frames = stream->stream_info[XINE_STREAM_INFO_SKIPPED_FRAMES];
         data.skipped_threshold = this->warn_skipped_threshold * 10;
         data.discarded_frames = stream->stream_info[XINE_STREAM_INFO_DISCARDED_FRAMES];
         data.discarded_threshold = this->warn_discarded_threshold * 10;
         xine_event_send(stream, &event);
      }
    }
    pthread_mutex_unlock(&this->streams_lock);


    if( this->num_frames_skipped || this->num_frames_discarded ) {
      xine_log(this->xine, XINE_LOG_MSG,
	       _("%d frames delivered, %d frames skipped, %d frames discarded\n"), 
	       this->num_frames_delivered, 
	       this->num_frames_skipped, this->num_frames_discarded);
    }

    this->num_frames_delivered = 0;
    this->num_frames_discarded = 0;
    this->num_frames_skipped   = 0;
  }
  
  return frames_to_skip;
}