diff options
Diffstat (limited to 'src/xine-engine/video_out.c')
-rw-r--r-- | src/xine-engine/video_out.c | 137 |
1 files changed, 115 insertions, 22 deletions
diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index d3b354ce6..aaa02bf4d 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out.c,v 1.30 2001/07/04 20:32:29 uid32519 Exp $ + * $Id: video_out.c,v 1.31 2001/07/08 18:15:54 guenter Exp $ * */ @@ -140,13 +140,14 @@ static void *video_out_loop (void *this_gen) { uint32_t cur_pts; int pts_absdiff, diff, absdiff, pts=0; vo_frame_t *img; + vo_overlay_t *overlay; + int count; uint32_t video_step, video_step_new; vo_instance_t *this = (vo_instance_t *) this_gen; sigset_t vo_mask; /* int dummysignum; */ - /* struct timespec ts; */ /* printf ("%d video_out start\n", getpid()); */ /* @@ -173,34 +174,26 @@ static void *video_out_loop (void *this_gen) { #endif video_step = this->metronom->get_video_rate (this->metronom); - - /* - ts.tv_sec = 0; - ts.tv_nsec = video_step * 2000 / 9; - */ - vo_set_timer (video_step); while (this->video_loop_running) { /* sigwait(&vo_mask, &dummysignum); */ /* wait for next timer tick */ - pause (); - /* nanosleep (&ts, NULL); */ video_step_new = this->metronom->get_video_rate (this->metronom); if (video_step_new != video_step) { video_step = video_step_new; vo_set_timer (video_step); - /* ts.tv_nsec = video_step * 2000 / 9; */ } - pts_absdiff = 1000000; cur_pts = this->metronom->get_current_time (this->metronom); xprintf (VERBOSE|VIDEO, "video_out : video loop iteration at audio pts %d\n", cur_pts); + /*printf ("video_out : video loop iteration at audio pts %d\n", cur_pts); + fflush (stdout); */ img = this->display_img_buf_queue->first; @@ -253,6 +246,11 @@ static void *video_out_loop (void *this_gen) { * time to display frame 0 ? */ + /* + printf ("video_out: diff %d\n", diff); + fflush(stdout); + */ + if (diff<0) { continue; } @@ -277,7 +275,60 @@ static void *video_out_loop (void *this_gen) { pthread_mutex_unlock (&img->mutex); xprintf (VERBOSE|VIDEO, "video_out : passing to video driver, image with pts = %d\n", pts); + + overlay=this->first_overlay; + while (overlay) { + if(overlay->state==OVERLAY_SHOWING) { + this->driver->overlay_blend (img,overlay); + } + overlay=overlay->next; + } this->driver->display_frame (this->driver, img); + + /* Control Overlay SHOW/HIDE based on PTS */ + /* FIXME: Not implemented: These all need to be put to FREE state if the slider gets moved or STOP is pressed. */ + overlay=this->first_overlay; + count=1; + while (overlay) { + count++; + switch(overlay->state) { + case OVERLAY_FREE: + break; + case OVERLAY_CREATING: + break; + case OVERLAY_READY_TO_SHOW: + if (cur_pts>overlay->PTS) overlay->state=OVERLAY_SHOWING; + if (abs(cur_pts-overlay->PTS) > pts_absdiff ) overlay->state=OVERLAY_READY_TO_FREE; + break; + case OVERLAY_SHOWING: + /* duration is in frames, Who knows why div 4 ? */ + if ((cur_pts>overlay->PTS+(overlay->duration*video_step/4))) overlay->state=OVERLAY_READY_TO_FREE; + break; + case OVERLAY_READY_TO_FREE: + /* remove overlay from list */ + if (overlay->next) { + if (overlay->priv) + overlay->priv->next=overlay->next; + else + this->first_overlay=overlay->next; + overlay->next->priv=overlay->priv; + } else { + overlay->state=OVERLAY_FREE; + break; + } + /* Set status to free */ + overlay->state=OVERLAY_FREE; + /* Insert at end of list */ + overlay->priv=this->last_overlay; + this->last_overlay->next=overlay; + overlay->next=NULL; + this->last_overlay=overlay; + break; + default: + printf("OVERLAY in UNKNOWN state\n"); + } + overlay=overlay->next; + } } /* @@ -326,6 +377,7 @@ static vo_frame_t *vo_get_frame (vo_instance_t *this, /* printf ("video_out: get_frame %d x %d from queue %d\n", width, height, this->free_img_buf_queue); + fflush(stdout); */ if (this->pts_per_frame != duration) { @@ -416,14 +468,16 @@ static int vo_frame_draw (vo_frame_t *img) { int frames_to_skip; pic_vpts = this->metronom->got_video_frame (this->metronom, img->PTS); + + /* + printf ("video_out: got image %d. vpts for picture is %d (pts was %d)\n", + img, pic_vpts, img->PTS); + */ img->PTS = pic_vpts; this->num_frames_delivered++; xprintf (VERBOSE|VIDEO,"video_out: got image. vpts for picture is %d\n", pic_vpts); - /* - printf ("video_out: got image %d. vpts for picture is %d\n", - img, pic_vpts); - */ + cur_vpts = this->metronom->get_current_time(this->metronom); diff = pic_vpts - cur_vpts; @@ -489,15 +543,54 @@ static int vo_frame_draw (vo_frame_t *img) { return frames_to_skip; } +/**************************************************************** + * Current assumption is that only one thread will call vo_get_overlay at a time + * Also mutex locks have not yet been considered or used + * Also, when one is FREEed, it is moved to the end of the queue, so it will be the first one used + * The design is based around a dynamic buffer size. + * The buffer starts at nothing, then increases as needed. + * If a buffer entry is free, it will be reused. + * If all buffers are full, xmalloc is called. + * FIXME: Can someone make this simpler ? It seems a bit long winded to me. + ***************************************************************/ static vo_overlay_t *vo_get_overlay (vo_instance_t *this) { - /* FIXME: implement */ - return this->overlay; + vo_overlay_t *next_overlay; + vo_overlay_t *prev_overlay; + int count_overlay=0; + if (this->first_overlay==NULL) { + this->first_overlay = this->last_overlay = xmalloc (sizeof (vo_overlay_t)) ; + this->first_overlay->data=NULL; + this->first_overlay->next=NULL; + this->first_overlay->priv=NULL; + this->first_overlay->state=OVERLAY_CREATING; + count_overlay++; + return this->first_overlay; + } + prev_overlay=this->first_overlay; + next_overlay=this->first_overlay->next; + while (next_overlay && (prev_overlay->state!=OVERLAY_FREE)) { + count_overlay++; + prev_overlay=next_overlay; + next_overlay=prev_overlay->next; + } + if (prev_overlay->state==OVERLAY_FREE) { + prev_overlay->state=OVERLAY_CREATING; + return prev_overlay; + } + prev_overlay->next = next_overlay = this->last_overlay = xmalloc (sizeof (vo_overlay_t)) ; + count_overlay++; + next_overlay->data=NULL; + next_overlay->next=NULL; + next_overlay->priv=prev_overlay; + next_overlay->state=OVERLAY_CREATING; + return next_overlay; } static void vo_queue_overlay (vo_instance_t *this, vo_overlay_t *overlay) { - /* FIXME: implement */ - this->driver->set_overlay (this->driver, overlay); + overlay->PTS = this->metronom->got_spu_packet (this->metronom, overlay->PTS,overlay->duration); + if (overlay->data==NULL) overlay->state=OVERLAY_FREE; + else overlay->state=OVERLAY_READY_TO_SHOW; } vo_instance_t *vo_new_instance (vo_driver_t *driver, metronom_t *metronom) { @@ -506,8 +599,8 @@ vo_instance_t *vo_new_instance (vo_driver_t *driver, metronom_t *metronom) { int i; this = xmalloc (sizeof (vo_instance_t)) ; - this->overlay = xmalloc (sizeof (vo_overlay_t)) ; - + this->first_overlay=NULL; + this->last_overlay=NULL; this->driver = driver; this->metronom = metronom; |