diff options
author | Alfred E. Heggestad <alfred.heggestad@gmail.com> | 2018-04-08 18:10:30 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-08 18:10:30 +0200 |
commit | 02bb5304bebbf4fdf0206f8628c81dab464a79ac (patch) | |
tree | 80c3fda138c96b0dcc76135bbf36134af1c0252b /modules | |
parent | b3bd9972e0633451eecff834297d3cc139d69b4b (diff) | |
parent | 09c1b0287be9a7c33dffb11d2bad9286142be3a2 (diff) |
vidsrc: add timestamp to the frame API (#368)
Diffstat (limited to 'modules')
-rw-r--r-- | modules/avcapture/avcapture.m | 6 | ||||
-rw-r--r-- | modules/avformat/avformat.c | 10 | ||||
-rw-r--r-- | modules/cairo/cairo.c | 19 | ||||
-rw-r--r-- | modules/fakevideo/fakevideo.c | 6 | ||||
-rw-r--r-- | modules/rst/video.c | 6 | ||||
-rw-r--r-- | modules/v4l/v4l.c | 11 | ||||
-rw-r--r-- | modules/v4l2/v4l2.c | 13 | ||||
-rw-r--r-- | modules/vidbridge/src.c | 11 | ||||
-rw-r--r-- | modules/vidbridge/vidbridge.h | 4 | ||||
-rw-r--r-- | modules/vidloop/vidloop.c | 48 | ||||
-rw-r--r-- | modules/x11grab/x11grab.c | 11 |
11 files changed, 115 insertions, 30 deletions
diff --git a/modules/avcapture/avcapture.m b/modules/avcapture/avcapture.m index f276c96..7420cfe 100644 --- a/modules/avcapture/avcapture.m +++ b/modules/avcapture/avcapture.m @@ -234,7 +234,9 @@ didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)conn { const CVImageBufferRef b = CMSampleBufferGetImageBuffer(sampleBuffer); + CMTime ts = CMSampleBufferGetOutputPresentationTimeStamp(sampleBuffer); struct vidframe vf; + uint64_t timestamp; (void)captureOutput; (void)conn; @@ -246,8 +248,10 @@ didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer vidframe_set_pixbuf(&vf, b); + timestamp = CMTimeGetSeconds(ts) * VIDEO_TIMEBASE; + if (vidframe_isvalid(&vf)) - vsrc->frameh(&vf, vsrc->arg); + vsrc->frameh(&vf, timestamp, vsrc->arg); CVPixelBufferUnlockBaseAddress(b, 0); } diff --git a/modules/avformat/avformat.c b/modules/avformat/avformat.c index 62f6fda..af20082 100644 --- a/modules/avformat/avformat.c +++ b/modules/avformat/avformat.c @@ -100,6 +100,8 @@ static void handle_packet(struct vidsrc_st *st, AVPacket *pkt) struct vidframe vf; struct vidsz sz; unsigned i; + int64_t pts; + uint64_t timestamp; if (st->codec) { int got_pict, ret; @@ -147,6 +149,12 @@ static void handle_packet(struct vidsrc_st *st, AVPacket *pkt) return; } + pts = av_frame_get_best_effort_timestamp(frame); + const AVRational time_base = st->time_base; + + /* convert timestamp */ + timestamp = pts * VIDEO_TIMEBASE * time_base.num / time_base.den; + #if LIBAVCODEC_VERSION_INT >= ((53<<16)+(5<<8)+0) switch (frame->format) { @@ -172,7 +180,7 @@ static void handle_packet(struct vidsrc_st *st, AVPacket *pkt) vf.linesize[i] = frame->linesize[i]; } - st->frameh(&vf, st->arg); + st->frameh(&vf, timestamp, st->arg); out: if (frame) { diff --git a/modules/cairo/cairo.c b/modules/cairo/cairo.c index 5e95b52..2422d6b 100644 --- a/modules/cairo/cairo.c +++ b/modules/cairo/cairo.c @@ -129,7 +129,7 @@ static void draw_logo(struct vidsrc_st *st) } -static void process(struct vidsrc_st *st) +static void process(struct vidsrc_st *st, uint64_t timestamp) { struct vidframe f; unsigned xoffs = 2, yoffs = 24; @@ -141,6 +141,9 @@ static void process(struct vidsrc_st *st) draw_text(st, xoffs, yoffs + FONT_SIZE*2, "%u x %u @ %.2f fps", st->size.w, st->size.h, st->prm.fps); + draw_text(st, xoffs, yoffs + FONT_SIZE*3, "Time: %.3f sec", + timestamp / (double)VIDEO_TIMEBASE); + draw_logo(st); st->step += 0.02 / st->prm.fps; @@ -148,29 +151,33 @@ static void process(struct vidsrc_st *st) vidframe_init_buf(&f, VID_FMT_RGB32, &st->size, cairo_image_surface_get_data(st->surface)); - st->frameh(&f, st->arg); + st->frameh(&f, timestamp, st->arg); } static void *read_thread(void *arg) { struct vidsrc_st *st = arg; - uint64_t ts = 0; + uint64_t ts = 0, ts_start; while (st->run) { uint64_t now; + uint64_t timestamp; sys_msleep(2); now = tmr_jiffies(); - if (!ts) - ts = now; + if (!ts) { + ts = ts_start = now; + } if (ts > now) continue; - process(st); + timestamp = (ts - ts_start) * VIDEO_TIMEBASE / 1000; + + process(st, timestamp); ts += 1000/st->prm.fps; } diff --git a/modules/fakevideo/fakevideo.c b/modules/fakevideo/fakevideo.c index 03d0200..53b9c9a 100644 --- a/modules/fakevideo/fakevideo.c +++ b/modules/fakevideo/fakevideo.c @@ -60,12 +60,16 @@ static void *read_thread(void *arg) while (st->run) { + uint64_t timestamp; + if (tmr_jiffies() < ts) { sys_msleep(4); continue; } - st->frameh(st->frame, st->arg); + timestamp = ts * VIDEO_TIMEBASE / 1000; + + st->frameh(st->frame, timestamp, st->arg); ts += (1000/st->fps); } diff --git a/modules/rst/video.c b/modules/rst/video.c index bf59daf..c12ca0a 100644 --- a/modules/rst/video.c +++ b/modules/rst/video.c @@ -62,6 +62,8 @@ static void *video_thread(void *arg) while (st->run) { + uint64_t timestamp; + sys_msleep(4); now = tmr_jiffies(); @@ -69,8 +71,10 @@ static void *video_thread(void *arg) if (ts > now) continue; + timestamp = ts * VIDEO_TIMEBASE / 1000; + pthread_mutex_lock(&st->mutex); - st->frameh(st->frame, st->arg); + st->frameh(st->frame, timestamp, st->arg); pthread_mutex_unlock(&st->mutex); ts += 1000/st->prm.fps; diff --git a/modules/v4l/v4l.c b/modules/v4l/v4l.c index a171021..9f65cf6 100644 --- a/modules/v4l/v4l.c +++ b/modules/v4l/v4l.c @@ -117,13 +117,14 @@ static int v4l_get_win(int fd, int width, int height) } -static void call_frame_handler(struct vidsrc_st *st, uint8_t *buf) +static void call_frame_handler(struct vidsrc_st *st, uint8_t *buf, + uint64_t timestamp) { struct vidframe frame; vidframe_init_buf(&frame, st->fmt, &st->size, buf); - st->frameh(&frame, st->arg); + st->frameh(&frame, timestamp, st->arg); } @@ -133,6 +134,7 @@ static void *read_thread(void *arg) while (st->run) { ssize_t n; + uint64_t timestamp; n = read(st->fd, st->mb->buf, st->mb->size); if ((ssize_t)st->mb->size != n) { @@ -141,7 +143,10 @@ static void *read_thread(void *arg) continue; } - call_frame_handler(st, st->mb->buf); + /* XXX: review this */ + timestamp = tmr_jiffies() * 1000; + + call_frame_handler(st, st->mb->buf, timestamp); } return NULL; diff --git a/modules/v4l2/v4l2.c b/modules/v4l2/v4l2.c index 20ad762..228ec10 100644 --- a/modules/v4l2/v4l2.c +++ b/modules/v4l2/v4l2.c @@ -353,19 +353,22 @@ static int start_capturing(struct vidsrc_st *st) } -static void call_frame_handler(struct vidsrc_st *st, uint8_t *buf) +static void call_frame_handler(struct vidsrc_st *st, uint8_t *buf, + uint64_t timestamp) { struct vidframe frame; vidframe_init_buf(&frame, match_fmt(st->pixfmt), &st->sz, buf); - st->frameh(&frame, st->arg); + st->frameh(&frame, timestamp, st->arg); } static int read_frame(struct vidsrc_st *st) { struct v4l2_buffer buf; + struct timeval ts; + uint64_t timestamp; memset(&buf, 0, sizeof(buf)); @@ -393,7 +396,11 @@ static int read_frame(struct vidsrc_st *st) warning("v4l2: index >= n_buffers\n"); } - call_frame_handler(st, st->buffers[buf.index].start); + ts = buf.timestamp; + timestamp = 1000000U * ts.tv_sec + ts.tv_usec; + timestamp = timestamp * VIDEO_TIMEBASE / 1000000U; + + call_frame_handler(st, st->buffers[buf.index].start, timestamp); if (-1 == xioctl (st->fd, VIDIOC_QBUF, &buf)) { warning("v4l2: VIDIOC_QBUF\n"); diff --git a/modules/vidbridge/src.c b/modules/vidbridge/src.c index 5e7d08a..2ead7cc 100644 --- a/modules/vidbridge/src.c +++ b/modules/vidbridge/src.c @@ -30,11 +30,10 @@ int vidbridge_src_alloc(struct vidsrc_st **stp, const struct vidsrc *vs, struct vidsrc_st *st; int err; (void)ctx; - (void)prm; (void)fmt; (void)errorh; - if (!stp || !size || !frameh) + if (!stp || !prm || !size || !frameh) return EINVAL; st = mem_zalloc(sizeof(*st), destructor); @@ -44,6 +43,7 @@ int vidbridge_src_alloc(struct vidsrc_st **stp, const struct vidsrc *vs, st->vs = vs; st->frameh = frameh; st->arg = arg; + st->fps = prm->fps; err = str_dup(&st->device, dev); if (err) @@ -82,12 +82,15 @@ struct vidsrc_st *vidbridge_src_find(const char *device) } -void vidbridge_src_input(const struct vidsrc_st *st, +void vidbridge_src_input(struct vidsrc_st *st, const struct vidframe *frame) { if (!st || !frame) return; + /* XXX: Read from vidisp input */ + st->timestamp += VIDEO_TIMEBASE / st->fps; + if (st->frameh) - st->frameh((struct vidframe *)frame, st->arg); + st->frameh((struct vidframe *)frame, st->timestamp, st->arg); } diff --git a/modules/vidbridge/vidbridge.h b/modules/vidbridge/vidbridge.h index 0fbf68e..74b2e24 100644 --- a/modules/vidbridge/vidbridge.h +++ b/modules/vidbridge/vidbridge.h @@ -10,6 +10,8 @@ struct vidsrc_st { struct le le; struct vidisp_st *vidisp; + uint64_t timestamp; + double fps; char *device; vidsrc_frame_h *frameh; void *arg; @@ -43,5 +45,5 @@ int vidbridge_src_alloc(struct vidsrc_st **stp, const struct vidsrc *vs, const char *dev, vidsrc_frame_h *frameh, vidsrc_error_h *errorh, void *arg); struct vidsrc_st *vidbridge_src_find(const char *device); -void vidbridge_src_input(const struct vidsrc_st *st, +void vidbridge_src_input(struct vidsrc_st *st, const struct vidframe *frame); diff --git a/modules/vidloop/vidloop.c b/modules/vidloop/vidloop.c index 0c41d72..ca7979b 100644 --- a/modules/vidloop/vidloop.c +++ b/modules/vidloop/vidloop.c @@ -73,6 +73,10 @@ struct video_loop { uint64_t enc_packets; uint64_t disp_frames; } stats; + + bool timestamp_set; + uint64_t timestamp_base; /* lowest timestamp */ + uint64_t timestamp_last; /* most recent timestamp */ }; @@ -189,7 +193,21 @@ static int packet_handler(bool marker, uint64_t rtp_ts, } -static void vidsrc_frame_handler(struct vidframe *frame, void *arg) +static double stream_duration(const struct video_loop *vl) +{ + uint64_t dur; + + if (vl->timestamp_set) + dur = vl->timestamp_last - vl->timestamp_base; + else + dur = 0; + + return video_timestamp_to_seconds(dur); +} + + +static void vidsrc_frame_handler(struct vidframe *frame, uint64_t timestamp, + void *arg) { struct video_loop *vl = arg; struct vidframe *f2 = NULL; @@ -207,6 +225,20 @@ static void vidsrc_frame_handler(struct vidframe *frame, void *arg) vl->src_fmt = frame->fmt; ++vl->stats.src_frames; + /* Timestamp logic */ + if (vl->timestamp_set) { + if (timestamp <= vl->timestamp_base) { + info("vidloop: timestamp wrapped -- reset base\n"); + vl->timestamp_base = timestamp; + } + vl->timestamp_last = timestamp; + } + else { + vl->timestamp_base = timestamp; + vl->timestamp_last = timestamp; + vl->timestamp_set = true; + } + ++vl->stat.frames; if (frame->fmt != (enum vidfmt)vl->cfg.enc_fmt) { @@ -259,8 +291,9 @@ static int print_stats(struct re_printf *pf, const struct video_loop *vl) double real_dur = .0; int err = 0; - if (vl->ts_start) - real_dur = 0.000001 * (double)(vl->ts_last - vl->ts_start); + if (vl->ts_start) { + real_dur = stream_duration(vl); + } err |= re_hprintf(pf, "~~~~~ Videoloop summary: ~~~~~\n"); @@ -279,6 +312,7 @@ static int print_stats(struct re_printf *pf, const struct video_loop *vl) " pixformat %s\n" " frames %llu\n" " framerate %.2f fps (avg %.2f fps)\n" + " duration %.3f sec\n" "\n" , vs->name, @@ -286,7 +320,8 @@ static int print_stats(struct re_printf *pf, const struct video_loop *vl) vl->src_size.w, vl->src_size.h, vidfmt_name(vl->src_fmt), vl->stats.src_frames, - vl->srcprm.fps, avg_fps); + vl->srcprm.fps, avg_fps, + real_dur); } /* Video conversion */ @@ -438,8 +473,9 @@ static void print_status(struct video_loop *vl) { (void)re_fprintf(stdout, "\rstatus:" - " [%s] [%s] fmt=%s intra=%zu " + " %.3f sec [%s] [%s] fmt=%s intra=%zu " " EFPS=%.1f %u kbit/s \r", + stream_duration(vl), vl->vc_enc ? vl->vc_enc->name : "", vl->vc_dec ? vl->vc_dec->name : "", vidfmt_name(vl->cfg.enc_fmt), @@ -478,7 +514,7 @@ static void timeout_bw(void *arg) return; } - tmr_start(&vl->tmr_bw, 2000, timeout_bw, vl); + tmr_start(&vl->tmr_bw, 500, timeout_bw, vl); calc_bitrate(vl); print_status(vl); diff --git a/modules/x11grab/x11grab.c b/modules/x11grab/x11grab.c index d3aa287..36f37c1 100644 --- a/modules/x11grab/x11grab.c +++ b/modules/x11grab/x11grab.c @@ -100,13 +100,14 @@ static inline uint8_t *x11grab_read(struct vidsrc_st *st) } -static void call_frame_handler(struct vidsrc_st *st, uint8_t *buf) +static void call_frame_handler(struct vidsrc_st *st, uint8_t *buf, + uint64_t timestamp) { struct vidframe frame; vidframe_init_buf(&frame, st->pixfmt, &st->size, buf); - st->frameh(&frame, st->arg); + st->frameh(&frame, timestamp, st->arg); } @@ -118,6 +119,8 @@ static void *read_thread(void *arg) while (st->run) { + uint64_t timestamp; + if (tmr_jiffies() < ts) { sys_msleep(4); continue; @@ -127,9 +130,11 @@ static void *read_thread(void *arg) if (!buf) continue; + timestamp = ts * VIDEO_TIMEBASE / 1000; + ts += (1000/st->fps); - call_frame_handler(st, buf); + call_frame_handler(st, buf, timestamp); } return NULL; |