diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/vidloop/vidloop.c | 156 |
1 files changed, 152 insertions, 4 deletions
diff --git a/modules/vidloop/vidloop.c b/modules/vidloop/vidloop.c index 6d6e571..446ca02 100644 --- a/modules/vidloop/vidloop.c +++ b/modules/vidloop/vidloop.c @@ -52,13 +52,27 @@ struct video_loop { struct viddec_state *dec; struct vidisp_st *vidisp; struct vidsrc_st *vsrc; + struct vidsrc_prm srcprm; struct list filtencl; struct list filtdecl; struct vstat stat; struct tmr tmr_bw; + struct vidsz src_size; + struct vidsz disp_size; + enum vidfmt src_fmt; + uint64_t ts_start; /* usec */ + uint64_t ts_last; /* usec */ uint16_t seq; bool need_conv; + bool started; int err; + + struct { + uint64_t src_frames; + uint64_t enc_bytes; + uint64_t enc_packets; + uint64_t disp_frames; + } stats; }; @@ -102,14 +116,20 @@ static int display(struct video_loop *vl, struct vidframe *frame) warning("vidloop: error in video-filters (%m)\n", err); } + /* save the displayed frame info */ + vl->disp_size = frame->size; + ++vl->stats.disp_frames; + /* display frame */ err = vidisp_display(vl->vidisp, "Video Loop", frame); if (err == ENODEV) { info("vidloop: video-display was closed\n"); vl->vidisp = mem_deref(vl->vidisp); vl->err = err; + goto out; } + out: mem_deref(frame_filt); return err; @@ -128,6 +148,9 @@ static int packet_handler(bool marker, uint64_t rtp_ts, int err = 0; (void)rtp_ts; + ++vl->stats.enc_packets; + vl->stats.enc_bytes += (hdr_len + pld_len); + mb = mbuf_alloc(hdr_len + pld_len); if (!mb) return ENOMEM; @@ -171,8 +194,19 @@ static void vidsrc_frame_handler(struct vidframe *frame, void *arg) struct video_loop *vl = arg; struct vidframe *f2 = NULL; struct le *le; + const uint64_t now = tmr_jiffies_usec(); int err = 0; + /* save the timing info */ + if (!gvl->ts_start) + gvl->ts_start = now; + gvl->ts_last = now; + + /* save the video frame info */ + vl->src_size = frame->size; + vl->src_fmt = frame->fmt; + ++vl->stats.src_frames; + ++vl->stat.frames; if (frame->fmt != (enum vidfmt)vl->cfg.enc_fmt) { @@ -206,6 +240,7 @@ static void vidsrc_frame_handler(struct vidframe *frame, void *arg) err = vl->vc_enc->ench(vl->enc, false, frame); if (err) { warning("vidloop: encoder error (%m)\n", err); + goto out; } } else { @@ -213,14 +248,126 @@ static void vidsrc_frame_handler(struct vidframe *frame, void *arg) (void)display(vl, frame); } + out: mem_deref(f2); } +static int print_stats(struct re_printf *pf, const struct video_loop *vl) +{ + const struct config_video *cfg = &vl->cfg; + double real_dur = .0; + int err = 0; + + if (vl->ts_start) + real_dur = 0.000001 * (double)(vl->ts_last - vl->ts_start); + + err |= re_hprintf(pf, "~~~~~ Videoloop summary: ~~~~~\n"); + + /* Source */ + if (vl->vsrc) { + double avg_fps = .0; + + if (vl->stats.src_frames >= 2) + avg_fps = (vl->stats.src_frames-1) / real_dur; + + err |= re_hprintf(pf, + "* Source\n" + " resolution %u x %u (actual %u x %u)\n" + " pixformat %s\n" + " frames %llu\n" + " framerate %.2f fps (avg %.2f fps)\n" + "\n" + , + cfg->width, cfg->height, + vl->src_size.w, vl->src_size.h, + vidfmt_name(vl->src_fmt), + vl->stats.src_frames, + vl->srcprm.fps, avg_fps); + } + + /* Video conversion */ + if (vl->need_conv) { + err |= re_hprintf(pf, + "* Vidconv\n" + " pixformat %s\n" + "\n" + , + vidfmt_name(cfg->enc_fmt)); + } + + /* Filters */ + if (!list_isempty(baresip_vidfiltl())) { + struct le *le; + + err |= re_hprintf(pf, + "* Filters (%u):", + list_count(baresip_vidfiltl())); + + for (le = list_head(baresip_vidfiltl()); le; le = le->next) { + struct vidfilt *vf = le->data; + err |= re_hprintf(pf, " %s", vf->name); + } + err |= re_hprintf(pf, "\n\n"); + } + + /* Encoder */ + if (vl->vc_enc) { + double avg_bitrate; + double avg_pktrate; + + avg_bitrate = 8.0 * (double)vl->stats.enc_bytes / real_dur; + avg_pktrate = (double)vl->stats.enc_packets / real_dur; + + err |= re_hprintf(pf, + "* Encoder\n" + " module %s\n" + " bitrate %u bit/s (avg %.1f bit/s)\n" + " packets %llu (avg %.1f pkt/s)\n" + "\n" + , + vl->vc_enc->name, + cfg->bitrate, avg_bitrate, + vl->stats.enc_packets, avg_pktrate); + } + + /* Decoder */ + if (vl->vc_dec) { + err |= re_hprintf(pf, + "* Decoder\n" + " module %s\n" + " key-frames %zu\n" + "\n" + , + vl->vc_dec->name, + vl->stat.n_intra); + } + + /* Display */ + if (vl->vidisp) { + err |= re_hprintf(pf, + "* Display\n" + " resolution %u x %u\n" + " fullscreen %s\n" + " frames %llu\n" + "\n" + , + vl->disp_size.w, vl->disp_size.h, + cfg->fullscreen ? "Yes" : "No", + vl->stats.disp_frames); + } + + return err; +} + + static void vidloop_destructor(void *arg) { struct video_loop *vl = arg; + if (vl->started) + re_printf("%H\n", print_stats, vl); + tmr_cancel(&vl->tmr_bw); mem_deref(vl->vsrc); mem_deref(vl->enc); @@ -333,19 +480,18 @@ static void timeout_bw(void *arg) static int vsrc_reopen(struct video_loop *vl, const struct vidsz *sz) { - struct vidsrc_prm prm; int err; info("vidloop: %s,%s: open video source: %u x %u at %.2f fps\n", vl->cfg.src_mod, vl->cfg.src_dev, sz->w, sz->h, vl->cfg.fps); - prm.orient = VIDORIENT_PORTRAIT; - prm.fps = vl->cfg.fps; + vl->srcprm.orient = VIDORIENT_PORTRAIT; + vl->srcprm.fps = vl->cfg.fps; vl->vsrc = mem_deref(vl->vsrc); err = vidsrc_alloc(&vl->vsrc, baresip_vidsrcl(), - vl->cfg.src_mod, NULL, &prm, sz, + vl->cfg.src_mod, NULL, &vl->srcprm, sz, NULL, vl->cfg.src_dev, vidsrc_frame_handler, NULL, vl); if (err) { @@ -460,6 +606,8 @@ static int vidloop_start(struct re_printf *pf, void *arg) return err; } + gvl->started = true; + return err; } |