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); }
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); }
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);*/ }
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); }
static void fooviz_dispose(post_plugin_t *this_gen) { post_plugin_fooviz_t *this = (post_plugin_fooviz_t *)this_gen; xine_post_out_t *output = (xine_post_out_t *)xine_list_last_content(this_gen->output); xine_video_port_t *port = *(xine_video_port_t **)output->data; if (this->stream) port->close(port, this->stream); free(this->post.xine_post.audio_input); free(this->post.xine_post.video_input); free(xine_list_first_content(this->post.input)); free(xine_list_first_content(this->post.output)); xine_list_free(this->post.input); xine_list_free(this->post.output); if(this->buf.mem) free(this->buf.mem); free(this); }
xine_event_t *xine_event_get (xine_event_queue_t *queue) { xine_event_t *event; pthread_mutex_lock (&queue->lock); event = (xine_event_t *) xine_list_first_content (queue->events); if (event) xine_list_delete_current (queue->events); pthread_mutex_unlock (&queue->lock); return event; }
xine_event_t *xine_event_wait (xine_event_queue_t *queue) { xine_event_t *event; pthread_mutex_lock (&queue->lock); while (!(event = (xine_event_t *) xine_list_first_content (queue->events))) { pthread_cond_wait (&queue->new_event, &queue->lock); } xine_list_delete_current (queue->events); pthread_mutex_unlock (&queue->lock); return event; }
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); }
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; }
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; }