Esempio n. 1
0
/* 可能是video,audio,local time                   */
static double get_master_clock(VideoState *is) {
	if(is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
		return get_video_clock(is);
	} else {
		return get_external_clock(is);
	}
}
Esempio n. 2
0
double get_master_clock(VideoState *is) {
	if(is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
		return get_video_clock(is);
	} else if(is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audioStream>0) {
		return get_audio_clock(is);
	} else {
		return get_external_clock(is);
	}
}
Esempio n. 3
0
double get_master_clock(VideoState *is) {
    double masterClock;
    if(is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
        masterClock = get_video_clock(is);
    } else if(is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
        masterClock = get_audio_clock(is);
    } else {
        masterClock = get_external_clock(is);
    }
    // fprintf(stderr, "---> get_master_clock: %.8f\n", masterClock);

    return masterClock;
}
Esempio n. 4
0
/* Must be called from the user thread. */
static void retrieve_picture(VideoState *is)
{
   VideoPicture *vp;
   int dst_pix_fmt;
   AVPicture pict;
   static struct SwsContext *img_convert_ctx;
   AVFrame *pFrame;
   
   if (!is->got_picture) return;

   vp = &is->pictq[is->pictq_windex];
   
   pFrame = vp->frame;
   
   if (!vp->bmp ||
       vp->width != is->video_st->codec->width ||
       vp->height != is->video_st->codec->height) {
       alloc_picture(is);
   }
   
   /* YUV->RGB conversion. */
   if (vp->bmp) {
      /* Don't waste CPU on an outdated frame. */
      if (get_video_clock(is) >= get_external_clock(is) - 0.25) {
         ALLEGRO_LOCKED_REGION *lock;
         lock = al_lock_bitmap(vp->bmp, 0, ALLEGRO_LOCK_WRITEONLY);

         dst_pix_fmt = PIX_FMT_RGB24;

         pict.data[0] = lock->data;
         pict.linesize[0] = lock->pitch;

         if (img_convert_ctx == NULL) {
            int w = is->video_st->codec->width;
            int h = is->video_st->codec->height;
            img_convert_ctx = sws_getContext(w, h,
                                             is->video_st->codec->pix_fmt, w, h,
                                             dst_pix_fmt, SWS_BICUBIC, NULL, NULL,
                                             NULL);
            if (img_convert_ctx == NULL) {
               ALLEGRO_ERROR("Cannot initialize the conversion context!\n");
               return;
            }
         }
         sws_scale(img_convert_ctx, (uint8_t const *const*)pFrame->data, pFrame->linesize,
                   0, is->video_st->codec->height, pict.data, pict.linesize);

         al_unlock_bitmap(vp->bmp);
      }
      else {
         vp->dropped = true;
      }
      //printf("[%d] %f %f %f %s\n", is->pictq_windex,
      //   vp->pts, get_video_clock(is), get_external_clock(is), vp->dropped ? "dropped" : "shown");

      if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE) {
         is->pictq_windex = 0;
      }
   }

   al_lock_mutex(is->pictq_mutex);
   is->pictq_size++;
   is->got_picture--;
   vp->allocated = 1;
   al_signal_cond(is->pictq_cond);
   al_unlock_mutex(is->pictq_mutex);
}
Esempio n. 5
0
static void video_refresh_timer(void *userdata)
{

   VideoState *is = (VideoState *) userdata;
   VideoPicture *vp;
   double actual_delay, delay, sync_threshold, ref_clock, diff;

   if (!is->first)
      return;
   if (!is->video_st)
      return;
   if (is->pictq_size == 0)
      return;
   if (is->paused) return;
   
   if (get_master_clock(is) < is->show_next) return;

   vp = &is->pictq[is->pictq_rindex];

   is->video_current_pts = vp->pts;
   is->video_current_pts_time = av_gettime();

   delay = vp->pts - is->frame_last_pts;        /* the pts from last time */
   if (delay <= 0 || delay >= 1.0) {
      /* if incorrect delay, use previous one */
      delay = is->frame_last_delay;
   }
   /* save for next time */
   is->frame_last_delay = delay;
   is->frame_last_pts = vp->pts;

   /* update delay to sync to audio if not master source */
   if (is->av_sync_type != AV_SYNC_VIDEO_MASTER) {
      ref_clock = get_master_clock(is);
      diff = vp->pts - ref_clock;

      /* Skip or repeat the frame. Take delay into account */
      sync_threshold = (delay > AV_SYNC_THRESHOLD) ? delay : AV_SYNC_THRESHOLD;
      if (fabs(diff) < AV_NOSYNC_THRESHOLD) {
         if (diff <= -sync_threshold) {
            delay = 0;
         }
         else if (diff >= sync_threshold) {
            delay = 2 * delay;
         }
      }
   }

   is->frame_timer += delay;
   /* computer the REAL delay */
   actual_delay = is->frame_timer - (av_gettime() / 1000000.0);

   if (!vp->dropped && vp->bmp) {
      is->video->current_frame = vp->bmp;
      
      /* Can be NULL or wrong size, will be (re-)allocated as needed. */
      vp->bmp = is->shown.bmp;
      /* That way it won't be overwritten. */
      is->shown.bmp = is->video->current_frame;

      is->video->position = get_master_clock(is);
      is->video->video_position = get_video_clock(is);
      is->video->audio_position = get_audio_clock(is);
      
      is->show_next = is->video->position + actual_delay;
      al_signal_cond(is->timer_cond);

      if (is->video_st->codec->sample_aspect_ratio.num == 0) {
         is->video->aspect_ratio = 0;
      }
      else {
         is->video->aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio) *
             is->video_st->codec->width / is->video_st->codec->height;
      }
      if (is->video->aspect_ratio <= 0.0) {
         is->video->aspect_ratio = (float)is->video_st->codec->width /
             (float)is->video_st->codec->height;
      }
   }
   else
      is->dropped_count++;
   
   //printf("[%d] %f %s\n", is->pictq_rindex,
   //   actual_delay, vp->dropped ? "dropped" : "shown");

   /* update queue for next picture! */
   if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE) {
      is->pictq_rindex = 0;
   }
   
   al_lock_mutex(is->pictq_mutex);
   is->pictq_size--;
   al_signal_cond(is->pictq_cond);
   al_unlock_mutex(is->pictq_mutex);

   /* We skipped a frame... let's grab more until we catch up. */
   if (actual_delay < 0)
      video_refresh_timer(userdata);
}