summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorAlfred E. Heggestad <alfred.heggestad@gmail.com>2018-04-08 18:10:30 +0200
committerGitHub <noreply@github.com>2018-04-08 18:10:30 +0200
commit02bb5304bebbf4fdf0206f8628c81dab464a79ac (patch)
tree80c3fda138c96b0dcc76135bbf36134af1c0252b /modules
parentb3bd9972e0633451eecff834297d3cc139d69b4b (diff)
parent09c1b0287be9a7c33dffb11d2bad9286142be3a2 (diff)
vidsrc: add timestamp to the frame API (#368)
Diffstat (limited to 'modules')
-rw-r--r--modules/avcapture/avcapture.m6
-rw-r--r--modules/avformat/avformat.c10
-rw-r--r--modules/cairo/cairo.c19
-rw-r--r--modules/fakevideo/fakevideo.c6
-rw-r--r--modules/rst/video.c6
-rw-r--r--modules/v4l/v4l.c11
-rw-r--r--modules/v4l2/v4l2.c13
-rw-r--r--modules/vidbridge/src.c11
-rw-r--r--modules/vidbridge/vidbridge.h4
-rw-r--r--modules/vidloop/vidloop.c48
-rw-r--r--modules/x11grab/x11grab.c11
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;